diff options
Diffstat (limited to 'lib/Transforms/Instrumentation/InstrProfiling.cpp')
-rw-r--r-- | lib/Transforms/Instrumentation/InstrProfiling.cpp | 213 |
1 files changed, 121 insertions, 92 deletions
diff --git a/lib/Transforms/Instrumentation/InstrProfiling.cpp b/lib/Transforms/Instrumentation/InstrProfiling.cpp index 15b94388cbe5..63c2b8078967 100644 --- a/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -1,9 +1,8 @@ //===-- InstrProfiling.cpp - Frontend instrumentation based profiling -----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -19,6 +18,8 @@ #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" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/Attributes.h" @@ -148,8 +149,8 @@ public: static char ID; InstrProfilingLegacyPass() : ModulePass(ID) {} - InstrProfilingLegacyPass(const InstrProfOptions &Options) - : ModulePass(ID), InstrProf(Options) {} + InstrProfilingLegacyPass(const InstrProfOptions &Options, bool IsCS = false) + : ModulePass(ID), InstrProf(Options, IsCS) {} StringRef getPassName() const override { return "Frontend instrumentation-based coverage lowering"; @@ -187,7 +188,7 @@ public: SSA.AddAvailableValue(PH, Init); } - void doExtraRewritesBeforeFinalDeletion() const override { + void doExtraRewritesBeforeFinalDeletion() override { for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { BasicBlock *ExitBlock = ExitBlocks[i]; Instruction *InsertPos = InsertPts[i]; @@ -196,6 +197,7 @@ public: // block. Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock); Value *Addr = cast<StoreInst>(Store)->getPointerOperand(); + Type *Ty = LiveInValue->getType(); IRBuilder<> Builder(InsertPos); if (AtomicCounterUpdatePromoted) // automic update currently can only be promoted across the current @@ -203,7 +205,7 @@ public: Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, LiveInValue, AtomicOrdering::SequentiallyConsistent); else { - LoadInst *OldVal = Builder.CreateLoad(Addr, "pgocount.promoted"); + LoadInst *OldVal = Builder.CreateLoad(Ty, Addr, "pgocount.promoted"); auto *NewVal = Builder.CreateAdd(OldVal, LiveInValue); auto *NewStore = Builder.CreateStore(NewVal, Addr); @@ -232,9 +234,9 @@ class PGOCounterPromoter { public: PGOCounterPromoter( DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCands, - Loop &CurLoop, LoopInfo &LI) + Loop &CurLoop, LoopInfo &LI, BlockFrequencyInfo *BFI) : LoopToCandidates(LoopToCands), ExitBlocks(), InsertPts(), L(CurLoop), - LI(LI) { + LI(LI), BFI(BFI) { SmallVector<BasicBlock *, 8> LoopExitBlocks; SmallPtrSet<BasicBlock *, 8> BlockSet; @@ -263,6 +265,20 @@ public: SSAUpdater SSA(&NewPHIs); Value *InitVal = ConstantInt::get(Cand.first->getType(), 0); + // If BFI is set, we will use it to guide the promotions. + if (BFI) { + auto *BB = Cand.first->getParent(); + auto InstrCount = BFI->getBlockProfileCount(BB); + if (!InstrCount) + continue; + auto PreheaderCount = BFI->getBlockProfileCount(L.getLoopPreheader()); + // If the average loop trip count is not greater than 1.5, we skip + // promotion. + if (PreheaderCount && + (PreheaderCount.getValue() * 3) >= (InstrCount.getValue() * 2)) + continue; + } + PGOCounterPromoterHelper Promoter(Cand.first, Cand.second, SSA, InitVal, L.getLoopPreheader(), ExitBlocks, InsertPts, LoopToCandidates, LI); @@ -312,6 +328,11 @@ private: SmallVector<BasicBlock *, 8> ExitingBlocks; LP->getExitingBlocks(ExitingBlocks); + + // If BFI is set, we do more aggressive promotions based on BFI. + if (BFI) + return (unsigned)-1; + // Not considierered speculative. if (ExitingBlocks.size() == 1) return MaxNumOfPromotionsPerLoop; @@ -343,6 +364,7 @@ private: SmallVector<Instruction *, 8> InsertPts; Loop &L; LoopInfo &LI; + BlockFrequencyInfo *BFI; }; } // end anonymous namespace @@ -365,8 +387,9 @@ INITIALIZE_PASS_END( "Frontend instrumentation-based coverage lowering.", false, false) ModulePass * -llvm::createInstrProfilingLegacyPass(const InstrProfOptions &Options) { - return new InstrProfilingLegacyPass(Options); +llvm::createInstrProfilingLegacyPass(const InstrProfOptions &Options, + bool IsCS) { + return new InstrProfilingLegacyPass(Options, IsCS); } static InstrProfIncrementInst *castToIncrementInst(Instruction *Instr) { @@ -415,6 +438,13 @@ void InstrProfiling::promoteCounterLoadStores(Function *F) { LoopInfo LI(DT); DenseMap<Loop *, SmallVector<LoadStorePair, 8>> LoopPromotionCandidates; + std::unique_ptr<BlockFrequencyInfo> BFI; + if (Options.UseBFIInPromotion) { + std::unique_ptr<BranchProbabilityInfo> BPI; + BPI.reset(new BranchProbabilityInfo(*F, LI, TLI)); + BFI.reset(new BlockFrequencyInfo(*F, *BPI, LI)); + } + for (const auto &LoadStore : PromotionCandidates) { auto *CounterLoad = LoadStore.first; auto *CounterStore = LoadStore.second; @@ -430,7 +460,7 @@ void InstrProfiling::promoteCounterLoadStores(Function *F) { // Do a post-order traversal of the loops so that counter updates can be // iteratively hoisted outside the loop nest. for (auto *Loop : llvm::reverse(Loops)) { - PGOCounterPromoter Promoter(LoopPromotionCandidates, *Loop, LI); + PGOCounterPromoter Promoter(LoopPromotionCandidates, *Loop, LI, BFI.get()); Promoter.run(&TotalCountersPromoted); } } @@ -509,13 +539,16 @@ bool InstrProfiling::run(Module &M, const TargetLibraryInfo &TLI) { return true; } -static Constant *getOrInsertValueProfilingCall(Module &M, - const TargetLibraryInfo &TLI, - bool IsRange = false) { +static FunctionCallee +getOrInsertValueProfilingCall(Module &M, const TargetLibraryInfo &TLI, + bool IsRange = false) { LLVMContext &Ctx = M.getContext(); auto *ReturnTy = Type::getVoidTy(M.getContext()); - Constant *Res; + AttributeList AL; + if (auto AK = TLI.getExtAttrForI32Param(false)) + AL = AL.addParamAttribute(M.getContext(), 2, AK); + if (!IsRange) { Type *ParamTypes[] = { #define VALUE_PROF_FUNC_PARAM(ParamType, ParamName, ParamLLVMType) ParamLLVMType @@ -523,8 +556,8 @@ static Constant *getOrInsertValueProfilingCall(Module &M, }; auto *ValueProfilingCallTy = FunctionType::get(ReturnTy, makeArrayRef(ParamTypes), false); - Res = M.getOrInsertFunction(getInstrProfValueProfFuncName(), - ValueProfilingCallTy); + return M.getOrInsertFunction(getInstrProfValueProfFuncName(), + ValueProfilingCallTy, AL); } else { Type *RangeParamTypes[] = { #define VALUE_RANGE_PROF 1 @@ -534,15 +567,9 @@ static Constant *getOrInsertValueProfilingCall(Module &M, }; auto *ValueRangeProfilingCallTy = FunctionType::get(ReturnTy, makeArrayRef(RangeParamTypes), false); - Res = M.getOrInsertFunction(getInstrProfValueRangeProfFuncName(), - ValueRangeProfilingCallTy); + return M.getOrInsertFunction(getInstrProfValueRangeProfFuncName(), + ValueRangeProfilingCallTy, AL); } - - if (Function *FunRes = dyn_cast<Function>(Res)) { - if (auto AK = TLI.getExtAttrForI32Param(false)) - FunRes->addParamAttr(2, AK); - } - return Res; } void InstrProfiling::computeNumValueSiteCounts(InstrProfValueProfileInst *Ind) { @@ -601,13 +628,15 @@ void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { IRBuilder<> Builder(Inc); uint64_t Index = Inc->getIndex()->getZExtValue(); - Value *Addr = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Index); + Value *Addr = Builder.CreateConstInBoundsGEP2_64(Counters->getValueType(), + Counters, 0, Index); if (Options.Atomic || AtomicCounterUpdateAll) { Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, Inc->getStep(), AtomicOrdering::Monotonic); } else { - Value *Load = Builder.CreateLoad(Addr, "pgocount"); + Value *IncStep = Inc->getStep(); + Value *Load = Builder.CreateLoad(IncStep->getType(), Addr, "pgocount"); auto *Count = Builder.CreateAdd(Load, Inc->getStep()); auto *Store = Builder.CreateStore(Count, Addr); if (isCounterPromotionEnabled()) @@ -678,32 +707,14 @@ static inline bool shouldRecordFunctionAddr(Function *F) { return F->hasAddressTaken() || F->hasLinkOnceLinkage(); } -static inline Comdat *getOrCreateProfileComdat(Module &M, Function &F, - InstrProfIncrementInst *Inc) { - if (!needsComdatForCounter(F, M)) - return nullptr; - - // COFF format requires a COMDAT section to have a key symbol with the same - // name. The linker targeting COFF also requires that the COMDAT - // a section is associated to must precede the associating section. For this - // reason, we must choose the counter var's name as the name of the comdat. - StringRef ComdatPrefix = (Triple(M.getTargetTriple()).isOSBinFormatCOFF() - ? getInstrProfCountersVarPrefix() - : getInstrProfComdatPrefix()); - return M.getOrInsertComdat(StringRef(getVarName(Inc, ComdatPrefix))); -} - -static bool needsRuntimeRegistrationOfSectionRange(const Module &M) { +static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) { // Don't do this for Darwin. compiler-rt uses linker magic. - if (Triple(M.getTargetTriple()).isOSDarwin()) + if (TT.isOSDarwin()) return false; - // Use linker script magic to get data/cnts/name start/end. - if (Triple(M.getTargetTriple()).isOSLinux() || - Triple(M.getTargetTriple()).isOSFreeBSD() || - Triple(M.getTargetTriple()).isOSNetBSD() || - Triple(M.getTargetTriple()).isOSFuchsia() || - Triple(M.getTargetTriple()).isPS4CPU()) + if (TT.isOSLinux() || TT.isOSFreeBSD() || TT.isOSNetBSD() || + TT.isOSSolaris() || TT.isOSFuchsia() || TT.isPS4CPU() || + TT.isOSWindows()) return false; return true; @@ -720,13 +731,37 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { PD = It->second; } - // 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 copy of counters of the COMDAT function will be emitted after - // linking. + // Match the linkage and visibility of the name global, except on COFF, where + // the linkage must be local and consequentially the visibility must be + // default. Function *Fn = Inc->getParent()->getParent(); - Comdat *ProfileVarsComdat = nullptr; - ProfileVarsComdat = getOrCreateProfileComdat(*M, *Fn, Inc); + 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 + // copy of counters of the COMDAT function will be emitted after linking. Keep + // in mind that this pass may run before the inliner, so we need to create a + // 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. + Comdat *Cmdt = nullptr; + GlobalValue::LinkageTypes CounterLinkage = Linkage; + if (needsComdatForCounter(*Fn, *M)) { + StringRef CmdtPrefix = getInstrProfComdatPrefix(); + if (TT.isOSBinFormatCOFF()) { + // For COFF, the comdat group name must be the name of a symbol in the + // group. Use the counter variable name, and upgrade its linkage to + // something externally visible, like linkonce_odr. + CmdtPrefix = getInstrProfCountersVarPrefix(); + CounterLinkage = GlobalValue::LinkOnceODRLinkage; + } + Cmdt = M->getOrInsertComdat(getVarName(Inc, CmdtPrefix)); + } uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); LLVMContext &Ctx = M->getContext(); @@ -734,20 +769,21 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { // Create the counters variable. auto *CounterPtr = - new GlobalVariable(*M, CounterTy, false, NamePtr->getLinkage(), + new GlobalVariable(*M, CounterTy, false, Linkage, Constant::getNullValue(CounterTy), getVarName(Inc, getInstrProfCountersVarPrefix())); - CounterPtr->setVisibility(NamePtr->getVisibility()); + CounterPtr->setVisibility(Visibility); CounterPtr->setSection( getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat())); CounterPtr->setAlignment(8); - CounterPtr->setComdat(ProfileVarsComdat); + CounterPtr->setComdat(Cmdt); + CounterPtr->setLinkage(CounterLinkage); auto *Int8PtrTy = Type::getInt8PtrTy(Ctx); // Allocate statically the array of pointers to value profile nodes for // the current function. Constant *ValuesPtrExpr = ConstantPointerNull::get(Int8PtrTy); - if (ValueProfileStaticAlloc && !needsRuntimeRegistrationOfSectionRange(*M)) { + if (ValueProfileStaticAlloc && !needsRuntimeRegistrationOfSectionRange(TT)) { uint64_t NS = 0; for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) NS += PD.NumValueSites[Kind]; @@ -755,14 +791,14 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS); auto *ValuesVar = - new GlobalVariable(*M, ValuesTy, false, NamePtr->getLinkage(), + new GlobalVariable(*M, ValuesTy, false, Linkage, Constant::getNullValue(ValuesTy), getVarName(Inc, getInstrProfValuesVarPrefix())); - ValuesVar->setVisibility(NamePtr->getVisibility()); + ValuesVar->setVisibility(Visibility); ValuesVar->setSection( getInstrProfSectionName(IPSK_vals, TT.getObjectFormat())); ValuesVar->setAlignment(8); - ValuesVar->setComdat(ProfileVarsComdat); + ValuesVar->setComdat(Cmdt); ValuesPtrExpr = ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx)); } @@ -789,13 +825,13 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init, #include "llvm/ProfileData/InstrProfData.inc" }; - auto *Data = new GlobalVariable(*M, DataTy, false, NamePtr->getLinkage(), + auto *Data = new GlobalVariable(*M, DataTy, false, Linkage, ConstantStruct::get(DataTy, DataVals), getVarName(Inc, getInstrProfDataVarPrefix())); - Data->setVisibility(NamePtr->getVisibility()); + Data->setVisibility(Visibility); Data->setSection(getInstrProfSectionName(IPSK_data, TT.getObjectFormat())); Data->setAlignment(INSTR_PROF_DATA_ALIGNMENT); - Data->setComdat(ProfileVarsComdat); + Data->setComdat(Cmdt); PD.RegionCounters = CounterPtr; PD.DataVar = Data; @@ -820,7 +856,7 @@ void InstrProfiling::emitVNodes() { // For now only support this on platforms that do // not require runtime registration to discover // named section start/end. - if (needsRuntimeRegistrationOfSectionRange(*M)) + if (needsRuntimeRegistrationOfSectionRange(TT)) return; size_t TotalNS = 0; @@ -881,6 +917,10 @@ void InstrProfiling::emitNameData() { NamesSize = CompressedNameStr.size(); NamesVar->setSection( getInstrProfSectionName(IPSK_name, TT.getObjectFormat())); + // On COFF, it's important to reduce the alignment down to 1 to prevent the + // linker from inserting padding before the start of the names section or + // between names entries. + NamesVar->setAlignment(1); UsedVars.push_back(NamesVar); for (auto *NamePtr : ReferencedNames) @@ -888,7 +928,7 @@ void InstrProfiling::emitNameData() { } void InstrProfiling::emitRegistration() { - if (!needsRuntimeRegistrationOfSectionRange(*M)) + if (!needsRuntimeRegistrationOfSectionRange(TT)) return; // Construct the function. @@ -929,7 +969,7 @@ void InstrProfiling::emitRegistration() { bool InstrProfiling::emitRuntimeHook() { // We expect the linker to be invoked with -u<hook_var> flag for linux, // for which case there is no need to emit the user function. - if (Triple(M->getTargetTriple()).isOSLinux()) + if (TT.isOSLinux()) return false; // If the module's provided its own runtime, we don't need to do anything. @@ -950,11 +990,11 @@ bool InstrProfiling::emitRuntimeHook() { if (Options.NoRedZone) User->addFnAttr(Attribute::NoRedZone); User->setVisibility(GlobalValue::HiddenVisibility); - if (Triple(M->getTargetTriple()).supportsCOMDAT()) + if (TT.supportsCOMDAT()) User->setComdat(M->getOrInsertComdat(User->getName())); IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", User)); - auto *Load = IRB.CreateLoad(Var); + auto *Load = IRB.CreateLoad(Int32Ty, Var); IRB.CreateRet(Load); // Mark the user variable as used so that it isn't stripped out. @@ -968,23 +1008,13 @@ void InstrProfiling::emitUses() { } void InstrProfiling::emitInitialization() { - 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)); - 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()); + // Create ProfileFileName variable. Don't don't this for the + // context-sensitive instrumentation lowering: This lowering is after + // LTO/ThinLTO linking. Pass PGOInstrumentationGenCreateVar should + // have already create the variable before LTO/ThinLTO linking. + if (!IsCS) + createProfileFileNameVar(*M, Options.InstrProfileOutput); + Function *RegisterF = M->getFunction(getInstrProfRegFuncsName()); if (!RegisterF) return; @@ -1000,8 +1030,7 @@ void InstrProfiling::emitInitialization() { // Add the basic block and the necessary calls. IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", F)); - if (RegisterF) - IRB.CreateCall(RegisterF, {}); + IRB.CreateCall(RegisterF, {}); IRB.CreateRetVoid(); appendToGlobalCtors(*M, F, 0); |