aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp')
-rw-r--r--llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp171
1 files changed, 125 insertions, 46 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index 9efc7d1ac500..0d257bb6bd52 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -205,6 +205,7 @@ public:
// automic update currently can only be promoted across the current
// loop, not the whole loop nest.
Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, LiveInValue,
+ MaybeAlign(),
AtomicOrdering::SequentiallyConsistent);
else {
LoadInst *OldVal = Builder.CreateLoad(Ty, Addr, "pgocount.promoted");
@@ -466,9 +467,14 @@ bool InstrProfiling::lowerIntrinsics(Function *F) {
}
bool InstrProfiling::isRuntimeCounterRelocationEnabled() const {
+ // Mach-O don't support weak external references.
+ if (TT.isOSBinFormatMachO())
+ return false;
+
if (RuntimeCounterRelocation.getNumOccurrences() > 0)
return RuntimeCounterRelocation;
+ // Fuchsia uses runtime counter relocation by default.
return TT.isOSFuchsia();
}
@@ -538,6 +544,7 @@ bool InstrProfiling::run(
NamesVar = nullptr;
NamesSize = 0;
ProfileDataMap.clear();
+ CompilerUsedVars.clear();
UsedVars.clear();
TT = Triple(M.getTargetTriple());
@@ -688,10 +695,19 @@ void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) {
Type *Int64Ty = Type::getInt64Ty(M->getContext());
GlobalVariable *Bias = M->getGlobalVariable(getInstrProfCounterBiasVarName());
if (!Bias) {
+ // Compiler must define this variable when runtime counter relocation
+ // is being used. Runtime has a weak external reference that is used
+ // to check whether that's the case or not.
Bias = new GlobalVariable(*M, Int64Ty, false, GlobalValue::LinkOnceODRLinkage,
Constant::getNullValue(Int64Ty),
getInstrProfCounterBiasVarName());
Bias->setVisibility(GlobalVariable::HiddenVisibility);
+ // A definition that's weak (linkonce_odr) without being in a COMDAT
+ // section wouldn't lead to link errors, but it would lead to a dead
+ // data word from every TU but one. Putting it in COMDAT ensures there
+ // will be exactly one data slot in the link.
+ if (TT.supportsCOMDAT())
+ Bias->setComdat(M->getOrInsertComdat(Bias->getName()));
}
LI = Builder.CreateLoad(Int64Ty, Bias);
}
@@ -702,7 +718,7 @@ void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) {
if (Options.Atomic || AtomicCounterUpdateAll ||
(Index == 0 && AtomicFirstCounter)) {
Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, Inc->getStep(),
- AtomicOrdering::Monotonic);
+ MaybeAlign(), AtomicOrdering::Monotonic);
} else {
Value *IncStep = Inc->getStep();
Value *Load = Builder.CreateLoad(IncStep->getType(), Addr, "pgocount");
@@ -746,7 +762,34 @@ static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) {
return (Prefix + Name + "." + Twine(FuncHash)).str();
}
+static uint64_t getIntModuleFlagOrZero(const Module &M, StringRef Flag) {
+ auto *MD = dyn_cast_or_null<ConstantAsMetadata>(M.getModuleFlag(Flag));
+ if (!MD)
+ return 0;
+
+ // If the flag is a ConstantAsMetadata, it should be an integer representable
+ // in 64-bits.
+ return cast<ConstantInt>(MD->getValue())->getZExtValue();
+}
+
+static bool enablesValueProfiling(const Module &M) {
+ return isIRPGOFlagSet(&M) ||
+ getIntModuleFlagOrZero(M, "EnableValueProfiling") != 0;
+}
+
+// Conservatively returns true if data variables may be referenced by code.
+static bool profDataReferencedByCode(const Module &M) {
+ return enablesValueProfiling(M);
+}
+
static inline bool shouldRecordFunctionAddr(Function *F) {
+ // Only record function addresses if IR PGO is enabled or if clang value
+ // profiling is enabled. Recording function addresses greatly increases object
+ // file size, because it prevents the inliner from deleting functions that
+ // have been inlined everywhere.
+ if (!profDataReferencedByCode(*F->getParent()))
+ return false;
+
// Check the linkage
bool HasAvailableExternallyLinkage = F->hasAvailableExternallyLinkage();
if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() &&
@@ -800,15 +843,10 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
PD = It->second;
}
- // Match the linkage and visibility of the name global. COFF supports using
- // comdats with internal symbols, so do that if we can.
+ // Match the linkage and visibility of the name global.
Function *Fn = Inc->getParent()->getParent();
GlobalValue::LinkageTypes Linkage = NamePtr->getLinkage();
GlobalValue::VisibilityTypes Visibility = NamePtr->getVisibility();
- if (TT.isOSBinFormatCOFF()) {
- Linkage = GlobalValue::InternalLinkage;
- Visibility = GlobalValue::DefaultVisibility;
- }
// Move the name variable to the right section. Place them in a COMDAT group
// if the associated function is a COMDAT. This will make sure that only one
@@ -817,22 +855,31 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
// new comdat group for the counters and profiling data. If we use the comdat
// of the parent function, that will result in relocations against discarded
// sections.
+ //
+ // If the data variable is referenced by code, counters and data have to be
+ // in different comdats for COFF because the Visual C++ linker will report
+ // duplicate symbol errors if there are multiple external symbols with the
+ // same name marked IMAGE_COMDAT_SELECT_ASSOCIATIVE.
+ //
+ // For ELF, when not using COMDAT, put counters, data and values into a
+ // nodeduplicate COMDAT which is lowered to a zero-flag section group. This
+ // allows -z start-stop-gc to discard the entire group when the function is
+ // discarded.
+ bool DataReferencedByCode = profDataReferencedByCode(*M);
bool NeedComdat = needsComdatForCounter(*Fn, *M);
- if (NeedComdat) {
- if (TT.isOSBinFormatCOFF()) {
- // For COFF, put the counters, data, and values each into their own
- // comdats. We can't use a group because the Visual C++ linker will
- // report duplicate symbol errors if there are multiple external symbols
- // with the same name marked IMAGE_COMDAT_SELECT_ASSOCIATIVE.
- Linkage = GlobalValue::LinkOnceODRLinkage;
- Visibility = GlobalValue::HiddenVisibility;
- }
- }
+ std::string CntsVarName = getVarName(Inc, getInstrProfCountersVarPrefix());
std::string DataVarName = getVarName(Inc, getInstrProfDataVarPrefix());
- auto MaybeSetComdat = [=](GlobalVariable *GV) {
- if (NeedComdat)
- GV->setComdat(M->getOrInsertComdat(TT.isOSBinFormatCOFF() ? GV->getName()
- : DataVarName));
+ auto MaybeSetComdat = [&](GlobalVariable *GV) {
+ bool UseComdat = (NeedComdat || TT.isOSBinFormatELF());
+ if (UseComdat) {
+ StringRef GroupName = TT.isOSBinFormatCOFF() && DataReferencedByCode
+ ? GV->getName()
+ : CntsVarName;
+ Comdat *C = M->getOrInsertComdat(GroupName);
+ if (!NeedComdat)
+ C->setSelectionKind(Comdat::NoDeduplicate);
+ GV->setComdat(C);
+ }
};
uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
@@ -842,8 +889,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
// Create the counters variable.
auto *CounterPtr =
new GlobalVariable(*M, CounterTy, false, Linkage,
- Constant::getNullValue(CounterTy),
- getVarName(Inc, getInstrProfCountersVarPrefix()));
+ Constant::getNullValue(CounterTy), CntsVarName);
CounterPtr->setVisibility(Visibility);
CounterPtr->setSection(
getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat()));
@@ -855,25 +901,22 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
// Allocate statically the array of pointers to value profile nodes for
// the current function.
Constant *ValuesPtrExpr = ConstantPointerNull::get(Int8PtrTy);
- if (ValueProfileStaticAlloc && !needsRuntimeRegistrationOfSectionRange(TT)) {
- uint64_t NS = 0;
- for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
- NS += PD.NumValueSites[Kind];
- if (NS) {
- ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS);
-
- auto *ValuesVar =
- new GlobalVariable(*M, ValuesTy, false, Linkage,
- Constant::getNullValue(ValuesTy),
- getVarName(Inc, getInstrProfValuesVarPrefix()));
- ValuesVar->setVisibility(Visibility);
- ValuesVar->setSection(
- getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
- ValuesVar->setAlignment(Align(8));
- MaybeSetComdat(ValuesVar);
- ValuesPtrExpr =
- ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
- }
+ uint64_t NS = 0;
+ for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
+ NS += PD.NumValueSites[Kind];
+ if (NS > 0 && ValueProfileStaticAlloc &&
+ !needsRuntimeRegistrationOfSectionRange(TT)) {
+ ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS);
+ auto *ValuesVar = new GlobalVariable(
+ *M, ValuesTy, false, Linkage, Constant::getNullValue(ValuesTy),
+ getVarName(Inc, getInstrProfValuesVarPrefix()));
+ ValuesVar->setVisibility(Visibility);
+ ValuesVar->setSection(
+ getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
+ ValuesVar->setAlignment(Align(8));
+ MaybeSetComdat(ValuesVar);
+ ValuesPtrExpr =
+ ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
}
// Create data variable.
@@ -897,6 +940,18 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
#define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init,
#include "llvm/ProfileData/InstrProfData.inc"
};
+ // If the data variable is not referenced by code (if we don't emit
+ // @llvm.instrprof.value.profile, NS will be 0), and the counter keeps the
+ // data variable live under linker GC, the data variable can be private. This
+ // optimization applies to ELF.
+ //
+ // On COFF, a comdat leader cannot be local so we require DataReferencedByCode
+ // to be false.
+ if (NS == 0 && (TT.isOSBinFormatELF() ||
+ (!DataReferencedByCode && TT.isOSBinFormatCOFF()))) {
+ Linkage = GlobalValue::PrivateLinkage;
+ Visibility = GlobalValue::DefaultVisibility;
+ }
auto *Data =
new GlobalVariable(*M, DataTy, false, Linkage,
ConstantStruct::get(DataTy, DataVals), DataVarName);
@@ -911,7 +966,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
ProfileDataMap[NamePtr] = PD;
// Mark the data variable as used so that it isn't stripped out.
- UsedVars.push_back(Data);
+ CompilerUsedVars.push_back(Data);
// Now that the linkage set by the FE has been passed to the data and counter
// variables, reset Name variable's linkage and visibility to private so that
// it can be removed later by the compiler.
@@ -966,6 +1021,8 @@ void InstrProfiling::emitVNodes() {
Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName());
VNodesVar->setSection(
getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat()));
+ // VNodesVar is used by runtime but not referenced via relocation by other
+ // sections. Conservatively make it linker retained.
UsedVars.push_back(VNodesVar);
}
@@ -994,6 +1051,8 @@ void InstrProfiling::emitNameData() {
// linker from inserting padding before the start of the names section or
// between names entries.
NamesVar->setAlignment(Align(1));
+ // NamesVar is used by runtime but not referenced via relocation by other
+ // sections. Conservatively make it linker retained.
UsedVars.push_back(NamesVar);
for (auto *NamePtr : ReferencedNames)
@@ -1021,6 +1080,9 @@ void InstrProfiling::emitRegistration() {
getInstrProfRegFuncName(), M);
IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", RegisterF));
+ for (Value *Data : CompilerUsedVars)
+ if (!isa<Function>(Data))
+ IRB.CreateCall(RuntimeRegisterF, IRB.CreateBitCast(Data, VoidPtrTy));
for (Value *Data : UsedVars)
if (Data != NamesVar && !isa<Function>(Data))
IRB.CreateCall(RuntimeRegisterF, IRB.CreateBitCast(Data, VoidPtrTy));
@@ -1071,13 +1133,30 @@ bool InstrProfiling::emitRuntimeHook() {
IRB.CreateRet(Load);
// Mark the user variable as used so that it isn't stripped out.
- UsedVars.push_back(User);
+ CompilerUsedVars.push_back(User);
return true;
}
void InstrProfiling::emitUses() {
- if (!UsedVars.empty())
- appendToUsed(*M, UsedVars);
+ // The metadata sections are parallel arrays. Optimizers (e.g.
+ // GlobalOpt/ConstantMerge) may not discard associated sections as a unit, so
+ // we conservatively retain all unconditionally in the compiler.
+ //
+ // On ELF, the linker can guarantee the associated sections will be retained
+ // or discarded as a unit, so llvm.compiler.used is sufficient. Similarly on
+ // COFF, if prof data is not referenced by code we use one comdat and ensure
+ // this GC property as well. Otherwise, we have to conservatively make all of
+ // the sections retained by the linker.
+ if (TT.isOSBinFormatELF() ||
+ (TT.isOSBinFormatCOFF() && !profDataReferencedByCode(*M)))
+ appendToCompilerUsed(*M, CompilerUsedVars);
+ else
+ appendToUsed(*M, CompilerUsedVars);
+
+ // We do not add proper references from used metadata sections to NamesVar and
+ // VNodesVar, so we have to be conservative and place them in llvm.used
+ // regardless of the target,
+ appendToUsed(*M, UsedVars);
}
void InstrProfiling::emitInitialization() {