Skip to content

Commit a84f4fc

Browse files
committed
[InstrProfiling] Place __llvm_prf_vnodes and __llvm_prf_names in llvm.used on ELF
`__llvm_prf_vnodes` and `__llvm_prf_names` are used by runtime but not referenced via relocation in the translation unit. With `-z start-stop-gc` (LLD 13 (D96914); GNU ld 2.37 https://sourceware.org/bugzilla/show_bug.cgi?id=27451), the linker does not let `__start_/__stop_` references retain their sections. Place `__llvm_prf_vnodes` and `__llvm_prf_names` in `llvm.used` to make them retained by the linker. This patch changes most existing `UsedVars` cases to `CompilerUsedVars` to reflect the ideal state - if the binary format properly supports section based GC (dead stripping), `llvm.compiler.used` should be sufficient. `__llvm_prf_vnodes` and `__llvm_prf_names` are switched to `UsedVars` since we want them to be unconditionally retained by both compiler and linker. Behaviors on COFF/Mach-O are not affected. Reviewed By: davidxl Differential Revision: https://reviews.llvm.org/D97649
1 parent 75df61e commit a84f4fc

File tree

4 files changed

+25
-5
lines changed

4 files changed

+25
-5
lines changed

compiler-rt/test/profile/Linux/instrprof-value-merge-lld.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// REQUIRES: lld-available
22
/// Test ld with GC.
33

4-
// RUN: %clang_pgogen -o %t -O3 %S/Inputs/instrprof-value-merge.c -fuse-ld=lld -ffunction-sections -fdata-sections -Wl,--gc-sections
4+
// RUN: %clang_pgogen -o %t -O3 %S/Inputs/instrprof-value-merge.c -fuse-ld=lld -ffunction-sections -fdata-sections -Wl,--gc-sections -z start-stop-gc
55
// RUN: rm -rf %t.profdir
66
// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t
77
// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw %run %t

llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class InstrProfiling : public PassInfoMixin<InstrProfiling> {
5757
}
5858
};
5959
DenseMap<GlobalVariable *, PerFunctionProfileData> ProfileDataMap;
60+
std::vector<GlobalValue *> CompilerUsedVars;
6061
std::vector<GlobalValue *> UsedVars;
6162
std::vector<GlobalVariable *> ReferencedNames;
6263
GlobalVariable *NamesVar;

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ bool InstrProfiling::run(
539539
NamesVar = nullptr;
540540
NamesSize = 0;
541541
ProfileDataMap.clear();
542+
CompilerUsedVars.clear();
542543
UsedVars.clear();
543544
TT = Triple(M.getTargetTriple());
544545

@@ -921,7 +922,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
921922
ProfileDataMap[NamePtr] = PD;
922923

923924
// Mark the data variable as used so that it isn't stripped out.
924-
UsedVars.push_back(Data);
925+
CompilerUsedVars.push_back(Data);
925926
// Now that the linkage set by the FE has been passed to the data and counter
926927
// variables, reset Name variable's linkage and visibility to private so that
927928
// it can be removed later by the compiler.
@@ -976,6 +977,8 @@ void InstrProfiling::emitVNodes() {
976977
Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName());
977978
VNodesVar->setSection(
978979
getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat()));
980+
// VNodesVar is used by runtime but not referenced via relocation by other
981+
// sections. Conservatively make it linker retained.
979982
UsedVars.push_back(VNodesVar);
980983
}
981984

@@ -1004,6 +1007,8 @@ void InstrProfiling::emitNameData() {
10041007
// linker from inserting padding before the start of the names section or
10051008
// between names entries.
10061009
NamesVar->setAlignment(Align(1));
1010+
// NamesVar is used by runtime but not referenced via relocation by other
1011+
// sections. Conservatively make it linker retained.
10071012
UsedVars.push_back(NamesVar);
10081013

10091014
for (auto *NamePtr : ReferencedNames)
@@ -1031,6 +1036,9 @@ void InstrProfiling::emitRegistration() {
10311036
getInstrProfRegFuncName(), M);
10321037

10331038
IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", RegisterF));
1039+
for (Value *Data : CompilerUsedVars)
1040+
if (!isa<Function>(Data))
1041+
IRB.CreateCall(RuntimeRegisterF, IRB.CreateBitCast(Data, VoidPtrTy));
10341042
for (Value *Data : UsedVars)
10351043
if (Data != NamesVar && !isa<Function>(Data))
10361044
IRB.CreateCall(RuntimeRegisterF, IRB.CreateBitCast(Data, VoidPtrTy));
@@ -1081,7 +1089,7 @@ bool InstrProfiling::emitRuntimeHook() {
10811089
IRB.CreateRet(Load);
10821090

10831091
// Mark the user variable as used so that it isn't stripped out.
1084-
UsedVars.push_back(User);
1092+
CompilerUsedVars.push_back(User);
10851093
return true;
10861094
}
10871095

@@ -1094,9 +1102,14 @@ void InstrProfiling::emitUses() {
10941102
// or discarded as a unit, so llvm.compiler.used is sufficient. Otherwise,
10951103
// conservatively make all of them retained by the linker.
10961104
if (TT.isOSBinFormatELF())
1097-
appendToCompilerUsed(*M, UsedVars);
1105+
appendToCompilerUsed(*M, CompilerUsedVars);
10981106
else
1099-
appendToUsed(*M, UsedVars);
1107+
appendToUsed(*M, CompilerUsedVars);
1108+
1109+
// We do not add proper references from used metadata sections to NamesVar and
1110+
// VNodesVar, so we have to be conservative and place them in llvm.used
1111+
// regardless of the target,
1112+
appendToUsed(*M, UsedVars);
11001113
}
11011114

11021115
void InstrProfiling::emitInitialization() {

llvm/test/Instrumentation/InstrProfiling/icall.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ attributes #0 = { nounwind }
5050
; DYN-NOT: @__profvp_foo
5151
; DYN-NOT: @__llvm_prf_vnodes
5252

53+
;; __llvm_prf_vnodes and __llvm_prf_nm are not referenced by other metadata sections.
54+
;; We have to conservatively place them in llvm.used.
55+
; STATIC: @llvm.used = appending global
56+
; STATIC-SAME: @__llvm_prf_vnodes
57+
; STATIC-SAME: @__llvm_prf_nm
58+
5359
; STATIC: call void @__llvm_profile_instrument_target(i64 %3, i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_foo to i8*), i32 0)
5460
; STATIC-EXT: call void @__llvm_profile_instrument_target(i64 %3, i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_foo to i8*), i32 zeroext 0)
5561
; STATIC-SEXT: call void @__llvm_profile_instrument_target(i64 %3, i8* bitcast ({ i64, i64, i64*, i8*, i8*, i32, [2 x i16] }* @__profd_foo to i8*), i32 signext 0)

0 commit comments

Comments
 (0)