diff options
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp | 106 |
1 files changed, 97 insertions, 9 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index c0409206216e..a7b1953ce81c 100644 --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -16,7 +16,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/BranchProbabilityInfo.h" @@ -47,6 +46,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include "llvm/Transforms/Utils/SSAUpdater.h" #include <algorithm> @@ -421,6 +421,9 @@ bool InstrProfiling::lowerIntrinsics(Function *F) { } else if (auto *IPI = dyn_cast<InstrProfIncrementInst>(&Instr)) { lowerIncrement(IPI); MadeChange = true; + } else if (auto *IPC = dyn_cast<InstrProfTimestampInst>(&Instr)) { + lowerTimestamp(IPC); + MadeChange = true; } else if (auto *IPC = dyn_cast<InstrProfCoverInst>(&Instr)) { lowerCover(IPC); MadeChange = true; @@ -510,6 +513,7 @@ static bool containsProfilingIntrinsics(Module &M) { return containsIntrinsic(llvm::Intrinsic::instrprof_cover) || containsIntrinsic(llvm::Intrinsic::instrprof_increment) || containsIntrinsic(llvm::Intrinsic::instrprof_increment_step) || + containsIntrinsic(llvm::Intrinsic::instrprof_timestamp) || containsIntrinsic(llvm::Intrinsic::instrprof_value_profile); } @@ -540,18 +544,19 @@ bool InstrProfiling::run( // the instrumented function. This is counting the number of instrumented // target value sites to enter it as field in the profile data variable. for (Function &F : M) { - InstrProfIncrementInst *FirstProfIncInst = nullptr; + InstrProfInstBase *FirstProfInst = nullptr; for (BasicBlock &BB : F) for (auto I = BB.begin(), E = BB.end(); I != E; I++) if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(I)) computeNumValueSiteCounts(Ind); - else if (FirstProfIncInst == nullptr) - FirstProfIncInst = dyn_cast<InstrProfIncrementInst>(I); + else if (FirstProfInst == nullptr && + (isa<InstrProfIncrementInst>(I) || isa<InstrProfCoverInst>(I))) + FirstProfInst = dyn_cast<InstrProfInstBase>(I); // Value profiling intrinsic lowering requires per-function profile data // variable to be created first. - if (FirstProfIncInst != nullptr) - static_cast<void>(getOrCreateRegionCounters(FirstProfIncInst)); + if (FirstProfInst != nullptr) + static_cast<void>(getOrCreateRegionCounters(FirstProfInst)); } for (Function &F : M) @@ -669,6 +674,9 @@ Value *InstrProfiling::getCounterAddress(InstrProfInstBase *I) { auto *Counters = getOrCreateRegionCounters(I); IRBuilder<> Builder(I); + if (isa<InstrProfTimestampInst>(I)) + Counters->setAlignment(Align(8)); + auto *Addr = Builder.CreateConstInBoundsGEP2_32( Counters->getValueType(), Counters, 0, I->getIndex()->getZExtValue()); @@ -710,6 +718,21 @@ void InstrProfiling::lowerCover(InstrProfCoverInst *CoverInstruction) { CoverInstruction->eraseFromParent(); } +void InstrProfiling::lowerTimestamp( + InstrProfTimestampInst *TimestampInstruction) { + assert(TimestampInstruction->getIndex()->isZeroValue() && + "timestamp probes are always the first probe for a function"); + auto &Ctx = M->getContext(); + auto *TimestampAddr = getCounterAddress(TimestampInstruction); + IRBuilder<> Builder(TimestampInstruction); + auto *CalleeTy = + FunctionType::get(Type::getVoidTy(Ctx), TimestampAddr->getType(), false); + auto Callee = M->getOrInsertFunction( + INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_SET_TIMESTAMP), CalleeTy); + Builder.CreateCall(Callee, {TimestampAddr}); + TimestampInstruction->eraseFromParent(); +} + void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { auto *Addr = getCounterAddress(Inc); @@ -823,6 +846,72 @@ static inline bool shouldRecordFunctionAddr(Function *F) { return F->hasAddressTaken() || F->hasLinkOnceLinkage(); } +static inline bool shouldUsePublicSymbol(Function *Fn) { + // It isn't legal to make an alias of this function at all + if (Fn->isDeclarationForLinker()) + return true; + + // Symbols with local linkage can just use the symbol directly without + // introducing relocations + if (Fn->hasLocalLinkage()) + return true; + + // PGO + ThinLTO + CFI cause duplicate symbols to be introduced due to some + // unfavorable interaction between the new alias and the alias renaming done + // in LowerTypeTests under ThinLTO. For comdat functions that would normally + // be deduplicated, but the renaming scheme ends up preventing renaming, since + // it creates unique names for each alias, resulting in duplicated symbols. In + // the future, we should update the CFI related passes to migrate these + // aliases to the same module as the jump-table they refer to will be defined. + if (Fn->hasMetadata(LLVMContext::MD_type)) + return true; + + // For comdat functions, an alias would need the same linkage as the original + // function and hidden visibility. There is no point in adding an alias with + // identical linkage an visibility to avoid introducing symbolic relocations. + if (Fn->hasComdat() && + (Fn->getVisibility() == GlobalValue::VisibilityTypes::HiddenVisibility)) + return true; + + // its OK to use an alias + return false; +} + +static inline Constant *getFuncAddrForProfData(Function *Fn) { + auto *Int8PtrTy = Type::getInt8PtrTy(Fn->getContext()); + // Store a nullptr in __llvm_profd, if we shouldn't use a real address + if (!shouldRecordFunctionAddr(Fn)) + return ConstantPointerNull::get(Int8PtrTy); + + // If we can't use an alias, we must use the public symbol, even though this + // may require a symbolic relocation. + if (shouldUsePublicSymbol(Fn)) + return ConstantExpr::getBitCast(Fn, Int8PtrTy); + + // When possible use a private alias to avoid symbolic relocations. + auto *GA = GlobalAlias::create(GlobalValue::LinkageTypes::PrivateLinkage, + Fn->getName() + ".local", Fn); + + // When the instrumented function is a COMDAT function, we cannot use a + // private alias. If we did, we would create reference to a local label in + // this function's section. If this version of the function isn't selected by + // the linker, then the metadata would introduce a reference to a discarded + // section. So, for COMDAT functions, we need to adjust the linkage of the + // alias. Using hidden visibility avoids a dynamic relocation and an entry in + // the dynamic symbol table. + // + // Note that this handles COMDAT functions with visibility other than Hidden, + // since that case is covered in shouldUsePublicSymbol() + if (Fn->hasComdat()) { + GA->setLinkage(Fn->getLinkage()); + GA->setVisibility(GlobalValue::VisibilityTypes::HiddenVisibility); + } + + // appendToCompilerUsed(*Fn->getParent(), {GA}); + + return ConstantExpr::getBitCast(GA, Int8PtrTy); +} + static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) { // Don't do this for Darwin. compiler-rt uses linker magic. if (TT.isOSDarwin()) @@ -1014,9 +1103,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) { }; auto *DataTy = StructType::get(Ctx, ArrayRef(DataTypes)); - Constant *FunctionAddr = shouldRecordFunctionAddr(Fn) - ? ConstantExpr::getBitCast(Fn, Int8PtrTy) - : ConstantPointerNull::get(Int8PtrTy); + Constant *FunctionAddr = getFuncAddrForProfData(Fn); Constant *Int16ArrayVals[IPVK_Last + 1]; for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) @@ -1116,6 +1203,7 @@ void InstrProfiling::emitVNodes() { Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName()); VNodesVar->setSection( getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat())); + VNodesVar->setAlignment(M->getDataLayout().getABITypeAlign(VNodesTy)); // VNodesVar is used by runtime but not referenced via relocation by other // sections. Conservatively make it linker retained. UsedVars.push_back(VNodesVar); |