Index: lld/ELF/LTO.cpp =================================================================== --- lld/ELF/LTO.cpp +++ lld/ELF/LTO.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/WithColor.h" #include #include #include @@ -187,6 +188,38 @@ return c; } +// Check whether cache pruning happens. Add a ThinLTO warning if +// cache_size_bytes or cache_size_files is too small for the current link job. +// The warning recommends the user to consider adjusting --thinlto-cache-policy. +static void +checkCacheCapacity(const std::vector> &files, + CachePruningPolicy Policy) { + // files.size() is greater the number of inputs by one. However, a timestamp + // file (named llvmcache.timestamp) is created and stored in the cache + // directory if --thinlto-cache-policy option is used. llvmcache.timestamp is + // used to prune the old cache file. The cache pruning will happen if (the + // number of inputs+1) is greater than Policy.MaxSizeFiles. Therefore, I used + // files.size() here. + if (Policy.MaxSizeFiles && (files.size() > Policy.MaxSizeFiles)) + WithColor::warning() + << "ThinLTO cache pruning happens since the total number of the files " + "created by the current link job exceeds the maximum number of " + "files; consider adjusting --thinlto-cache-policy.\n"; + + if (Policy.MaxSizeBytes > 0) { + size_t Size = 0; + for (const auto &File : files) + if (File) + Size += File->getBufferSize(); + + if (Size > config->thinLTOCachePolicy.MaxSizeBytes) + WithColor::warning() + << "ThinLTO cache pruning happens since the total size of the cache " + "files consumed by the current link job exceeds maximum cache " + "size; consider adjusting --thinlto-cache-policy.\n"; + } +} + BitcodeCompiler::BitcodeCompiler() { // Initialize indexFile. if (!config->thinLTOIndexOnlyArg.empty()) @@ -341,6 +374,9 @@ }, cache)); + if (!config->thinLTOCacheDir.empty()) + checkCacheCapacity(files, config->thinLTOCachePolicy); + // Emit empty index files for non-indexed files but not in single-module mode. if (config->thinLTOModulesToCompile.empty()) { for (StringRef s : thinIndices) { Index: lld/test/ELF/lto/cache-warnings.ll =================================================================== --- /dev/null +++ lld/test/ELF/lto/cache-warnings.ll @@ -0,0 +1,39 @@ +; REQUIRES: x86 +; NetBSD: noatime mounts currently inhibit 'touch' from updating atime +; UNSUPPORTED: system-netbsd + +; RUN: opt -module-hash -module-summary %s -o %t.o +; RUN: opt -module-hash -module-summary %p/Inputs/cache.ll -o %t2.o + +; Create two cache files in order to test the warnings. +; RUN: rm -Rf %t.cache && mkdir %t.cache +; RUN: touch %t.cache/llvmcache-foo +; RUN: touch %t.cache/llvmcache-bar + +; Check cache policies of the number of files. +; Case 1: A value of 0 disables the number of files based pruning. Therefore, there is no warning. +; RUN: ld.lld -v --thinlto-cache-dir=%t.cache --thinlto-cache-policy=prune_interval=0s:cache_size_files=0 %t2.o %t.o -o %t3 2>&1 | FileCheck %s --implicit-check-not=warning +; Case 2: If the total number of the files created by the current link job is less than the maximum number of files, there is no warning. +; RUN: ld.lld -v --thinlto-cache-dir=%t.cache --thinlto-cache-policy=prune_interval=0s:cache_size_files=3 %t2.o %t.o -o %t3 2>&1 | FileCheck %s --implicit-check-not=warning +; Case 3: If the total number of the files created by the current link job exceeds the maximum number of files, a warning is given. +; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy=prune_interval=0s:cache_size_files=1 %t2.o %t.o -o %t3 2>&1 | FileCheck %s --check-prefix=WARN + + +; Check cache policies of the cache size. +; Case 1: A value of 0 disables the absolute size-based pruning. Therefore, there is no warning. +; RUN: ld.lld -v --thinlto-cache-dir=%t.cache --thinlto-cache-policy=prune_interval=0s:cache_size_bytes=0 %t2.o %t.o -o %t3 2>&1 | FileCheck %s --implicit-check-not=warning +; Case 2: If the total size of the cache files created by the current link job is less than the maximum size for the cache directory in bytes, there is no warning. +; RUN: ld.lld -v --thinlto-cache-dir=%t.cache --thinlto-cache-policy=prune_interval=0s:cache_size_bytes=1355 %t2.o %t.o -o %t3 2>&1 | FileCheck %s --implicit-check-not=warning +; Case 3: If the total size of the cache files created by the current link job exceeds the maximum size for the cache directory in bytes, a warning is given. +; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy=prune_interval=0s:cache_size_bytes=1350 %t2.o %t.o -o %t3 2>&1 | FileCheck %s --check-prefix=WARN + +; WARN: warning: ThinLTO cache pruning happens{{.*}}--thinlto-cache-policy. +; WARN-NOT: warning: ThinLTO cache pruning happens{{.*}}--thinlto-cache-policy. + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @globalfunc() { +entry: + ret void +}