diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -174,22 +174,35 @@ // imported symbols for each module may affect code generation and is // sensitive to link order, so include that as well. using ImportMapIteratorTy = FunctionImporter::ImportMapTy::const_iterator; - std::vector ImportModulesVector; + struct ImportModule { + ImportMapIteratorTy ModIt; + uint64_t ModId; + + StringRef getIdentifier() const { return ModIt->getKey(); } + const FunctionImporter::FunctionsToImportTy &getFunctions() const { + return ModIt->second; + } + }; + + std::vector ImportModulesVector; ImportModulesVector.reserve(ImportList.size()); for (ImportMapIteratorTy It = ImportList.begin(); It != ImportList.end(); ++It) { - ImportModulesVector.push_back(It); + ImportModulesVector.push_back({It, Index.getModuleId(It->getKey())}); } + // Order using moduleId integer which is based on the order the module was + // added. llvm::sort(ImportModulesVector, - [](const ImportMapIteratorTy &Lhs, const ImportMapIteratorTy &Rhs) - -> bool { return Lhs->getKey() < Rhs->getKey(); }); - for (const ImportMapIteratorTy &EntryIt : ImportModulesVector) { - auto ModHash = Index.getModuleHash(EntryIt->first()); + [](const ImportModule &Lhs, const ImportModule &Rhs) -> bool { + return Lhs.ModId < Rhs.ModId; + }); + for (const ImportModule &Entry : ImportModulesVector) { + auto ModHash = Index.getModuleHash(Entry.getIdentifier()); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); - AddUint64(EntryIt->second.size()); - for (auto &Fn : EntryIt->second) + AddUint64(Entry.getFunctions().size()); + for (auto &Fn : Entry.getFunctions()) AddUint64(Fn); } @@ -259,9 +272,10 @@ // Imported functions may introduce new uses of type identifier resolutions, // so we need to collect their used resolutions as well. - for (auto &ImpM : ImportList) - for (auto &ImpF : ImpM.second) { - GlobalValueSummary *S = Index.findSummaryInModule(ImpF, ImpM.first()); + for (const ImportModule &ImpM : ImportModulesVector) + for (auto &ImpF : ImpM.getFunctions()) { + GlobalValueSummary *S = + Index.findSummaryInModule(ImpF, ImpM.getIdentifier()); AddUsedThings(S); // If this is an alias, we also care about any types/etc. that the aliasee // may reference. diff --git a/llvm/test/ThinLTO/X86/cache-decoupled-from-filenames.ll b/llvm/test/ThinLTO/X86/cache-decoupled-from-filenames.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ThinLTO/X86/cache-decoupled-from-filenames.ll @@ -0,0 +1,27 @@ +; RUN: rm -rf %t && mkdir -p %t/1 %t/2 %t/3 %t/4 +; RUN: opt -module-hash -module-summary %s -o %t/t.bc +; RUN: opt -module-hash -module-summary %S/Inputs/cache-import-lists1.ll -o %t/1/a.bc +; RUN: opt -module-hash -module-summary %S/Inputs/cache-import-lists2.ll -o %t/2/b.bc + +; Tests that the hash for t is insensitive to the bitcode module filenames. + +; RUN: rm -rf %t/cache +; RUN: llvm-lto2 run -cache-dir %t/cache -o %t.o %t/t.bc %t/1/a.bc %t/2/b.bc -r=%t/t.bc,main,plx -r=%t/t.bc,f1,lx -r=%t/t.bc,f2,lx -r=%t/1/a.bc,f1,plx -r=%t/1/a.bc,linkonce_odr,plx -r=%t/2/b.bc,f2,plx -r=%t/2/b.bc,linkonce_odr,lx +; RUN: ls %t/cache | count 3 + +; RUN: cp %t/1/a.bc %t/4/d.bc +; RUN: cp %t/2/b.bc %t/3/k.bc +; RUN: llvm-lto2 run -cache-dir %t/cache -o %t.o %t/t.bc %t/4/d.bc %t/3/k.bc -r=%t/t.bc,main,plx -r=%t/t.bc,f1,lx -r=%t/t.bc,f2,lx -r=%t/4/d.bc,f1,plx -r=%t/4/d.bc,linkonce_odr,plx -r=%t/3/k.bc,f2,plx -r=%t/3/k.bc,linkonce_odr,lx +; RUN: ls %t/cache | count 3 + +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 @main() { + call void @f1() + call void @f2() + ret void +} + +declare void @f1() +declare void @f2()