llvm.org GIT mirror llvm / cdc5782
[LTO][ThinLTO] Use the linker resolutions to mark global values as dso_local. Now that we have a way to mark GlobalValues as local we can use the symbol resolutions that the linker plugin provides as part of lto/thinlto link step to refine the compilers view on what symbols will end up being local. Differential Revision: https://reviews.llvm.org/D35702 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317374 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Fertile 1 year, 11 months ago
19 changed file(s) with 115 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
147147 /// In combined summary, indicate that the global value is live.
148148 unsigned Live : 1;
149149
150 /// Indicates that the linker resolved the symbol to a definition from
151 /// within the same linkage unit.
152 unsigned DSOLocal : 1;
153
150154 /// Convenience Constructors
151155 explicit GVFlags(GlobalValue::LinkageTypes Linkage,
152 bool NotEligibleToImport, bool Live)
156 bool NotEligibleToImport, bool Live, bool IsLocal)
153157 : Linkage(Linkage), NotEligibleToImport(NotEligibleToImport),
154 Live(Live) {}
158 Live(Live), DSOLocal(IsLocal) {}
155159 };
156160
157161 private:
227231 bool notEligibleToImport() const { return Flags.NotEligibleToImport; }
228232
229233 void setLive(bool Live) { Flags.Live = Live; }
234
235 void setDSOLocal(bool Local) { Flags.DSOLocal = Local; }
236
237 bool isDSOLocal() const { return Flags.DSOLocal; }
230238
231239 /// Flag that this global value cannot be imported.
232240 void setNotEligibleToImport() { Flags.NotEligibleToImport = true; }
134134
135135 struct FunctionSummaryYaml {
136136 unsigned Linkage;
137 bool NotEligibleToImport, Live;
137 bool NotEligibleToImport, Live, IsLocal;
138138 std::vector TypeTests;
139139 std::vector TypeTestAssumeVCalls,
140140 TypeCheckedLoadVCalls;
176176 io.mapOptional("Linkage", summary.Linkage);
177177 io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport);
178178 io.mapOptional("Live", summary.Live);
179 io.mapOptional("Local", summary.IsLocal);
179180 io.mapOptional("TypeTests", summary.TypeTests);
180181 io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
181182 io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls);
210211 Elem.SummaryList.push_back(llvm::make_unique(
211212 GlobalValueSummary::GVFlags(
212213 static_cast(FSum.Linkage),
213 FSum.NotEligibleToImport, FSum.Live),
214 FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal),
214215 0, FunctionSummary::FFlags{}, ArrayRef{},
215216 ArrayRef{}, std::move(FSum.TypeTests),
216217 std::move(FSum.TypeTestAssumeVCalls),
227228 FSums.push_back(FunctionSummaryYaml{
228229 FSum->flags().Linkage,
229230 static_cast(FSum->flags().NotEligibleToImport),
230 static_cast(FSum->flags().Live), FSum->type_tests(),
231 static_cast(FSum->flags().Live),
232 static_cast(FSum->flags().DSOLocal), FSum->type_tests(),
231233 FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(),
232234 FSum->type_test_assume_const_vcalls(),
233235 FSum->type_checked_load_const_vcalls()});
302302 // FIXME: refactor this to use the same code that inliner is using.
303303 F.isVarArg();
304304 GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport,
305 /* Live = */ false);
305 /* Live = */ false, F.isDSOLocal());
306306 FunctionSummary::FFlags FunFlags{
307307 F.hasFnAttribute(Attribute::ReadNone),
308308 F.hasFnAttribute(Attribute::ReadOnly),
328328 findRefEdges(Index, &V, RefEdges, Visited);
329329 bool NonRenamableLocal = isNonRenamableLocal(V);
330330 GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal,
331 /* Live = */ false);
331 /* Live = */ false, V.isDSOLocal());
332332 auto GVarSummary =
333333 llvm::make_unique(Flags, RefEdges.takeVector());
334334 if (NonRenamableLocal)
341341 DenseSet &CantBePromoted) {
342342 bool NonRenamableLocal = isNonRenamableLocal(A);
343343 GlobalValueSummary::GVFlags Flags(A.getLinkage(), NonRenamableLocal,
344 /* Live = */ false);
344 /* Live = */ false, A.isDSOLocal());
345345 auto AS = llvm::make_unique(Flags);
346346 auto *Aliasee = A.getBaseObject();
347347 auto *AliaseeSummary = Index.getGlobalValueSummary(*Aliasee);
409409 assert(GV->isDeclaration() && "Def in module asm already has definition");
410410 GlobalValueSummary::GVFlags GVFlags(GlobalValue::InternalLinkage,
411411 /* NotEligibleToImport = */ true,
412 /* Live = */ true);
412 /* Live = */ true,
413 /* Local */ GV->isDSOLocal());
413414 CantBePromoted.insert(GlobalValue::getGUID(Name));
414415 // Create the appropriate summary type.
415416 if (Function *F = dyn_cast(GV)) {
888888 // to work correctly on earlier versions, we must conservatively treat all
889889 // values as live.
890890 bool Live = (RawFlags & 0x2) || Version < 3;
891 return GlobalValueSummary::GVFlags(Linkage, NotEligibleToImport, Live);
891 bool Local = (RawFlags & 0x4);
892
893 return GlobalValueSummary::GVFlags(Linkage, NotEligibleToImport, Live, Local);
892894 }
893895
894896 static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) {
954954
955955 RawFlags |= Flags.NotEligibleToImport; // bool
956956 RawFlags |= (Flags.Live << 1);
957 RawFlags |= (Flags.DSOLocal << 2);
958
957959 // Linkage don't need to be remapped at that time for the summary. Any future
958960 // change to the getEncodedLinkage() function will need to be taken into
959961 // account here as well.
629629 NonPrevailingComdats.insert(GV->getComdat());
630630 cast(GV)->setComdat(nullptr);
631631 }
632
633 // Set the 'local' flag based on the linker resolution for this symbol.
634 GV->setDSOLocal(Res.FinalDefinitionInLinkageUnit);
632635 }
633636 // Common resolution: collect the maximum size/alignment over all commons.
634637 // We also record if we see an instance of a common as prevailing, so that
642645 CommonRes.Prevailing |= Res.Prevailing;
643646 }
644647
645 // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
646648 }
647649 if (!M.getComdatSymbolTable().empty())
648650 for (GlobalValue &GV : M.global_values())
697699 assert(ResI != ResE);
698700 SymbolResolution Res = *ResI++;
699701
700 if (Res.Prevailing) {
701 if (!Sym.getIRName().empty()) {
702 auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(
703 Sym.getIRName(), GlobalValue::ExternalLinkage, ""));
702 if (!Sym.getIRName().empty()) {
703 auto GUID = GlobalValue::getGUID(GlobalValue::getGlobalIdentifier(
704 Sym.getIRName(), GlobalValue::ExternalLinkage, ""));
705 if (Res.Prevailing) {
704706 ThinLTO.PrevailingModuleForGUID[GUID] = BM.getModuleIdentifier();
705707
706708 // For linker redefined symbols (via --wrap or --defsym) we want to
711713 if (auto S = ThinLTO.CombinedIndex.findSummaryInModule(
712714 GUID, BM.getModuleIdentifier()))
713715 S->setLinkage(GlobalValue::WeakAnyLinkage);
716 }
717
718 // If the linker resolved the symbol to a local definition then mark it
719 // as local in the summary for the module we are adding.
720 if (Res.FinalDefinitionInLinkageUnit) {
721 if (auto S = ThinLTO.CombinedIndex.findSummaryInModule(
722 GUID, BM.getModuleIdentifier())) {
723 S->setDSOLocal(true);
724 }
714725 }
715726 }
716727 }
202202 }
203203
204204 void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
205
206 // Check the summaries to see if the symbol gets resolved to a known local
207 // definition.
208 if (GV.hasName()) {
209 ValueInfo VI = ImportIndex.getValueInfo(GV.getGUID());
210 if (VI) {
211 // Need to check all summaries are local in case of hash collisions.
212 bool IsLocal = VI.getSummaryList().size() &&
213 llvm::all_of(VI.getSummaryList(),
214 [](const std::unique_ptr &Summary) {
215 return Summary->isDSOLocal();
216 });
217 if (IsLocal)
218 GV.setDSOLocal(true);
219 }
220 }
221
205222 bool DoPromote = false;
206223 if (GV.hasLocalLinkage() &&
207224 ((DoPromote = shouldPromoteLocalToGlobal(&GV)) || isPerformingImport())) {
0 ; Bitcode compatibility test for dso_local flag in thin-lto summaries.
1 ; Checks that older bitcode summaries without the dso_local op are still
2 ; properly parsed and don't set GlobalValues as dso_local.
3
4 ; RUN: llvm-dis < %s.bc | FileCheck %s
5 ; RUN: llvm-bcanalyzer -dump %s.bc | FileCheck %s --check-prefix=BCAN
6
7 define void @foo() {
8 ;CHECK-DAG:define void @foo()
9 ret void
10 }
11
12 @bar = global i32 0
13 ;CHECK-DAG: @bar = global i32 0
14
15 @baz = alias i32, i32* @bar
16 ;CHECK-DAG: @bar = global i32 0
17
18 ;BCAN:
19 ;BCAN-NEXT:
20 ;BCAN-NEXT:
21 ;BCAN-NEXT:
1616 ; would clash with the copy from this module.
1717 ; RUN: llvm-dis %t3.0.0.preopt.bc -o - | FileCheck %s
1818 ; CHECK: define internal void @__cxx_global_var_init() section ".text.startup" {
19 ; CHECK: define available_externally void @testglobfunc() section ".text.startup" {
19 ; CHECK: define available_externally dso_local void @testglobfunc() section ".text.startup" {
2020
2121 ; ModuleID = 'comdat-mixed-lto.o'
2222 source_filename = "comdat-mixed-lto.cpp"
6969 ; CHECK-DAG: @a23 = alias i32 (i8*), i32 (i8*)* @f1.2{{$}}
7070 ; CHECK-DAG: @a24 = alias i16, bitcast (i32 (i8*)* @f1.2 to i16*)
7171
72 ; CHECK: define weak_odr i32 @f1(i8*) comdat($c1) {
72 ; CHECK: define weak_odr dso_local i32 @f1(i8*) comdat($c1) {
7373 ; CHECK-NEXT: bb10:
7474 ; CHECK-NEXT: br label %bb11{{$}}
7575 ; CHECK: bb11:
7676 ; CHECK-NEXT: ret i32 42
7777 ; CHECK-NEXT: }
7878
79 ; CHECK: define internal i32 @f1.2(i8* %this) comdat($c2) {
79 ; CHECK: define internal dso_local i32 @f1.2(i8* %this) comdat($c2) {
8080 ; CHECK-NEXT: bb20:
8181 ; CHECK-NEXT: store i8* %this, i8** null
8282 ; CHECK-NEXT: br label %bb21
33 ; RUN: llvm-dis -o - %t.out.0.0.preopt.bc | FileCheck %s
44
55 ; A strong definition should override the common
6 ; CHECK: @x = global i32 42, align 4
6 ; CHECK: @x = dso_local global i32 42, align 4
77
88 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
99 target triple = "x86_64-unknown-linux-gnu"
1717 ; RUN: -r %t2.bc,_boo,pl \
1818 ; RUN: -r %t2.bc,_dead_func,pl \
1919 ; RUN: -r %t2.bc,_another_dead_func,pl
20 ; RUN: llvm-dis < %t.out.0.3.import.bc | FileCheck %s
21 ; RUN: llvm-dis < %t.out.1.3.import.bc | FileCheck %s --check-prefix=CHECK2
20 ; RUN: llvm-dis < %t.out.0.3.import.bc | FileCheck %s --check-prefix=LTO2
21 ; RUN: llvm-dis < %t.out.1.3.import.bc | FileCheck %s --check-prefix=LTO2-CHECK2
2222 ; RUN: llvm-nm %t.out.1 | FileCheck %s --check-prefix=CHECK2-NM
2323
2424 ; RUN: llvm-bcanalyzer -dump %t.out.index.bc | FileCheck %s --check-prefix=COMBINED
2626 ; COMBINED-DAG:
2727 ; Live, Internal
2828 ; COMBINED-DAG:
29 ; Live, External
30 ; COMBINED-DAG:
31 ; COMBINED-DAG:
32 ; COMBINED-DAG:
33 ; (Dead)
34 ; COMBINED-DAG:
35 ; COMBINED-DAG:
36 ; COMBINED-DAG:
29 ; Live, Local, External
30 ; COMBINED-DAG:
31 ; COMBINED-DAG:
32 ; COMBINED-DAG:
33 ; Local, (Dead)
34 ; COMBINED-DAG:
35 ; COMBINED-DAG:
36 ; COMBINED-DAG:
3737
3838 ; Dead-stripping on the index allows to internalize these,
3939 ; and limit the import of @baz thanks to early pruning.
4444 ; CHECK: define internal void @bar_internal()
4545 ; CHECK: define internal void @dead_func() {
4646 ; CHECK-NOT: available_externally {{.*}} @baz()
47 ; LTO2-NOT: available_externally {{.*}} @baz()
48 ; LTO2: @llvm.global_ctors =
49 ; LTO2: define internal void @_GLOBAL__I_a()
50 ; LTO2: define internal dso_local void @bar() {
51 ; LTO2: define internal void @bar_internal()
52 ; LTO2: define internal dso_local void @dead_func() {
53 ; LTO2-NOT: available_externally {{.*}} @baz()
4754
4855 ; Make sure we didn't internalize @boo, which is reachable via
4956 ; llvm.global_ctors
5057 ; CHECK2: define void @boo()
58 ; LTO2-CHECK2: define dso_local void @boo()
5159 ; We should have eventually removed @baz since it was internalized and unused
5260 ; CHECK2-NM-NOT: _baz
5361
7987
8088 ; We can't internalize @dead_func because of the use in the regular LTO
8189 ; partition.
82 ; CHECK-NOTDEAD: define void @dead_func()
90 ; CHECK-NOTDEAD: define dso_local void @dead_func()
8391 ; We also can't eliminate @baz because it is in the regular LTO partition
8492 ; and called from @dead_func.
8593 ; CHECK-NM-NOTDEAD: T _baz
66 ; RUN: -r=%t2.bc,_main,plx \
77 ; RUN: -r=%t2.bc,_foo,l
88 ; RUN: llvm-dis %t.o.1.3.import.bc -o - | FileCheck %s
9 ; CHECK: define available_externally void @foo()
9 ; CHECK: define available_externally dso_local void @foo()
1010
1111 ; We shouldn't do any importing at -O0
1212 ; rm -f %t.o.1.3.import.bc
1616 ; RUN: -r=%t2.bc,_main,plx \
1717 ; RUN: -r=%t2.bc,_foo,l
1818 ; RUN: llvm-dis %t.o.1.3.import.bc -o - | FileCheck %s --check-prefix=CHECKO0
19 ; CHECKO0: declare void @foo(...)
19 ; CHECKO0: declare dso_local void @foo(...)
2020
2121 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2222 target triple = "x86_64-apple-macosx10.11.0"
None ;; RUN: opt -module-summary %s -o %t1.bc
0 ; RUN: opt -module-summary %s -o %t1.bc
11 ; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc
22 ; RUN: llvm-lto -thinlto-action=internalize -thinlto-index %t.index.bc %t1.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=REGULAR
33 ; RUN: llvm-lto -thinlto-action=internalize -thinlto-index %t.index.bc %t1.bc -o - --exported-symbol=foo | llvm-dis -o - | FileCheck %s --check-prefix=INTERNALIZE
66 ; RUN: -r=%t1.bc,_foo,pxl \
77 ; RUN: -r=%t1.bc,_bar,pl \
88 ; RUN: -r=%t1.bc,_linkonce_func,pl
9 ; RUN: llvm-dis < %t.o.0.2.internalize.bc | FileCheck %s --check-prefix=INTERNALIZE
9 ; RUN: llvm-dis < %t.o.0.2.internalize.bc | FileCheck %s --check-prefix=INTERNALIZE2
1010
1111
1212 ; REGULAR: define void @foo
1515 ; INTERNALIZE: define void @foo
1616 ; INTERNALIZE: define internal void @bar
1717 ; INTERNALIZE: define internal void @linkonce_func()
18 ; INTERNALIZE2: define dso_local void @foo
19 ; INTERNALIZE2: define internal dso_local void @bar
20 ; INTERNALIZE2: define internal dso_local void @linkonce_func()
1821
1922 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2023 target triple = "x86_64-apple-macosx10.11.0"
2831 }
2932 define linkonce void @linkonce_func() {
3033 ret void
31 }
34 }
2121
2222 ; We want foo to be imported in the main module!
2323 ; RUN: llvm-dis < %t.o.1.3.import.bc | FileCheck %s --check-prefix=IMPORT
24 ; IMPORT: define available_externally i8** @foo()
24 ; IMPORT: define available_externally dso_local i8** @foo()
2525 define i8 **@foo() {
2626 ret i8 **@b
2727 }
66 ; SUMMARY-NEXT: - Linkage: 0
77 ; SUMMARY-NEXT: NotEligibleToImport: false
88 ; SUMMARY-NEXT: Live: true
9 ; SUMMARY-NEXT: Local: false
910 ; SUMMARY-NEXT: TypeTests: [ 123 ]
1011 ; SUMMARY-NEXT: TypeIdMap:
1112 ; SUMMARY-NEXT: typeid1:
2121 ; RUN: llvm-nm %t3.2 | FileCheck %s --check-prefix=NM
2222 ; NM: _ZL3barv
2323 ; RUN: llvm-dis < %t3.2.2.internalize.bc | FileCheck %s --check-prefix=INTERNALIZE
24 ; INTERNALIZE: define void @_ZL3barv
24 ; INTERNALIZE: define dso_local void @_ZL3barv
2525
2626 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2727 target triple = "x86_64-unknown-linux-gnu"
66 ; SUMMARY-NEXT: - Linkage: 0
77 ; SUMMARY-NEXT: NotEligibleToImport: false
88 ; SUMMARY-NEXT: Live: true
9 ; SUMMARY-NEXT: Local: false
910 ; SUMMARY-NEXT: TypeTestAssumeVCalls:
1011 ; SUMMARY-NEXT: - GUID: 123
1112 ; SUMMARY-NEXT: Offset: 0