Skip to content

Commit 9ab9a95

Browse files
committed
[InstrProfiling] Keep profd non-private for non-renamable comdat functions
The NS==0 condition used by D103717 missed a corner case: if the current copy does not have a hash suffix (e.g. weak_odr), a copy with value profiling (with a different CFG) may exist. This is super rare, but is possible with pre-inlining PGO instrumentation (which can make a weak_odr function inlines its callees differently, sometimes with value profiling while sometimes without). If the current copy with private profd is prevailing, the non-prevailing copy may get an undefined symbol if a caller inlining the non-prevailing function references its profd. If the other copy with non-private profd is prevailing, the current copy may cause a "relocation to discarded section" linker error. The fix is straightforward: just keep non-private profd in such a `DataReferencedByCode` case. With this change, a stage 2 (`-DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_INSTRUMENTED=IR`) clang is 0.08% larger (172431496/172286720-1). `stat -c %s **/*.o | awk '{s+=$1}END{print s}' is 0.026% larger. The majority of D103717's benefits remains. Reviewed By: xur Differential Revision: https://reviews.llvm.org/D108432
1 parent cd4d6d7 commit 9ab9a95

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -758,14 +758,18 @@ void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageNamesVar) {
758758
}
759759

760760
/// Get the name of a profiling variable for a particular function.
761-
static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) {
761+
static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix,
762+
bool &Renamed) {
762763
StringRef NamePrefix = getInstrProfNameVarPrefix();
763764
StringRef Name = Inc->getName()->getName().substr(NamePrefix.size());
764765
Function *F = Inc->getParent()->getParent();
765766
Module *M = F->getParent();
766767
if (!DoHashBasedCounterSplit || !isIRPGOFlagSet(M) ||
767-
!canRenameComdatFunc(*F))
768+
!canRenameComdatFunc(*F)) {
769+
Renamed = false;
768770
return (Prefix + Name).str();
771+
}
772+
Renamed = true;
769773
uint64_t FuncHash = Inc->getHash()->getZExtValue();
770774
SmallVector<char, 24> HashPostfix;
771775
if (Name.endswith((Twine(".") + Twine(FuncHash)).toStringRef(HashPostfix)))
@@ -878,8 +882,11 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
878882
// discarded.
879883
bool DataReferencedByCode = profDataReferencedByCode(*M);
880884
bool NeedComdat = needsComdatForCounter(*Fn, *M);
881-
std::string CntsVarName = getVarName(Inc, getInstrProfCountersVarPrefix());
882-
std::string DataVarName = getVarName(Inc, getInstrProfDataVarPrefix());
885+
bool Renamed;
886+
std::string CntsVarName =
887+
getVarName(Inc, getInstrProfCountersVarPrefix(), Renamed);
888+
std::string DataVarName =
889+
getVarName(Inc, getInstrProfDataVarPrefix(), Renamed);
883890
auto MaybeSetComdat = [&](GlobalVariable *GV) {
884891
bool UseComdat = (NeedComdat || TT.isOSBinFormatELF());
885892
if (UseComdat) {
@@ -920,7 +927,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
920927
ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS);
921928
auto *ValuesVar = new GlobalVariable(
922929
*M, ValuesTy, false, Linkage, Constant::getNullValue(ValuesTy),
923-
getVarName(Inc, getInstrProfValuesVarPrefix()));
930+
getVarName(Inc, getInstrProfValuesVarPrefix(), Renamed));
924931
ValuesVar->setVisibility(Visibility);
925932
ValuesVar->setSection(
926933
getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
@@ -955,8 +962,13 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
955962
//
956963
// On COFF, a comdat leader cannot be local so we require DataReferencedByCode
957964
// to be false.
958-
if (NS == 0 && (TT.isOSBinFormatELF() ||
959-
(!DataReferencedByCode && TT.isOSBinFormatCOFF()))) {
965+
//
966+
// If profd is in a deduplicate comdat, NS==0 with a hash suffix guarantees
967+
// that other copies must have the same CFG and cannot have value profiling.
968+
// If no hash suffix, other profd copies may be referenced by code.
969+
if (NS == 0 && !(DataReferencedByCode && NeedComdat && !Renamed) &&
970+
(TT.isOSBinFormatELF() ||
971+
(!DataReferencedByCode && TT.isOSBinFormatCOFF()))) {
960972
Linkage = GlobalValue::PrivateLinkage;
961973
Visibility = GlobalValue::DefaultVisibility;
962974
}

llvm/test/Transforms/PGOProfile/comdat.ll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ define linkonce_odr void @linkonceodr() comdat {
1616
ret void
1717
}
1818

19-
;; weakodr in a comdat is not renamed.
19+
;; weakodr in a comdat is not renamed. There is no guarantee that definitions in
20+
;; other modules don't have value profiling. profd should be conservatively
21+
;; non-private to prevent a caller from referencing a non-prevailing profd,
22+
;; causing a linker error.
2023
; ELF: @__profc_weakodr = weak_odr hidden global {{.*}} comdat, align 8
21-
; ELF: @__profd_weakodr = private global {{.*}} comdat($__profc_weakodr), align 8
24+
; ELF: @__profd_weakodr = weak_odr hidden global {{.*}} comdat($__profc_weakodr), align 8
2225
; COFF: @__profc_weakodr = weak_odr hidden global {{.*}} comdat, align 8
2326
; COFF: @__profd_weakodr = weak_odr hidden global {{.*}} comdat, align 8
2427
define weak_odr void @weakodr() comdat {

0 commit comments

Comments
 (0)