Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -86,6 +86,7 @@ llvm::StringRef OptRemarksFilename; llvm::StringRef SoName; llvm::StringRef Sysroot; + llvm::StringRef ThinLTOCacheDir; std::string RPath; std::vector VersionDefinitions; std::vector AuxiliaryList; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -583,6 +583,7 @@ Config->Sysroot = getString(Args, OPT_sysroot); Config->Target1Rel = getArg(Args, OPT_target1_rel, OPT_target1_abs, false); Config->Target2 = getTarget2(Args); + Config->ThinLTOCacheDir = getString(Args, OPT_thinlto_cache_dir); Config->ThinLTOJobs = getInteger(Args, OPT_thinlto_jobs, -1u); Config->Threads = getArg(Args, OPT_threads, OPT_no_threads, true); Config->Trace = Args.hasArg(OPT_trace); Index: lld/trunk/ELF/LTO.h =================================================================== --- lld/trunk/ELF/LTO.h +++ lld/trunk/ELF/LTO.h @@ -49,6 +49,7 @@ private: std::unique_ptr LTOObj; std::vector> Buff; + std::vector> Files; }; } } Index: lld/trunk/ELF/LTO.cpp =================================================================== --- lld/trunk/ELF/LTO.cpp +++ lld/trunk/ELF/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" @@ -142,11 +143,24 @@ std::vector Ret; unsigned MaxTasks = LTOObj->getMaxTasks(); Buff.resize(MaxTasks); + Files.resize(MaxTasks); - checkError(LTOObj->run([&](size_t Task) { - return llvm::make_unique( - llvm::make_unique(Buff[Task])); - })); + // The --thinlto-cache-dir 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->ThinLTOCacheDir.empty()) + Cache = lto::localCache(Config->ThinLTOCacheDir, + [&](size_t Task, StringRef Path) { + Files[Task] = check(MemoryBuffer::getFile(Path)); + }); + + checkError(LTOObj->run( + [&](size_t Task) { + return llvm::make_unique( + llvm::make_unique(Buff[Task])); + }, + Cache)); for (unsigned I = 0; I != MaxTasks; ++I) { if (Buff[I].empty()) @@ -160,5 +174,10 @@ InputFile *Obj = createObjectFile(MemoryBufferRef(Buff[I], "lto.tmp")); Ret.push_back(Obj); } + + for (std::unique_ptr &File : Files) + if (File) + Ret.push_back(createObjectFile(*File)); + return Ret; } Index: lld/trunk/ELF/Options.td =================================================================== --- lld/trunk/ELF/Options.td +++ lld/trunk/ELF/Options.td @@ -392,4 +392,6 @@ def opt_remarks_with_hotness: F<"opt-remarks-with-hotness">, HelpText<"Include hotness informations in the optimization remarks file">; def save_temps: F<"save-temps">; +def thinlto_cache_dir: J<"thinlto-cache-dir=">, + HelpText<"Path to ThinLTO cached object file directory">; def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; Index: lld/trunk/test/ELF/lto/Inputs/cache.ll =================================================================== --- lld/trunk/test/ELF/lto/Inputs/cache.ll +++ lld/trunk/test/ELF/lto/Inputs/cache.ll @@ -0,0 +1,10 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @main() { +entry: + call void (...) @globalfunc() + ret i32 0 +} + +declare void @globalfunc(...) Index: lld/trunk/test/ELF/lto/cache.ll =================================================================== --- lld/trunk/test/ELF/lto/cache.ll +++ lld/trunk/test/ELF/lto/cache.ll @@ -0,0 +1,15 @@ +; RUN: opt -module-hash -module-summary %s -o %t.o +; RUN: opt -module-hash -module-summary %p/Inputs/cache.ll -o %t2.o + +; RUN: rm -Rf %t.cache && mkdir %t.cache +; RUN: ld.lld --thinlto-cache-dir=%t.cache -o %t3.o %t2.o %t.o + +; RUN: ls %t.cache | count 2 + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @globalfunc() #0 { +entry: + ret void +}