diff options
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp | 171 |
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() { |