llvm.org GIT mirror llvm / b0786ec
[ThinLTO/gold] Perform index-based weak/linkonce resolution Summary: Invoke the weak/linkonce symbol resolution support (already used by libLTO) that operates via the summary index. This ensures prevailing linkonce are kept, by making them weak, and marks preempted copies as available_externally when possible. With this change, the older support for keeping the prevailing linkonce (by changing their symbol resolution) is removed. Reviewers: mehdi_amini Subscribers: llvm-commits, mehdi_amini Differential Revision: http://reviews.llvm.org/D22302 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275474 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 4 years ago
3 changed file(s) with 160 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
0 target triple = "x86_64-unknown-linux-gnu"
1
2 ; Alias are not optimized
3 @linkonceodralias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias
4
5 ; Alias are not optimized
6 @linkoncealias = linkonce alias void (), void ()* @linkoncefuncwithalias
7
8 ; Function with an alias are not optimized
9 define linkonce_odr void @linkonceodrfuncwithalias() #0 {
10 entry:
11 ret void
12 }
13
14 ; Function with an alias are not optimized
15 define linkonce void @linkoncefuncwithalias() #0 {
16 entry:
17 ret void
18 }
19
20 define linkonce_odr void @linkonceodrfunc() #0 {
21 entry:
22 ret void
23 }
24 define linkonce void @linkoncefunc() #0 {
25 entry:
26 ret void
27 }
28 define weak_odr void @weakodrfunc() #0 {
29 entry:
30 ret void
31 }
32 define weak void @weakfunc() #0 {
33 entry:
34 ret void
35 }
36
0 ; RUN: opt -module-summary %s -o %t.o
1 ; RUN: opt -module-summary %p/Inputs/thinlto_weak_resolution.ll -o %t2.o
2
3 ; Verify that prevailing weak for linker symbol is kept.
4 ; Note that gold picks the first copy of a function as the prevailing one,
5 ; so listing %t.o first is sufficient to ensure that its copies are prevailing.
6 ; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold.so \
7 ; RUN: --plugin-opt=thinlto \
8 ; RUN: --plugin-opt=save-temps \
9 ; RUN: -shared \
10 ; RUN: -o %t3.o %t.o %t2.o
11
12 ; RUN: llvm-nm %t3.o | FileCheck %s
13 ; CHECK: weakfunc
14
15 ; All of the preempted functions should have been eliminated (the plugin will
16 ; not link them in).
17 ; RUN: llvm-dis %t2.o.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
18 ; OPT2-NOT: @
19
20 ; RUN: llvm-dis %t.o.opt.bc -o - | FileCheck --check-prefix=OPT %s
21
22 target triple = "x86_64-unknown-linux-gnu"
23
24
25 define i32 @main() #0 {
26 entry:
27 call void @linkonceodralias()
28 call void @linkoncealias()
29 call void @linkonceodrfuncwithalias()
30 call void @linkoncefuncwithalias()
31 call void @linkonceodrfunc()
32 call void @linkoncefunc()
33 call void @weakodrfunc()
34 call void @weakfunc()
35 call void @linkonceodrfuncInSingleModule()
36 ret i32 0
37 }
38
39 ; Alias are resolved
40 ; OPT: @linkonceodralias = weak_odr alias void (), void ()* @linkonceodrfuncwithalias
41 @linkonceodralias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias
42
43 ; Alias are resolved
44 ; OPT: @linkoncealias = weak alias void (), void ()* @linkoncefuncwithalias
45 @linkoncealias = linkonce alias void (), void ()* @linkoncefuncwithalias
46
47 ; Function with an alias are not optimized
48 ; OPT: define linkonce_odr void @linkonceodrfuncwithalias()
49 define linkonce_odr void @linkonceodrfuncwithalias() #0 {
50 entry:
51 ret void
52 }
53
54 ; Function with an alias are not optimized
55 ; OPT: define linkonce void @linkoncefuncwithalias()
56 define linkonce void @linkoncefuncwithalias() #0 {
57 entry:
58 ret void
59 }
60
61 ; OPT: define weak_odr void @linkonceodrfunc()
62 define linkonce_odr void @linkonceodrfunc() #0 {
63 entry:
64 ret void
65 }
66 ; OPT: define weak void @linkoncefunc()
67 define linkonce void @linkoncefunc() #0 {
68 entry:
69 ret void
70 }
71 ; OPT: define weak_odr void @weakodrfunc()
72 define weak_odr void @weakodrfunc() #0 {
73 entry:
74 ret void
75 }
76 ; OPT: define weak void @weakfunc()
77 define weak void @weakfunc() #0 {
78 entry:
79 ret void
80 }
81
82 ; OPT: weak_odr void @linkonceodrfuncInSingleModule()
83 define linkonce_odr void @linkonceodrfuncInSingleModule() #0 {
84 entry:
85 ret void
86 }
734734 if (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP && !Res.IsLinkonceOdr)
735735 Resolution = LDPR_PREVAILING_DEF;
736736
737 // In ThinLTO mode change all prevailing resolutions to LDPR_PREVAILING_DEF.
738 // For ThinLTO the IR files are compiled through the backend independently,
739 // so we need to ensure that any prevailing linkonce copy will be emitted
740 // into the object file by making it weak. Additionally, we can skip the
741 // IRONLY handling for internalization, which isn't performed in ThinLTO
742 // mode currently anyway.
743 if (options::thinlto && (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP ||
744 Resolution == LDPR_PREVAILING_DEF_IRONLY))
745 Resolution = LDPR_PREVAILING_DEF;
746
747737 GV->setUnnamedAddr(Res.UnnamedAddr);
748738 GV->setVisibility(Res.Visibility);
749739
997987 M->setDataLayout(TM->createDataLayout());
998988
999989 if (CombinedIndex) {
990 // Apply summary-based LinkOnce/Weak resolution decisions.
991 thinLTOResolveWeakForLinkerModule(*M, *DefinedGlobals);
992
1000993 // Apply summary-based internalization decisions. Skip if there are no
1001994 // defined globals from the summary since not only is it unnecessary, but
1002995 // if this module did not have a summary section the internalizer will
13211314 // are referenced outside of a single IR module.
13221315 DenseSet Preserve;
13231316
1317 // Keep track of the prevailing copy for each GUID, for use in resolving
1318 // weak linkages.
1319 DenseMap PrevailingCopy;
1320
13241321 ModuleSummaryIndex CombinedIndex;
13251322 uint64_t NextModuleId = 0;
13261323 for (claimed_file &F : Modules) {
13411338
13421339 std::unique_ptr Index = getModuleSummaryIndexForFile(F);
13431340
1341 // Use gold's symbol resolution information to identify symbols referenced
1342 // by more than a single IR module (i.e. referenced by multiple IR modules
1343 // or by a non-IR module). Cross references introduced by importing are
1344 // checked separately via the export lists. Also track the prevailing copy
1345 // for later symbol resolution.
1346 for (auto &Sym : F.syms) {
1347 ld_plugin_symbol_resolution Resolution =
1348 (ld_plugin_symbol_resolution)Sym.resolution;
1349 GlobalValue::GUID SymGUID = GlobalValue::getGUID(Sym.name);
1350 if (Resolution != LDPR_PREVAILING_DEF_IRONLY)
1351 Preserve.insert(SymGUID);
1352
1353 if (Index && (Resolution == LDPR_PREVAILING_DEF ||
1354 Resolution == LDPR_PREVAILING_DEF_IRONLY ||
1355 Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP))
1356 PrevailingCopy[SymGUID] = Index->getGlobalValueSummary(SymGUID);
1357 }
1358
13441359 // Skip files without a module summary.
13451360 if (Index)
13461361 CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
1347
1348 // Use gold's symbol resolution information to identify symbols referenced
1349 // by more than a single IR module (before importing, which is checked
1350 // separately).
1351 for (auto &Sym : F.syms) {
1352 ld_plugin_symbol_resolution Resolution =
1353 (ld_plugin_symbol_resolution)Sym.resolution;
1354 if (Resolution != LDPR_PREVAILING_DEF_IRONLY)
1355 Preserve.insert(GlobalValue::getGUID(Sym.name));
1356 }
13571362 }
13581363
13591364 // Collect for each module the list of function it defines (GUID ->
13661371 StringMap ExportLists(NextModuleId);
13671372 ComputeCrossModuleImport(CombinedIndex, ModuleToDefinedGVSummaries,
13681373 ImportLists, ExportLists);
1374
1375 auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
1376 const auto &Prevailing = PrevailingCopy.find(GUID);
1377 assert(Prevailing != PrevailingCopy.end());
1378 return Prevailing->second == S;
1379 };
13691380
13701381 // Callback for internalization, to prevent internalization of symbols
13711382 // that were not candidates initially, and those that are being imported
13761387 ExportList->second.count(GUID)) ||
13771388 Preserve.count(GUID);
13781389 };
1390
1391 thinLTOResolveWeakForLinkerInIndex(
1392 CombinedIndex, isPrevailing,
1393 [](StringRef ModuleIdentifier, GlobalValue::GUID GUID,
1394 GlobalValue::LinkageTypes NewLinkage) {});
13791395
13801396 // Use global summary-based analysis to identify symbols that can be
13811397 // internalized (because they aren't exported or preserved as per callback).