Index: test/tools/gold/X86/Inputs/thinlto_funcimport.ll =================================================================== --- /dev/null +++ test/tools/gold/X86/Inputs/thinlto_funcimport.ll @@ -0,0 +1,33 @@ +; ModuleID = 'global_main.o' +source_filename = "global_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: nounwind uwtable +define i32 @main() local_unnamed_addr #0 !dbg !6 { + %1 = tail call i32 (...) @foo() #2, !dbg !10 + ret i32 %1, !dbg !11 +} + +declare i32 @foo(...) local_unnamed_addr #1 + +attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.1 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "global_main.c", directory: ".") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{!"clang version 3.9.1 "} +!6 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !0, variables: !2) +!7 = !DISubroutineType(types: !8) +!8 = !{!9} +!9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!10 = !DILocation(line: 3, column: 10, scope: !6) +!11 = !DILocation(line: 3, column: 3, scope: !6) Index: test/tools/gold/X86/thinlto_funcimport.ll =================================================================== --- /dev/null +++ test/tools/gold/X86/thinlto_funcimport.ll @@ -0,0 +1,55 @@ +; Do setup work for all below tests: generate bitcode and combined index +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/thinlto_funcimport.ll -o %t2.bc + +; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ +; RUN: --plugin-opt=save-temps \ +; RUN: --plugin-opt=thinlto \ +; RUN: -u main %t1.bc %t2.bc -o %t +; RUN: llvm-nm %t2.bc.thinlto.o | FileCheck %s --check-prefix=NM + +; We shouldn't do any importing at -O0 +; rm -f %t2.bc.3.import.bc +; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ +; RUN: --plugin-opt=save-temps \ +; RUN: --plugin-opt=thinlto \ +; RUN: --plugin-opt=O0 \ +; RUN: -u main %t1.bc %t2.bc -o %t +; RUN: llvm-nm %t2.bc.thinlto.o | FileCheck %s --check-prefix=NM + +; We shouldn't have imported a reference to global variable foobar at -O0. +; NM-NOT: U foobar + +; ModuleID = 'global.o' +source_filename = "global.c" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@foobar = local_unnamed_addr constant i32 10, align 4 + +; Function Attrs: norecurse nounwind readnone uwtable +define i32 @foo() local_unnamed_addr #0 !dbg !10 { + ret i32 1, !dbg !13 +} + +attributes #0 = { norecurse nounwind readnone uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.1 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3) +!1 = !DIFile(filename: "global.c", directory: ".") +!2 = !{} +!3 = !{!4} +!4 = distinct !DIGlobalVariable(name: "foobar", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, variable: i32* @foobar) +!5 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !6) +!6 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{!"clang version 3.9.1 "} +!10 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !11, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !2) +!11 = !DISubroutineType(types: !12) +!12 = !{!6} +!13 = !DILocation(line: 4, column: 3, scope: !10) + Index: tools/gold/gold-plugin.cpp =================================================================== --- tools/gold/gold-plugin.cpp +++ tools/gold/gold-plugin.cpp @@ -1369,35 +1369,39 @@ CombinedIndex.collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); StringMap ImportLists(NextModuleId); - StringMap ExportLists(NextModuleId); - ComputeCrossModuleImport(CombinedIndex, ModuleToDefinedGVSummaries, - ImportLists, ExportLists); - - auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) { - const auto &Prevailing = PrevailingCopy.find(GUID); - assert(Prevailing != PrevailingCopy.end()); - return Prevailing->second == S; - }; - - // Callback for internalization, to prevent internalization of symbols - // that were not candidates initially, and those that are being imported - // (which introduces new cross references). - auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { - const auto &ExportList = ExportLists.find(ModuleIdentifier); - return (ExportList != ExportLists.end() && - ExportList->second.count(GUID)) || - Preserve.count(GUID); - }; - thinLTOResolveWeakForLinkerInIndex( - CombinedIndex, isPrevailing, - [](StringRef ModuleIdentifier, GlobalValue::GUID GUID, - GlobalValue::LinkageTypes NewLinkage) {}); - - // Use global summary-based analysis to identify symbols that can be - // internalized (because they aren't exported or preserved as per callback). - // Changes are made in the index, consumed in the ThinLTO backends. - thinLTOInternalizeAndPromoteInIndex(CombinedIndex, isExported); + if (options::OptLevel > 0) { + StringMap ExportLists(NextModuleId); + ComputeCrossModuleImport(CombinedIndex, ModuleToDefinedGVSummaries, + ImportLists, ExportLists); + + auto isPrevailing = [&](GlobalValue::GUID GUID, + const GlobalValueSummary *S) { + const auto &Prevailing = PrevailingCopy.find(GUID); + assert(Prevailing != PrevailingCopy.end()); + return Prevailing->second == S; + }; + + // Callback for internalization, to prevent internalization of symbols + // that were not candidates initially, and those that are being imported + // (which introduces new cross references). + auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) { + const auto &ExportList = ExportLists.find(ModuleIdentifier); + return (ExportList != ExportLists.end() && + ExportList->second.count(GUID)) || + Preserve.count(GUID); + }; + + thinLTOResolveWeakForLinkerInIndex( + CombinedIndex, isPrevailing, + [](StringRef ModuleIdentifier, GlobalValue::GUID GUID, + GlobalValue::LinkageTypes NewLinkage) {}); + + // Use global summary-based analysis to identify symbols that can be + // internalized (because they aren't exported or preserved as per callback). + // Changes are made in the index, consumed in the ThinLTO backends. + thinLTOInternalizeAndPromoteInIndex(CombinedIndex, isExported); + } if (options::thinlto_emit_imports_files && !options::thinlto_index_only) message(LDPL_WARNING,