Skip to content

Commit 99e5b1a

Browse files
committed
Merging r372020 and r372182:
------------------------------------------------------------------------ r372020 | rnk | 2019-09-16 11:49:09 -0700 (Mon, 16 Sep 2019) | 30 lines [PGO] Use linkonce_odr linkage for __profd_ variables in comdat groups This fixes relocations against __profd_ symbols in discarded sections, which is PR41380. In general, instrumentation happens very early, and optimization and inlining happens afterwards. The counters for a function are calculated early, and after inlining, counters for an inlined function may be widely referenced by other functions. For C++ inline functions of all kinds (linkonce_odr & available_externally mainly), instr profiling wants to deduplicate these __profc_ and __profd_ globals. Otherwise the binary would be quite large. I made __profd_ and __profc_ comdat in r355044, but I chose to make __profd_ internal. At the time, I was only dealing with coverage, and in that case, none of the instrumentation needs to reference __profd_. However, if you use PGO, then instrumentation passes add calls to __llvm_profile_instrument_range which reference __profd_ globals. The solution is to make these globals externally visible by using linkonce_odr linkage for data as was done for counters. This is safe because PGO adds a CFG hash to the names of the data and counter globals, so if different TUs have different globals, they will get different data and counter arrays. Reviewers: xur, hans Differential Revision: https://reviews.llvm.org/D67579 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r372182 | rnk | 2019-09-17 14:10:49 -0700 (Tue, 17 Sep 2019) | 12 lines [PGO] Don't use comdat groups for counters & data on COFF For COFF, a comdat group is really a symbol marked IMAGE_COMDAT_SELECT_ANY and zero or more other symbols marked IMAGE_COMDAT_SELECT_ASSOCIATIVE. Typically the associative symbols in the group are not external and are not referenced by other TUs, they are things like debug info, C++ dynamic initializers, or other section registration schemes. The Visual C++ linker reports a duplicate symbol error for symbols marked IMAGE_COMDAT_SELECT_ASSOCIATIVE even if they would be discarded after handling the leader symbol. Fixes coverage-inline.cpp in check-profile after r372020. ------------------------------------------------------------------------ llvm-svn: 374858
1 parent 35127d7 commit 99e5b1a

File tree

4 files changed

+31
-25
lines changed

4 files changed

+31
-25
lines changed

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -731,9 +731,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
731731
PD = It->second;
732732
}
733733

734-
// Match the linkage and visibility of the name global, except on COFF, where
735-
// the linkage must be local and consequentially the visibility must be
736-
// default.
734+
// Match the linkage and visibility of the name global. COFF supports using
735+
// comdats with internal symbols, so do that if we can.
737736
Function *Fn = Inc->getParent()->getParent();
738737
GlobalValue::LinkageTypes Linkage = NamePtr->getLinkage();
739738
GlobalValue::VisibilityTypes Visibility = NamePtr->getVisibility();
@@ -749,19 +748,25 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
749748
// new comdat group for the counters and profiling data. If we use the comdat
750749
// of the parent function, that will result in relocations against discarded
751750
// sections.
752-
Comdat *Cmdt = nullptr;
753-
GlobalValue::LinkageTypes CounterLinkage = Linkage;
754-
if (needsComdatForCounter(*Fn, *M)) {
755-
StringRef CmdtPrefix = getInstrProfComdatPrefix();
751+
bool NeedComdat = needsComdatForCounter(*Fn, *M);
752+
Comdat *Cmdt = nullptr; // Comdat group.
753+
if (NeedComdat) {
756754
if (TT.isOSBinFormatCOFF()) {
757-
// For COFF, the comdat group name must be the name of a symbol in the
758-
// group. Use the counter variable name, and upgrade its linkage to
759-
// something externally visible, like linkonce_odr.
760-
CmdtPrefix = getInstrProfCountersVarPrefix();
761-
CounterLinkage = GlobalValue::LinkOnceODRLinkage;
755+
// For COFF, put the counters, data, and values each into their own
756+
// comdats. We can't use a group because the Visual C++ linker will
757+
// report duplicate symbol errors if there are multiple external symbols
758+
// with the same name marked IMAGE_COMDAT_SELECT_ASSOCIATIVE.
759+
Linkage = GlobalValue::LinkOnceODRLinkage;
760+
Visibility = GlobalValue::HiddenVisibility;
761+
} else {
762+
// Otherwise, create one comdat group for everything.
763+
Cmdt = M->getOrInsertComdat(getVarName(Inc, getInstrProfComdatPrefix()));
762764
}
763-
Cmdt = M->getOrInsertComdat(getVarName(Inc, CmdtPrefix));
764765
}
766+
auto MaybeSetComdat = [=](GlobalVariable *GV) {
767+
if (NeedComdat)
768+
GV->setComdat(Cmdt ? Cmdt : M->getOrInsertComdat(GV->getName()));
769+
};
765770

766771
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
767772
LLVMContext &Ctx = M->getContext();
@@ -776,8 +781,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
776781
CounterPtr->setSection(
777782
getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat()));
778783
CounterPtr->setAlignment(8);
779-
CounterPtr->setComdat(Cmdt);
780-
CounterPtr->setLinkage(CounterLinkage);
784+
MaybeSetComdat(CounterPtr);
785+
CounterPtr->setLinkage(Linkage);
781786

