diff options
| -rw-r--r-- | clang/docs/ThinLTO.rst | 16 | ||||
| -rw-r--r-- | lld/COFF/Config.h | 6 | ||||
| -rw-r--r-- | lld/COFF/Driver.cpp | 10 | ||||
| -rw-r--r-- | lld/COFF/LTO.cpp | 32 | ||||
| -rw-r--r-- | lld/COFF/LTO.h | 1 | ||||
| -rw-r--r-- | lld/COFF/Options.td | 2 | ||||
| -rw-r--r-- | lld/test/COFF/Inputs/lto-cache.ll | 10 | ||||
| -rw-r--r-- | lld/test/COFF/lto-cache.ll | 21 |
8 files changed, 87 insertions, 11 deletions
diff --git a/clang/docs/ThinLTO.rst b/clang/docs/ThinLTO.rst index 31fff51a61e..71b1d5d6330 100644 --- a/clang/docs/ThinLTO.rst +++ b/clang/docs/ThinLTO.rst @@ -119,23 +119,27 @@ Incremental ThinLTO supports fast incremental builds through the use of a cache, which currently must be enabled through a linker option. -- gold (as of LLVM r279883): +- gold (as of LLVM 4.0): ``-Wl,-plugin-opt,cache-dir=/path/to/cache`` - ld64 (support in clang 3.9 and Xcode 8): ``-Wl,-cache_path_lto,/path/to/cache`` -- lld (as of LLVM r296702): +- ELF lld (as of LLVM 5.0): ``-Wl,--thinlto-cache-dir=/path/to/cache`` +- COFF lld (as of LLVM 6.0): + ``/lldltocache:/path/to/cache`` Cache Pruning ------------- To help keep the size of the cache under control, ThinLTO supports cache -pruning. Cache pruning is supported with ld64 and ELF lld, but currently only -ELF lld allows you to control the policy with a policy string. The cache -policy must be specified with a linker option. +pruning. Cache pruning is supported with ld64 and ELF and COFF lld, but +currently only ELF and COFF lld allow you to control the policy with a +policy string. The cache policy must be specified with a linker option. -- ELF lld (as of LLVM r298036): +- ELF lld (as of LLVM 5.0): ``-Wl,--thinlto-cache-policy,POLICY`` +- COFF lld (as of LLVM 6.0): + ``/lldltocachepolicy:POLICY`` A policy string is a series of key-value pairs separated by ``:`` characters. Possible key-value pairs are: diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 5895cb06310..215dad91d97 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -12,6 +12,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/COFF.h" +#include "llvm/Support/CachePruning.h" #include <cstdint> #include <map> #include <set> @@ -123,6 +124,11 @@ struct Configuration { // Used for /opt:lldltopartitions=N unsigned LTOPartitions = 1; + // Used for /opt:lldltocache=path + StringRef LTOCache; + // Used for /opt:lldltocachepolicy=policy + llvm::CachePruningPolicy LTOCachePolicy; + // Used for /merge:from=to (e.g. /merge:.rdata=.text) std::map<StringRef, StringRef> Merge; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 6cebb91c953..e07bdac46db 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -877,6 +877,16 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { if (Args.hasArg(OPT_lldsavetemps)) Config->SaveTemps = true; + // Handle /lldltocache + if (auto *Arg = Args.getLastArg(OPT_lldltocache)) + Config->LTOCache = Arg->getValue(); + + // Handle /lldsavecachepolicy + if (auto *Arg = Args.getLastArg(OPT_lldltocachepolicy)) + Config->LTOCachePolicy = check( + parseCachePruningPolicy(Arg->getValue()), + Twine("/lldltocachepolicy: invalid cache policy: ") + Arg->getValue()); + // Handle /failifmismatch for (auto *Arg : Args.filtered(OPT_failifmismatch)) checkFailIfMismatch(Arg->getValue()); diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp index 6883b3b4c2c..1e62908baa4 100644 --- a/lld/COFF/LTO.cpp +++ b/lld/COFF/LTO.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/LTO/Caching.h" #include "llvm/LTO/Config.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/SymbolicFile.h" @@ -118,11 +119,27 @@ void BitcodeCompiler::add(BitcodeFile &F) { std::vector<StringRef> BitcodeCompiler::compile() { unsigned MaxTasks = LTOObj->getMaxTasks(); Buff.resize(MaxTasks); - - checkError(LTOObj->run([&](size_t Task) { - return llvm::make_unique<lto::NativeObjectStream>( - llvm::make_unique<raw_svector_ostream>(Buff[Task])); - })); + Files.resize(MaxTasks); + + // The /lldltocache option specifies the path to a directory in which to cache + // native object files for ThinLTO incremental builds. If a path was + // specified, configure LTO to use it as the cache directory. + lto::NativeObjectCache Cache; + if (!Config->LTOCache.empty()) + Cache = check( + lto::localCache(Config->LTOCache, + [&](size_t Task, std::unique_ptr<MemoryBuffer> MB, + StringRef Path) { Files[Task] = std::move(MB); })); + + checkError(LTOObj->run( + [&](size_t Task) { + return llvm::make_unique<lto::NativeObjectStream>( + llvm::make_unique<raw_svector_ostream>(Buff[Task])); + }, + Cache)); + + if (!Config->LTOCache.empty()) + pruneCache(Config->LTOCache, Config->LTOCachePolicy); std::vector<StringRef> Ret; for (unsigned I = 0; I != MaxTasks; ++I) { @@ -136,5 +153,10 @@ std::vector<StringRef> BitcodeCompiler::compile() { } Ret.emplace_back(Buff[I].data(), Buff[I].size()); } + + for (std::unique_ptr<MemoryBuffer> &File : Files) + if (File) + Ret.push_back(File->getBuffer()); + return Ret; } diff --git a/lld/COFF/LTO.h b/lld/COFF/LTO.h index 194a4cce8ad..a98dc761f35 100644 --- a/lld/COFF/LTO.h +++ b/lld/COFF/LTO.h @@ -49,6 +49,7 @@ public: private: std::unique_ptr<llvm::lto::LTO> LTOObj; std::vector<SmallString<0>> Buff; + std::vector<std::unique_ptr<MemoryBuffer>> Files; }; } } diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index 23dc5f41e24..0a6472cb591 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -31,6 +31,8 @@ def heap : P<"heap", "Size of the heap">; def implib : P<"implib", "Import library name">; def libpath : P<"libpath", "Additional library search path">; def linkrepro : P<"linkrepro", "Dump linker invocation and input files for debugging">; +def lldltocache : P<"lldltocache", "Path to ThinLTO cached object file directory">; +def lldltocachepolicy : P<"lldltocachepolicy", "Pruning policy for the ThinLTO cache">; def lldsavetemps : F<"lldsavetemps">, HelpText<"Save temporary files instead of deleting them">; def machine : P<"machine", "Specify target platform">; diff --git a/lld/test/COFF/Inputs/lto-cache.ll b/lld/test/COFF/Inputs/lto-cache.ll new file mode 100644 index 00000000000..acbee7be014 --- /dev/null +++ b/lld/test/COFF/Inputs/lto-cache.ll @@ -0,0 +1,10 @@ +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define i32 @main() { +entry: + call void (...) @globalfunc() + ret i32 0 +} + +declare void @globalfunc(...) diff --git a/lld/test/COFF/lto-cache.ll b/lld/test/COFF/lto-cache.ll new file mode 100644 index 00000000000..ad1a3b71f19 --- /dev/null +++ b/lld/test/COFF/lto-cache.ll @@ -0,0 +1,21 @@ +; REQUIRES: x86 + +; RUN: opt -module-hash -module-summary %s -o %t.o +; RUN: opt -module-hash -module-summary %p/Inputs/lto-cache.ll -o %t2.o + +; RUN: rm -Rf %t.cache && mkdir %t.cache +; Create two files that would be removed by cache pruning due to age. +; We should only remove files matching the pattern "llvmcache-*". +; RUN: touch -t 197001011200 %t.cache/llvmcache-foo %t.cache/foo +; RUN: lld-link /lldltocache:%t.cache /lldltocachepolicy:prune_after=1h /out:%t3 /entry:main %t2.o %t.o + +; Two cached objects, plus a timestamp file and "foo", minus the file we removed. +; RUN: ls %t.cache | count 4 + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define void @globalfunc() #0 { +entry: + ret void +} |

