diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp')
-rw-r--r-- | contrib/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp | 161 |
1 files changed, 76 insertions, 85 deletions
diff --git a/contrib/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/contrib/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index b11c6be..adea7e7 100644 --- a/contrib/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/contrib/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -15,6 +15,7 @@ #include "llvm/Transforms/InstrProfiling.h" #include "llvm/ADT/Triple.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" @@ -31,6 +32,11 @@ cl::opt<bool> DoNameCompression("enable-name-compression", cl::desc("Enable name string compression"), cl::init(true)); +cl::opt<bool> DoHashBasedCounterSplit( + "hash-based-counter-split", + cl::desc("Rename counter variable of a comdat function based on cfg hash"), + cl::init(true)); + cl::opt<bool> ValueProfileStaticAlloc( "vp-static-alloc", cl::desc("Do static counter allocation for value profiler"), @@ -53,30 +59,38 @@ public: InstrProfilingLegacyPass() : ModulePass(ID), InstrProf() {} InstrProfilingLegacyPass(const InstrProfOptions &Options) : ModulePass(ID), InstrProf(Options) {} - const char *getPassName() const override { + StringRef getPassName() const override { return "Frontend instrumentation-based coverage lowering"; } - bool runOnModule(Module &M) override { return InstrProf.run(M); } + bool runOnModule(Module &M) override { + return InstrProf.run(M, getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()); + } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); + AU.addRequired<TargetLibraryInfoWrapperPass>(); } }; } // anonymous namespace -PreservedAnalyses InstrProfiling::run(Module &M, AnalysisManager<Module> &AM) { - if (!run(M)) +PreservedAnalyses InstrProfiling::run(Module &M, ModuleAnalysisManager &AM) { + auto &TLI = AM.getResult<TargetLibraryAnalysis>(M); + if (!run(M, TLI)) return PreservedAnalyses::all(); return PreservedAnalyses::none(); } char InstrProfilingLegacyPass::ID = 0; -INITIALIZE_PASS(InstrProfilingLegacyPass, "instrprof", - "Frontend instrumentation-based coverage lowering.", false, - false) +INITIALIZE_PASS_BEGIN( + InstrProfilingLegacyPass, "instrprof", + "Frontend instrumentation-based coverage lowering.", false, false) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_END( + InstrProfilingLegacyPass, "instrprof", + "Frontend instrumentation-based coverage lowering.", false, false) ModulePass * llvm::createInstrProfilingLegacyPass(const InstrProfOptions &Options) { @@ -107,10 +121,18 @@ StringRef InstrProfiling::getCoverageSection() const { return getInstrProfCoverageSectionName(isMachO()); } -bool InstrProfiling::run(Module &M) { +static InstrProfIncrementInst *castToIncrementInst(Instruction *Instr) { + InstrProfIncrementInst *Inc = dyn_cast<InstrProfIncrementInstStep>(Instr); + if (Inc) + return Inc; + return dyn_cast<InstrProfIncrementInst>(Instr); +} + +bool InstrProfiling::run(Module &M, const TargetLibraryInfo &TLI) { bool MadeChange = false; this->M = &M; + this->TLI = &TLI; NamesVar = nullptr; NamesSize = 0; ProfileDataMap.clear(); @@ -138,7 +160,8 @@ bool InstrProfiling::run(Module &M) { for (BasicBlock &BB : F) for (auto I = BB.begin(), E = BB.end(); I != E;) { auto Instr = I++; - if (auto *Inc = dyn_cast<InstrProfIncrementInst>(Instr)) { + InstrProfIncrementInst *Inc = castToIncrementInst(&*Instr); + if (Inc) { lowerIncrement(Inc); MadeChange = true; } else if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(Instr)) { @@ -165,7 +188,8 @@ bool InstrProfiling::run(Module &M) { return true; } -static Constant *getOrInsertValueProfilingCall(Module &M) { +static Constant *getOrInsertValueProfilingCall(Module &M, + const TargetLibraryInfo &TLI) { LLVMContext &Ctx = M.getContext(); auto *ReturnTy = Type::getVoidTy(M.getContext()); Type *ParamTypes[] = { @@ -174,8 +198,13 @@ static Constant *getOrInsertValueProfilingCall(Module &M) { }; auto *ValueProfilingCallTy = FunctionType::get(ReturnTy, makeArrayRef(ParamTypes), false); - return M.getOrInsertFunction(getInstrProfValueProfFuncName(), - ValueProfilingCallTy); + Constant *Res = M.getOrInsertFunction(getInstrProfValueProfFuncName(), + ValueProfilingCallTy); + if (Function *FunRes = dyn_cast<Function>(Res)) { + if (auto AK = TLI.getExtAttrForI32Param(false)) + FunRes->addAttribute(3, AK); + } + return Res; } void InstrProfiling::computeNumValueSiteCounts(InstrProfValueProfileInst *Ind) { @@ -209,8 +238,11 @@ void InstrProfiling::lowerValueProfileInst(InstrProfValueProfileInst *Ind) { Value *Args[3] = {Ind->getTargetValue(), Builder.CreateBitCast(DataVar, Builder.getInt8PtrTy()), Builder.getInt32(Index)}; - Ind->replaceAllUsesWith( - Builder.CreateCall(getOrInsertValueProfilingCall(*M), Args)); + CallInst *Call = Builder.CreateCall(getOrInsertValueProfilingCall(*M, *TLI), + Args); + if (auto AK = TLI->getExtAttrForI32Param(false)) + Call->addAttribute(3, AK); + Ind->replaceAllUsesWith(Call); Ind->eraseFromParent(); } @@ -221,7 +253,7 @@ void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { uint64_t Index = Inc->getIndex()->getZExtValue(); Value *Addr = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Index); Value *Count = Builder.CreateLoad(Addr, "pgocount"); - Count = Builder.CreateAdd(Count, Builder.getInt64(1)); + Count = Builder.CreateAdd(Count, Inc->getStep()); Inc->replaceAllUsesWith(Builder.CreateStore(Count, Addr)); Inc->eraseFromParent(); } @@ -245,7 +277,16 @@ void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageNamesVar) { static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) { StringRef NamePrefix = getInstrProfNameVarPrefix(); StringRef Name = Inc->getName()->getName().substr(NamePrefix.size()); - return (Prefix + Name).str(); + Function *F = Inc->getParent()->getParent(); + Module *M = F->getParent(); + if (!DoHashBasedCounterSplit || !isIRPGOFlagSet(M) || + !canRenameComdatFunc(*F)) + return (Prefix + Name).str(); + uint64_t FuncHash = Inc->getHash()->getZExtValue(); + SmallVector<char, 24> HashPostfix; + if (Name.endswith((Twine(".") + Twine(FuncHash)).toStringRef(HashPostfix))) + return (Prefix + Name).str(); + return (Prefix + Name + "." + Twine(FuncHash)).str(); } static inline bool shouldRecordFunctionAddr(Function *F) { @@ -268,33 +309,6 @@ static inline bool shouldRecordFunctionAddr(Function *F) { return F->hasAddressTaken() || F->hasLinkOnceLinkage(); } -static inline bool needsComdatForCounter(Function &F, Module &M) { - - if (F.hasComdat()) - return true; - - Triple TT(M.getTargetTriple()); - if (!TT.isOSBinFormatELF()) - return false; - - // See createPGOFuncNameVar for more details. To avoid link errors, profile - // counters for function with available_externally linkage needs to be changed - // to linkonce linkage. On ELF based systems, this leads to weak symbols to be - // created. Without using comdat, duplicate entries won't be removed by the - // linker leading to increased data segement size and raw profile size. Even - // worse, since the referenced counter from profile per-function data object - // will be resolved to the common strong definition, the profile counts for - // available_externally functions will end up being duplicated in raw profile - // data. This can result in distorted profile as the counts of those dups - // will be accumulated by the profile merger. - GlobalValue::LinkageTypes Linkage = F.getLinkage(); - if (Linkage != GlobalValue::ExternalWeakLinkage && - Linkage != GlobalValue::AvailableExternallyLinkage) - return false; - - return true; -} - static inline Comdat *getOrCreateProfileComdat(Module &M, Function &F, InstrProfIncrementInst *Inc) { if (!needsComdatForCounter(F, M)) @@ -572,38 +586,30 @@ void InstrProfiling::emitRuntimeHook() { } void InstrProfiling::emitUses() { - if (UsedVars.empty()) - return; - - GlobalVariable *LLVMUsed = M->getGlobalVariable("llvm.used"); - std::vector<Constant *> MergedVars; - if (LLVMUsed) { - // Collect the existing members of llvm.used. - ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); - for (unsigned I = 0, E = Inits->getNumOperands(); I != E; ++I) - MergedVars.push_back(Inits->getOperand(I)); - LLVMUsed->eraseFromParent(); - } - - Type *i8PTy = Type::getInt8PtrTy(M->getContext()); - // Add uses for our data. - for (auto *Value : UsedVars) - MergedVars.push_back( - ConstantExpr::getBitCast(cast<Constant>(Value), i8PTy)); - - // Recreate llvm.used. - ArrayType *ATy = ArrayType::get(i8PTy, MergedVars.size()); - LLVMUsed = - new GlobalVariable(*M, ATy, false, GlobalValue::AppendingLinkage, - ConstantArray::get(ATy, MergedVars), "llvm.used"); - LLVMUsed->setSection("llvm.metadata"); + if (!UsedVars.empty()) + appendToUsed(*M, UsedVars); } void InstrProfiling::emitInitialization() { - std::string InstrProfileOutput = Options.InstrProfileOutput; + StringRef InstrProfileOutput = Options.InstrProfileOutput; + + if (!InstrProfileOutput.empty()) { + // Create variable for profile name. + Constant *ProfileNameConst = + ConstantDataArray::getString(M->getContext(), InstrProfileOutput, true); + GlobalVariable *ProfileNameVar = new GlobalVariable( + *M, ProfileNameConst->getType(), true, GlobalValue::WeakAnyLinkage, + ProfileNameConst, INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR)); + Triple TT(M->getTargetTriple()); + if (TT.supportsCOMDAT()) { + ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage); + ProfileNameVar->setComdat(M->getOrInsertComdat( + StringRef(INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR)))); + } + } Constant *RegisterF = M->getFunction(getInstrProfRegFuncsName()); - if (!RegisterF && InstrProfileOutput.empty()) + if (!RegisterF) return; // Create the initialization function. @@ -620,21 +626,6 @@ void InstrProfiling::emitInitialization() { IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", F)); if (RegisterF) IRB.CreateCall(RegisterF, {}); - if (!InstrProfileOutput.empty()) { - auto *Int8PtrTy = Type::getInt8PtrTy(M->getContext()); - auto *SetNameTy = FunctionType::get(VoidTy, Int8PtrTy, false); - auto *SetNameF = Function::Create(SetNameTy, GlobalValue::ExternalLinkage, - getInstrProfFileOverriderFuncName(), M); - - // Create variable for profile name. - Constant *ProfileNameConst = - ConstantDataArray::getString(M->getContext(), InstrProfileOutput, true); - GlobalVariable *ProfileName = - new GlobalVariable(*M, ProfileNameConst->getType(), true, - GlobalValue::PrivateLinkage, ProfileNameConst); - - IRB.CreateCall(SetNameF, IRB.CreatePointerCast(ProfileName, Int8PtrTy)); - } IRB.CreateRetVoid(); appendToGlobalCtors(*M, F, 0); |