llvm.org GIT mirror llvm / dcf1ffe
[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. Originally commited as r317374, but reverted in r317395 to update some missed tests. Differential Revision: https://reviews.llvm.org/D35702 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317408 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Fertile 1 year, 11 months ago
28 changed file(s) with 137 addition(s) and 58 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
88 ; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold.so \
99 ; RUN: --plugin-opt=save-temps \
1010 ; RUN: --plugin-opt=thinlto -o %t2 %t.o
11 ; RUN: llvm-dis < %t.o.5.precodegen.bc | FileCheck %s
11 ; RUN: llvm-dis < %t.o.5.precodegen.bc | FileCheck --check-prefix=CHECKTHIN %s
1212
1313 ; Check that foo is not internalized
1414 ; CHECK: define void @foo
15 ; CHECKTHIN: define dso_local void @foo
1516
1617 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
1718 target triple = "x86_64-unknown-linux-gnu"
1010 ret void
1111 }
1212
13 ; CHECK: define internal void @g() {
13 ; CHECK: define internal dso_local void @g() {
1414 define hidden void @g() {
1515 ret void
1616 }
4545 ; RUN: llvm-dis %t3.o -o - | FileCheck --check-prefix=MIXED %s
4646
4747 ; Mixed ELF and IR. We keep ours as common so the linker will finish the merge.
48 ; MIXED: @a = common global i16 0, align 8
48 ; MIXED: @a = common dso_local global i16 0, align 8
4747
4848 @g8 = external global i32
4949
50 ; CHECK-DAG: define internal void @f1()
50 ; CHECK-DAG: define internal dso_local void @f1()
5151 ; OPT2-NOT: @f1
5252 define hidden void @f1() {
5353 ret void
5454 }
5555
56 ; CHECK-DAG: define hidden void @f2()
57 ; OPT-DAG: define hidden void @f2()
56 ; CHECK-DAG: define dso_local hidden void @f2()
57 ; OPT-DAG: define dso_local hidden void @f2()
5858 define hidden void @f2() {
5959 ret void
6060 }
3939 target triple = "x86_64-unknown-linux-gnu"
4040
4141 ; We should not internalize @var_with_section due to section
42 ; CHECK-DAG: @var_with_section = global i32 0, section "some_section"
42 ; CHECK-DAG: @var_with_section = dso_local global i32 0, section "some_section"
4343 @var_with_section = global i32 0, section "some_section"
4444
4545 ; Confirm via a variable with a non-C identifier section that we are getting
4646 ; the expected internalization.
47 ; CHECK-DAG: @var_with_nonC_section = internal global i32 0, section ".nonCsection"
47 ; CHECK-DAG: @var_with_nonC_section = internal dso_local global i32 0, section ".nonCsection"
4848 @var_with_nonC_section = global i32 0, section ".nonCsection"
4949
5050 ; We should not internalize @deadfunc_with_section due to section
51 ; CHECK-DAG: define void @deadfunc_with_section() section "some_other_section"
51 ; CHECK-DAG: define dso_local void @deadfunc_with_section() section "some_other_section"
5252 define void @deadfunc_with_section() section "some_other_section" {
5353 call void @deadfunc2_called_from_section()
5454 ret void
5656
5757 ; Confirm via a function with a non-C identifier section that we are getting
5858 ; the expected internalization.
59 ; CHECK-DAG: define internal void @deadfunc_with_nonC_section() section ".nonCsection"
59 ; CHECK-DAG: define internal dso_local void @deadfunc_with_nonC_section() section ".nonCsection"
6060 define void @deadfunc_with_nonC_section() section ".nonCsection" {
6161 call void @deadfunc2_called_from_nonC_section()
6262 ret void
6464
6565 ; In RegularLTO mode, where we have combined all the IR,
6666 ; @deadfunc2_called_from_section can be internalized.
67 ; CHECK2-REGULARLTO: define internal void @deadfunc2_called_from_section
67 ; CHECK2-REGULARLTO: define internal dso_local void @deadfunc2_called_from_section
6868 ; In ThinLTO mode, we can't internalize it as it needs to be preserved
6969 ; (due to the access from @deadfunc_with_section which must be preserved), and
7070 ; can't be internalized since the reference is from a different module.
71 ; CHECK2-THINLTO: define void @deadfunc2_called_from_section
71 ; CHECK2-THINLTO: define dso_local void @deadfunc2_called_from_section
7272 declare void @deadfunc2_called_from_section()
7373
7474 ; Confirm when called from a function with a non-C identifier section that we
7575 ; are getting the expected internalization.
76 ; CHECK2-REGULARLTO: define internal void @deadfunc2_called_from_nonC_section
77 ; CHECK2-THINLTO: define internal void @deadfunc2_called_from_nonC_section
76 ; CHECK2-REGULARLTO: define internal dso_local void @deadfunc2_called_from_nonC_section
77 ; CHECK2-THINLTO: define internal dso_local void @deadfunc2_called_from_nonC_section
7878 declare void @deadfunc2_called_from_nonC_section()
88 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
99 target triple = "x86_64-unknown-linux-gnu"
1010
11 ; CHECK-BC0: define void @foo
12 ; CHECK-BC0: declare void @bar
11 ; CHECK-BC0: define dso_local void @foo
12 ; CHECK-BC0: declare dso_local void @bar
1313 ; CHECK0-NOT: bar
1414 ; CHECK0: T foo
1515 ; CHECK0-NOT: bar
1818 ret void
1919 }
2020
21 ; CHECK-BC1: declare void @foo
22 ; CHECK-BC1: define void @bar
21 ; CHECK-BC1: declare dso_local void @foo
22 ; CHECK-BC1: define dso_local void @bar
2323 ; CHECK1-NOT: foo
2424 ; CHECK1: T bar
2525 ; CHECK1-NOT: foo
2020 ; confirm the weak linkage directly in the saved opt bitcode files.
2121 ; CHECK-NOT: U f
2222 ; OPT-NOT: @f()
23 ; OPT2: define weak_odr hidden void @f()
23 ; OPT2: define weak_odr dso_local hidden void @f()
2424
2525 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2626 target triple = "x86_64-unknown-linux-gnu"
2323 ; copy of f() (and didn't simply convert to available_externally, which
2424 ; would incorrectly enable inlining).
2525 ; RUN: llvm-dis %t2.o.1.promote.bc -o - | FileCheck %s
26 ; CHECK: declare i32 @f()
26 ; CHECK: declare dso_local i32 @f()
2727
2828 ; ModuleID = 'thinlto_weak_library.c'
2929 source_filename = "thinlto_weak_library.c"
1616 ; CHECK-NEXT: STV_PROTECTED
1717 ; CHECK-NEXT: ]
1818
19 ; IR: define void @foo
19 ; IR: define dso_local void @foo
2020
2121 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2222 target triple = "x86_64-unknown-linux-gnu"