782787
auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
783788
// Allocate statically the array of pointers to value profile nodes for
@@ -798,7 +803,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
798803
ValuesVar->setSection(
799804
getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
800805
ValuesVar->setAlignment(8);
801-
ValuesVar->setComdat(Cmdt);
806+
MaybeSetComdat(ValuesVar);
802807
ValuesPtrExpr =
803808
ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
804809
}
@@ -831,7 +836,8 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
831836
Data->setVisibility(Visibility);
832837
Data->setSection(getInstrProfSectionName(IPSK_data, TT.getObjectFormat()));
833838
Data->setAlignment(INSTR_PROF_DATA_ALIGNMENT);
834-
Data->setComdat(Cmdt);
839+
MaybeSetComdat(Data);
840+
Data->setLinkage(Linkage);
835841

836842
PD.RegionCounters = CounterPtr;
837843
PD.DataVar = Data;

llvm/test/Instrumentation/InstrProfiling/PR23499.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ $_Z3barIvEvv = comdat any
2020

2121

2222
; COFF-NOT: __profn__Z3barIvEvv
23-
; COFF: @__profc__Z3barIvEvv = linkonce_odr dso_local global [1 x i64] zeroinitializer, section "{{.*}}prfc$M", comdat, align 8
24-
; COFF: @__profd__Z3barIvEvv = internal global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat($__profc__Z3barIvEvv), align 8
23+
; COFF: @__profc__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}prfc$M", comdat, align 8
24+
; COFF: @__profd__Z3barIvEvv = linkonce_odr hidden global { i64, i64, i64*, i8*, i8*, i32, [2 x i16] } { i64 4947693190065689389, i64 0, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc__Z3barIvEvv, i32 0, i32 0), i8*{{.*}}, i8* null, i32 1, [2 x i16] zeroinitializer }, section "{{.*}}prfd{{.*}}", comdat, align 8
2525

2626

2727
declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1

llvm/test/Instrumentation/InstrProfiling/comdat.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ $foo_inline = comdat any
1717

1818
; ELF: @__profc_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_cnts", comdat($__profv_foo_inline), align 8
1919
; ELF: @__profd_foo_inline = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($__profv_foo_inline), align 8
20-
; COFF: @__profc_foo_inline = linkonce_odr dso_local global{{.*}}, section ".lprfc$M", comdat, align 8
21-
; COFF: @__profd_foo_inline = internal global{{.*}}, section ".lprfd$M", comdat($__profc_foo_inline), align 8
20+
; COFF: @__profc_foo_inline = linkonce_odr hidden global{{.*}}, section ".lprfc$M", comdat, align 8
21+
; COFF: @__profd_foo_inline = linkonce_odr hidden global{{.*}}, section ".lprfd$M", comdat, align 8
2222
define weak_odr void @foo_inline() comdat {
2323
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_inline, i32 0, i32 0), i64 0, i32 1, i32 0)
2424
ret void
@@ -30,8 +30,8 @@ $foo_extern = comdat any
3030

3131
; ELF: @__profc_foo_extern = linkonce_odr hidden global{{.*}}, section "__llvm_prf_cnts", comdat($__profv_foo_extern)
3232
; ELF: @__profd_foo_extern = linkonce_odr hidden global{{.*}}, section "__llvm_prf_data", comdat($__profv_foo_extern)
33-
; COFF: @__profc_foo_extern = linkonce_odr dso_local global{{.*}}, section ".lprfc$M", comdat, align 8
34-
; COFF: @__profd_foo_extern = internal global{{.*}}, section ".lprfd$M", comdat($__profc_foo_extern), align 8
33+
; COFF: @__profc_foo_extern = linkonce_odr hidden global{{.*}}, section ".lprfc$M", comdat, align 8
34+
; COFF: @__profd_foo_extern = linkonce_odr hidden global{{.*}}, section ".lprfd$M", comdat, align 8
3535
define available_externally void @foo_extern() {
3636
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_extern, i32 0, i32 0), i64 0, i32 1, i32 0)
3737
ret void

llvm/test/Instrumentation/InstrProfiling/linkage.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ define linkonce_odr void @foo_inline() {
5757
; LINUX: @__profd_foo_extern = linkonce_odr hidden global {{.*}}section "__llvm_prf_data", comdat($__profv_foo_extern), align 8
5858
; MACHO: @__profc_foo_extern = linkonce_odr hidden global
5959
; MACHO: @__profd_foo_extern = linkonce_odr hidden global
60-
; COFF: @__profc_foo_extern = linkonce_odr dso_local global {{.*}}section ".lprfc$M", comdat, align 8
61-
; COFF: @__profd_foo_extern = internal global {{.*}}section ".lprfd$M", comdat($__profc_foo_extern), align 8
60+
; COFF: @__profc_foo_extern = linkonce_odr hidden global {{.*}}section ".lprfc$M", comdat, align 8
61+
; COFF: @__profd_foo_extern = linkonce_odr hidden global {{.*}}section ".lprfd$M", comdat, align 8
6262
define available_externally void @foo_extern() {
6363
call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__profn_foo_extern, i32 0, i32 0), i64 0, i32 1, i32 0)
6464
ret void

0 commit comments

Comments
 (0)