Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -6147,8 +6147,8 @@ if (!TheIndex) break; if (TheIndex->modulePaths().empty()) - // Does not have any summary emitted. - break; + // We always seed the index with the module. + TheIndex->addModulePath(Buffer->getBufferIdentifier(), 0); if (TheIndex->modulePaths().size() != 1) return error("Don't expect multiple modules defined?"); auto &Hash = TheIndex->modulePaths().begin()->second.second; Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -378,6 +378,7 @@ collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false); MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef(); + errs() << "Load buffer " << MBRef.getBufferIdentifier() << "\n"; ErrorOr> SummaryObjOrErr = object::ModuleSummaryIndexObjectFile::create(MBRef, Conf.DiagHandler); @@ -541,13 +542,15 @@ ImportList, DefinedGlobals, ModuleMap); }; - if (!Cache) + auto ModuleID = MBRef.getBufferIdentifier(); + if (!Cache || !CombinedIndex.modulePaths().count(ModuleID)) + // Cache disabled or no entry for this module in the combined index return RunThinBackend(AddStream); SmallString<40> Key; // The module may be cached, this helps handling it. - computeCacheKey(Key, CombinedIndex, MBRef.getBufferIdentifier(), - ImportList, ExportList, ResolvedODR, DefinedGlobals); + computeCacheKey(Key, CombinedIndex, ModuleID, ImportList, ExportList, + ResolvedODR, DefinedGlobals); if (AddStreamFn CacheAddStream = Cache(Task, Key)) return RunThinBackend(CacheAddStream); Index: lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- lib/LTO/ThinLTOCodeGenerator.cpp +++ lib/LTO/ThinLTOCodeGenerator.cpp @@ -234,6 +234,10 @@ if (CachePath.empty()) return; + if (!Index.modulePaths().count(ModuleID)) + // The module does not have an entry, it can't have a hash at all + return; + // Compute the unique hash for this entry // This is based on the current compiler version, the module itself, the // export list, the hash for every single module in the import list, the @@ -270,9 +274,11 @@ // Include the hash for the preserved symbols. for (auto &Entry : PreservedSymbols) { - if (DefinedFunctions.count(Entry)) + if (DefinedFunctions.count(Entry)) { + errs() << "PreservedSymbols " << Entry << "\n"; Hasher.update( ArrayRef((const uint8_t *)&Entry, sizeof(GlobalValue::GUID))); + } } sys::path::append(EntryPath, CachePath, toHex(Hasher.result())); @@ -502,10 +508,12 @@ return nullptr; } auto Index = (*ObjOrErr)->takeIndex(); - if (CombinedIndex) { - CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId); - } else { - CombinedIndex = std::move(Index); + // If the index is not empty, add it to the combined index + if (Index->begin() != Index->end()) { + if (CombinedIndex) + CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId); + else + CombinedIndex = std::move(Index); } } return CombinedIndex; Index: test/ThinLTO/X86/Inputs/empty_module_with_cache.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/Inputs/empty_module_with_cache.ll @@ -0,0 +1,8 @@ +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + + +define i32 @main() { +entry: + ret i32 0 +} Index: test/ThinLTO/X86/empty_module_with_cache.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/empty_module_with_cache.ll @@ -0,0 +1,17 @@ +; RUN: opt -module-summary %s -o %t.bc +; RUN: opt -module-summary %p/Inputs/empty_module_with_cache.ll -o %t2.bc + +; Verify that enabling caching is working, even if the module is empty +; RUN: rm -Rf %t.cache && mkdir %t.cache +; RUN: llvm-lto -thinlto-action=run %t2.bc %t.bc -exported-symbol=main -thinlto-cache-dir %t.cache +; RUN: ls %t.cache/llvmcache.timestamp +; RUN: ls %t.cache | count 2 + +; Verify that enabling caching is working with llvm-lto2 +; RUN: rm -Rf %t.cache && mkdir %t.cache +; RUN: llvm-lto2 -o %t.o %t2.bc %t.bc -cache-dir %t.cache \ +; RUN: -r=%t2.bc,_main,plx +; RUN: ls %t.cache | count 1 + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" Index: tools/llvm-lto/llvm-lto.cpp =================================================================== --- tools/llvm-lto/llvm-lto.cpp +++ tools/llvm-lto/llvm-lto.cpp @@ -390,6 +390,7 @@ for (auto &ModPath : Index.modulePaths()) { const auto &Filename = ModPath.first(); auto CurrentActivity = "loading file '" + Filename + "'"; + errs() << CurrentActivity << "\n"; auto InputOrErr = MemoryBuffer::getFile(Filename); error(InputOrErr, "error " + CurrentActivity); InputBuffers.push_back(std::move(*InputOrErr)); @@ -490,6 +491,8 @@ } auto CombinedIndex = ThinGenerator.linkCombinedIndex(); + if (!CombinedIndex) + report_fatal_error("ThinLink didn't create an index"); std::error_code EC; raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None); error(EC, "error opening the file '" + OutputFilename + "'");