Index: include/llvm/LTO/legacy/ThinLTOCodeGenerator.h =================================================================== --- include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -273,8 +273,8 @@ /** * Compute and emit the imported files for module at \p ModulePath. */ - static void emitImports(StringRef ModulePath, StringRef OutputName, - ModuleSummaryIndex &Index); + void emitImports(Module &Module, StringRef OutputName, + ModuleSummaryIndex &Index); /** * Perform cross-module importing for the module identified by @@ -285,8 +285,8 @@ /** * Compute the list of summaries needed for importing into module. */ - static void gatherImportedSummariesForModule( - StringRef ModulePath, ModuleSummaryIndex &Index, + void gatherImportedSummariesForModule( + Module &Module, ModuleSummaryIndex &Index, std::map &ModuleToSummariesForIndex); /** Index: lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- lib/LTO/ThinLTOCodeGenerator.cpp +++ lib/LTO/ThinLTOCodeGenerator.cpp @@ -661,37 +661,52 @@ * Compute the list of summaries needed for importing into module. */ void ThinLTOCodeGenerator::gatherImportedSummariesForModule( - StringRef ModulePath, ModuleSummaryIndex &Index, + Module &TheModule, ModuleSummaryIndex &Index, std::map &ModuleToSummariesForIndex) { auto ModuleCount = Index.modulePaths().size(); + auto ModuleIdentifier = TheModule.getModuleIdentifier(); // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries(ModuleCount); Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + // Convert the preserved symbols set from string to GUID + auto GUIDPreservedSymbols = computeGUIDPreservedSymbols( + PreservedSymbols, Triple(TheModule.getTargetTriple())); + + // Compute "dead" symbols, we don't want to import/export these! + computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols); + // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); ComputeCrossModuleImport(Index, ModuleToDefinedGVSummaries, ImportLists, ExportLists); - llvm::gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, - ImportLists[ModulePath], - ModuleToSummariesForIndex); + llvm::gatherImportedSummariesForModule( + ModuleIdentifier, ModuleToDefinedGVSummaries, + ImportLists[ModuleIdentifier], ModuleToSummariesForIndex); } /** * Emit the list of files needed for importing into module. */ -void ThinLTOCodeGenerator::emitImports(StringRef ModulePath, - StringRef OutputName, +void ThinLTOCodeGenerator::emitImports(Module &TheModule, StringRef OutputName, ModuleSummaryIndex &Index) { auto ModuleCount = Index.modulePaths().size(); + auto ModuleIdentifier = TheModule.getModuleIdentifier(); // Collect for each module the list of function it defines (GUID -> Summary). StringMap ModuleToDefinedGVSummaries(ModuleCount); Index.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); + // Convert the preserved symbols set from string to GUID + auto GUIDPreservedSymbols = computeGUIDPreservedSymbols( + PreservedSymbols, Triple(TheModule.getTargetTriple())); + + // Compute "dead" symbols, we don't want to import/export these! + computeDeadSymbolsInIndex(Index, GUIDPreservedSymbols); + // Generate import/export list StringMap ImportLists(ModuleCount); StringMap ExportLists(ModuleCount); @@ -699,13 +714,13 @@ ExportLists); std::map ModuleToSummariesForIndex; - llvm::gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries, - ImportLists[ModulePath], - ModuleToSummariesForIndex); + llvm::gatherImportedSummariesForModule( + ModuleIdentifier, ModuleToDefinedGVSummaries, + ImportLists[ModuleIdentifier], ModuleToSummariesForIndex); std::error_code EC; - if ((EC = - EmitImportsFiles(ModulePath, OutputName, ModuleToSummariesForIndex))) + if ((EC = EmitImportsFiles(ModuleIdentifier, OutputName, + ModuleToSummariesForIndex))) report_fatal_error(Twine("Failed to open ") + OutputName + " to save imports lists\n"); } Index: lib/Transforms/IPO/FunctionImport.cpp =================================================================== --- lib/Transforms/IPO/FunctionImport.cpp +++ lib/Transforms/IPO/FunctionImport.cpp @@ -293,9 +293,22 @@ LLVM_DEBUG(dbgs() << " ref -> " << VI << "\n"); + // If this is a local variable, make sure we import the copy + // in the caller's module. The only time a local variable can + // share an entry in the index is if there is a local with the same name + // in another module that had the same source file name (in a different + // directory), where each was compiled in their own directory so there + // was not distinguishing path. + auto LocalNotInModule = [&](const GlobalValueSummary *RefSummary) -> bool { + return GlobalValue::isLocalLinkage(RefSummary->linkage()) && + VI.getSummaryList().size() > 1 && + RefSummary->modulePath() != Summary.modulePath(); + }; + for (auto &RefSummary : VI.getSummaryList()) if (isa(RefSummary.get()) && - canImportGlobalVar(RefSummary.get())) { + canImportGlobalVar(RefSummary.get()) && + !LocalNotInModule(RefSummary.get())) { auto ILI = ImportList[RefSummary->modulePath()].insert(VI.getGUID()); // Only update stat if we haven't already imported this variable. if (ILI.second) Index: test/ThinLTO/X86/Inputs/local_name_conflict1.ll =================================================================== --- test/ThinLTO/X86/Inputs/local_name_conflict1.ll +++ test/ThinLTO/X86/Inputs/local_name_conflict1.ll @@ -3,6 +3,8 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" +@baz = internal constant i32 10, align 4 + ; Function Attrs: noinline nounwind uwtable define i32 @a() { entry: @@ -13,5 +15,6 @@ ; Function Attrs: noinline nounwind uwtable define internal i32 @foo() { entry: - ret i32 1 + %0 = load i32, i32* @baz, align 4 + ret i32 %0 } Index: test/ThinLTO/X86/Inputs/local_name_conflict2.ll =================================================================== --- test/ThinLTO/X86/Inputs/local_name_conflict2.ll +++ test/ThinLTO/X86/Inputs/local_name_conflict2.ll @@ -3,6 +3,8 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" +@baz = internal constant i32 10, align 4 + ; Function Attrs: noinline nounwind uwtable define i32 @b() { entry: @@ -13,5 +15,6 @@ ; Function Attrs: noinline nounwind uwtable define internal i32 @foo() { entry: - ret i32 2 + %0 = load i32, i32* @baz, align 4 + ret i32 %0 } Index: test/ThinLTO/X86/Inputs/local_name_conflict_var1.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/Inputs/local_name_conflict_var1.ll @@ -0,0 +1,13 @@ +; ModuleID = 'local_name_conflict_var.o' +source_filename = "local_name_conflict_var.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@baz = internal global i32 10, align 4 + +; Function Attrs: noinline nounwind uwtable +define i32 @a() { +entry: + %0 = load i32, i32* @baz, align 4 + ret i32 %0 +} Index: test/ThinLTO/X86/Inputs/local_name_conflict_var2.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/Inputs/local_name_conflict_var2.ll @@ -0,0 +1,13 @@ +; ModuleID = 'local_name_conflict_var.o' +source_filename = "local_name_conflict_var.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@baz = internal global i32 10, align 4 + +; Function Attrs: noinline nounwind uwtable +define i32 @b() { +entry: + %0 = load i32, i32* @baz, align 4 + ret i32 %0 +} Index: test/ThinLTO/X86/local_name_conflict.ll =================================================================== --- test/ThinLTO/X86/local_name_conflict.ll +++ test/ThinLTO/X86/local_name_conflict.ll @@ -1,5 +1,5 @@ ; Test handling when two files with the same source file name contain -; static functions with the same name (which will have the same GUID +; static functions/variables with the same name (which will have the same GUID ; in the combined index. ; Do setup work for all below tests: generate bitcode and combined index @@ -8,19 +8,22 @@ ; RUN: opt -module-summary -module-hash %p/Inputs/local_name_conflict2.ll -o %t3.bc ; RUN: llvm-lto -thinlto-action=thinlink -o %t4.bc %t.bc %t2.bc %t3.bc -; This module will import b() which should cause the copy of foo from +; This module will import b() which should cause the copy of foo and baz from ; that module (%t3.bc) to be imported. Check that the imported reference's ; promoted name matches the imported copy. ; RUN: llvm-lto -thinlto-action=import %t.bc -thinlto-index=%t4.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORT -; IMPORT: call i32 @foo.llvm.[[HASH:[0-9]+]] +; IMPORT: @baz.llvm.[[HASH:[0-9]+]] = available_externally hidden constant i32 10, align 4 +; IMPORT: call i32 @foo.llvm.[[HASH]] ; IMPORT: define available_externally hidden i32 @foo.llvm.[[HASH]]() ; The copy in %t2.bc should not be exported/promoted/renamed ; RUN: llvm-lto -thinlto-action=promote %t2.bc -thinlto-index=%t4.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=NOEXPORTSTATIC +; NOEXPORTSTATIC: @baz = internal constant i32 10, align 4 ; NOEXPORTSTATIC: define internal i32 @foo() ; Make sure foo is promoted and renamed without complaint in %t3.bc. ; RUN: llvm-lto -thinlto-action=promote %t3.bc -thinlto-index=%t4.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=EXPORTSTATIC +; EXPORTSTATIC: @baz.llvm.{{.*}} = hidden constant i32 10, align 4 ; EXPORTSTATIC: define hidden i32 @foo.llvm. ; ModuleID = 'local_name_conflict_main.o' Index: test/ThinLTO/X86/local_name_conflict_var.ll =================================================================== --- /dev/null +++ test/ThinLTO/X86/local_name_conflict_var.ll @@ -0,0 +1,32 @@ +; Test handling when two files with the same source file name contain +; static read only variables with the same name (which will have the same GUID +; in the combined index). + +; Do setup work for all below tests: generate bitcode and combined index +; RUN: opt -module-summary -module-hash %s -o %t.bc +; RUN: opt -module-summary -module-hash %p/Inputs/local_name_conflict_var1.ll -o %t2.bc +; RUN: opt -module-summary -module-hash %p/Inputs/local_name_conflict_var2.ll -o %t3.bc +; RUN: llvm-lto -thinlto-action=thinlink -o %t4.bc %t.bc %t2.bc %t3.bc + +; This module will import a() and b() which should cause the read only copy +; of baz from each of those modules to be imported. Check that the both are +; imported as local copies. +; RUN: llvm-lto -thinlto-action=import -exported-symbol=main %t.bc -thinlto-index=%t4.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=IMPORT +; IMPORT: @baz.llvm.{{.*}} = internal global i32 10 +; IMPORT: @baz.llvm.{{.*}} = internal global i32 10 + +; ModuleID = 'local_name_conflict_var_main.o' +source_filename = "local_name_conflict_var_main.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: noinline nounwind uwtable +define i32 @main() { +entry: + %call1 = call i32 (...) @a() + %call2 = call i32 (...) @b() + ret i32 0 +} + +declare i32 @a(...) +declare i32 @b(...) Index: tools/llvm-lto/llvm-lto.cpp =================================================================== --- tools/llvm-lto/llvm-lto.cpp +++ tools/llvm-lto/llvm-lto.cpp @@ -562,11 +562,14 @@ auto Index = loadCombinedIndex(); for (auto &Filename : InputFilenames) { + LLVMContext Ctx; + auto TheModule = loadModule(Filename, Ctx); + // Build a map of module to the GUIDs and summary objects that should // be written to its index. std::map ModuleToSummariesForIndex; - ThinLTOCodeGenerator::gatherImportedSummariesForModule( - Filename, *Index, ModuleToSummariesForIndex); + ThinGenerator.gatherImportedSummariesForModule(*TheModule, *Index, + ModuleToSummariesForIndex); std::string OutputName = OutputFilename; if (OutputName.empty()) { @@ -594,12 +597,14 @@ auto Index = loadCombinedIndex(); for (auto &Filename : InputFilenames) { + LLVMContext Ctx; + auto TheModule = loadModule(Filename, Ctx); std::string OutputName = OutputFilename; if (OutputName.empty()) { OutputName = Filename + ".imports"; } OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix); - ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index); + ThinGenerator.emitImports(*TheModule, OutputName, *Index); } }