diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:04:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:05:05 +0000 |
| commit | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (patch) | |
| tree | 3a4038f3b7bafaeade9fd6146ea8021237616657 /llvm/lib/Transforms/Instrumentation | |
| parent | 6f8fc217eaa12bf657be1c6468ed9938d10168b3 (diff) | |
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation')
6 files changed, 211 insertions, 77 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 6e72255e51ae..8f94172a6402 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1527,22 +1527,22 @@ void AddressSanitizer::getInterestingMemoryOperands( return; if (LoadInst *LI = dyn_cast<LoadInst>(I)) { - if (!ClInstrumentReads || ignoreAccess(LI, LI->getPointerOperand())) + if (!ClInstrumentReads || ignoreAccess(I, LI->getPointerOperand())) return; Interesting.emplace_back(I, LI->getPointerOperandIndex(), false, LI->getType(), LI->getAlign()); } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) { - if (!ClInstrumentWrites || ignoreAccess(LI, SI->getPointerOperand())) + if (!ClInstrumentWrites || ignoreAccess(I, SI->getPointerOperand())) return; Interesting.emplace_back(I, SI->getPointerOperandIndex(), true, SI->getValueOperand()->getType(), SI->getAlign()); } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) { - if (!ClInstrumentAtomics || ignoreAccess(LI, RMW->getPointerOperand())) + if (!ClInstrumentAtomics || ignoreAccess(I, RMW->getPointerOperand())) return; Interesting.emplace_back(I, RMW->getPointerOperandIndex(), true, RMW->getValOperand()->getType(), None); } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) { - if (!ClInstrumentAtomics || ignoreAccess(LI, XCHG->getPointerOperand())) + if (!ClInstrumentAtomics || ignoreAccess(I, XCHG->getPointerOperand())) return; Interesting.emplace_back(I, XCHG->getPointerOperandIndex(), true, XCHG->getCompareOperand()->getType(), None); @@ -1556,7 +1556,7 @@ void AddressSanitizer::getInterestingMemoryOperands( return; auto BasePtr = CI->getOperand(OpOffset); - if (ignoreAccess(LI, BasePtr)) + if (ignoreAccess(I, BasePtr)) return; Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType(); MaybeAlign Alignment = Align(1); @@ -1568,7 +1568,7 @@ void AddressSanitizer::getInterestingMemoryOperands( } else { for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) { if (!ClInstrumentByval || !CI->isByValArgument(ArgNo) || - ignoreAccess(LI, CI->getArgOperand(ArgNo))) + ignoreAccess(I, CI->getArgOperand(ArgNo))) continue; Type *Ty = CI->getParamByValType(ArgNo); Interesting.emplace_back(I, ArgNo, false, Ty, Align(1)); diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index fb10a99d1338..7b3741d19a1b 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -304,6 +304,7 @@ public: static bool isStandardLifetime(const AllocaInfo &AllocaInfo, const DominatorTree &DT); bool instrumentStack( + bool ShouldDetectUseAfterScope, MapVector<AllocaInst *, AllocaInfo> &AllocasToInstrument, SmallVector<Instruction *, 4> &UnrecognizedLifetimes, DenseMap<AllocaInst *, std::vector<DbgVariableIntrinsic *>> &AllocaDbgMap, @@ -1359,6 +1360,7 @@ bool HWAddressSanitizer::isStandardLifetime(const AllocaInfo &AllocaInfo, } bool HWAddressSanitizer::instrumentStack( + bool ShouldDetectUseAfterScope, MapVector<AllocaInst *, AllocaInfo> &AllocasToInstrument, SmallVector<Instruction *, 4> &UnrecognizedLifetimes, DenseMap<AllocaInst *, std::vector<DbgVariableIntrinsic *>> &AllocaDbgMap, @@ -1410,7 +1412,7 @@ bool HWAddressSanitizer::instrumentStack( }; bool StandardLifetime = UnrecognizedLifetimes.empty() && isStandardLifetime(Info, GetDT()); - if (DetectUseAfterScope && StandardLifetime) { + if (ShouldDetectUseAfterScope && StandardLifetime) { IntrinsicInst *Start = Info.LifetimeStart[0]; IRB.SetInsertPoint(Start->getNextNode()); tagAlloca(IRB, AI, Tag, Size); @@ -1505,8 +1507,14 @@ bool HWAddressSanitizer::sanitizeFunction( SmallVector<Instruction *, 8> LandingPadVec; SmallVector<Instruction *, 4> UnrecognizedLifetimes; DenseMap<AllocaInst *, std::vector<DbgVariableIntrinsic *>> AllocaDbgMap; + bool CallsReturnTwice = false; for (auto &BB : F) { for (auto &Inst : BB) { + if (CallInst *CI = dyn_cast<CallInst>(&Inst)) { + if (CI->canReturnTwice()) { + CallsReturnTwice = true; + } + } if (InstrumentStack) { if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) { if (isInterestingAlloca(*AI)) @@ -1531,9 +1539,14 @@ bool HWAddressSanitizer::sanitizeFunction( } } - if (isa<ReturnInst>(Inst) || isa<ResumeInst>(Inst) || - isa<CleanupReturnInst>(Inst)) + if (isa<ReturnInst>(Inst)) { + if (CallInst *CI = Inst.getParent()->getTerminatingMustTailCall()) + RetVec.push_back(CI); + else + RetVec.push_back(&Inst); + } else if (isa<ResumeInst, CleanupReturnInst>(Inst)) { RetVec.push_back(&Inst); + } if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst)) { for (Value *V : DVI->location_ops()) { @@ -1585,7 +1598,12 @@ bool HWAddressSanitizer::sanitizeFunction( if (!AllocasToInstrument.empty()) { Value *StackTag = ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB); - instrumentStack(AllocasToInstrument, UnrecognizedLifetimes, AllocaDbgMap, + // Calls to functions that may return twice (e.g. setjmp) confuse the + // postdominator analysis, and will leave us to keep memory tagged after + // function return. Work around this by always untagging at every return + // statement if return_twice functions are called. + instrumentStack(DetectUseAfterScope && !CallsReturnTwice, + AllocasToInstrument, UnrecognizedLifetimes, AllocaDbgMap, RetVec, StackTag, GetDT, GetPDT); } // Pad and align each of the allocas that we instrumented to stop small diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index ab179b03dd29..6868408ef5f5 100644 --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -456,6 +456,9 @@ bool InstrProfiling::lowerIntrinsics(Function *F) { } else if (auto *IPI = dyn_cast<InstrProfIncrementInst>(&Instr)) { lowerIncrement(IPI); MadeChange = true; + } else if (auto *IPC = dyn_cast<InstrProfCoverInst>(&Instr)) { + lowerCover(IPC); + MadeChange = true; } else if (auto *IPVP = dyn_cast<InstrProfValueProfileInst>(&Instr)) { lowerValueProfileInst(IPVP); MadeChange = true; @@ -539,7 +542,8 @@ static bool containsProfilingIntrinsics(Module &M) { return !F->use_empty(); return false; }; - return containsIntrinsic(llvm::Intrinsic::instrprof_increment) || + return containsIntrinsic(llvm::Intrinsic::instrprof_cover) || + containsIntrinsic(llvm::Intrinsic::instrprof_increment) || containsIntrinsic(llvm::Intrinsic::instrprof_increment_step) || containsIntrinsic(llvm::Intrinsic::instrprof_value_profile); } @@ -689,47 +693,58 @@ void InstrProfiling::lowerValueProfileInst(InstrProfValueProfileInst *Ind) { Ind->eraseFromParent(); } -void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { - GlobalVariable *Counters = getOrCreateRegionCounters(Inc); +Value *InstrProfiling::getCounterAddress(InstrProfInstBase *I) { + auto *Counters = getOrCreateRegionCounters(I); + IRBuilder<> Builder(I); - IRBuilder<> Builder(Inc); - uint64_t Index = Inc->getIndex()->getZExtValue(); - Value *Addr = Builder.CreateConstInBoundsGEP2_32(Counters->getValueType(), - Counters, 0, Index); + auto *Addr = Builder.CreateConstInBoundsGEP2_32( + Counters->getValueType(), Counters, 0, I->getIndex()->getZExtValue()); - if (isRuntimeCounterRelocationEnabled()) { - Type *Int64Ty = Type::getInt64Ty(M->getContext()); - Type *Int64PtrTy = Type::getInt64PtrTy(M->getContext()); - Function *Fn = Inc->getParent()->getParent(); - Instruction &I = Fn->getEntryBlock().front(); - LoadInst *LI = dyn_cast<LoadInst>(&I); - if (!LI) { - IRBuilder<> Builder(&I); - 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); + if (!isRuntimeCounterRelocationEnabled()) + return Addr; + + Type *Int64Ty = Type::getInt64Ty(M->getContext()); + Function *Fn = I->getParent()->getParent(); + Instruction &EntryI = Fn->getEntryBlock().front(); + LoadInst *LI = dyn_cast<LoadInst>(&EntryI); + if (!LI) { + IRBuilder<> EntryBuilder(&EntryI); + auto *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())); } - auto *Add = Builder.CreateAdd(Builder.CreatePtrToInt(Addr, Int64Ty), LI); - Addr = Builder.CreateIntToPtr(Add, Int64PtrTy); + LI = EntryBuilder.CreateLoad(Int64Ty, Bias); } + auto *Add = Builder.CreateAdd(Builder.CreatePtrToInt(Addr, Int64Ty), LI); + return Builder.CreateIntToPtr(Add, Addr->getType()); +} + +void InstrProfiling::lowerCover(InstrProfCoverInst *CoverInstruction) { + auto *Addr = getCounterAddress(CoverInstruction); + IRBuilder<> Builder(CoverInstruction); + // We store zero to represent that this block is covered. + Builder.CreateStore(Builder.getInt8(0), Addr); + CoverInstruction->eraseFromParent(); +} + +void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { + auto *Addr = getCounterAddress(Inc); + IRBuilder<> Builder(Inc); if (Options.Atomic || AtomicCounterUpdateAll || - (Index == 0 && AtomicFirstCounter)) { + (Inc->getIndex()->isZeroValue() && AtomicFirstCounter)) { Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, Inc->getStep(), MaybeAlign(), AtomicOrdering::Monotonic); } else { @@ -849,6 +864,31 @@ static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) { } GlobalVariable * +InstrProfiling::createRegionCounters(InstrProfInstBase *Inc, StringRef Name, + GlobalValue::LinkageTypes Linkage) { + uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); + auto &Ctx = M->getContext(); + GlobalVariable *GV; + if (isa<InstrProfCoverInst>(Inc)) { + auto *CounterTy = Type::getInt8Ty(Ctx); + auto *CounterArrTy = ArrayType::get(CounterTy, NumCounters); + // TODO: `Constant::getAllOnesValue()` does not yet accept an array type. + std::vector<Constant *> InitialValues(NumCounters, + Constant::getAllOnesValue(CounterTy)); + GV = new GlobalVariable(*M, CounterArrTy, false, Linkage, + ConstantArray::get(CounterArrTy, InitialValues), + Name); + GV->setAlignment(Align(1)); + } else { + auto *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters); + GV = new GlobalVariable(*M, CounterTy, false, Linkage, + Constant::getNullValue(CounterTy), Name); + GV->setAlignment(Align(8)); + } + return GV; +} + +GlobalVariable * InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) { GlobalVariable *NamePtr = Inc->getName(); auto &PD = ProfileDataMap[NamePtr]; @@ -914,16 +954,11 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) { uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); LLVMContext &Ctx = M->getContext(); - ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters); - // Create the counters variable. - auto *CounterPtr = - new GlobalVariable(*M, CounterTy, false, Linkage, - Constant::getNullValue(CounterTy), CntsVarName); + auto *CounterPtr = createRegionCounters(Inc, CntsVarName, Linkage); CounterPtr->setVisibility(Visibility); CounterPtr->setSection( getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat())); - CounterPtr->setAlignment(Align(8)); MaybeSetComdat(CounterPtr); CounterPtr->setLinkage(Linkage); PD.RegionCounters = CounterPtr; diff --git a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp index 8fedefccf0e1..5e078f2c4212 100644 --- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index cfe993dedbc2..c51acdf52f14 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -182,6 +182,7 @@ #include "llvm/IR/ValueMap.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" +#include "llvm/Support/Alignment.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -1718,11 +1719,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { // Figure out maximal valid memcpy alignment. const Align ArgAlign = DL.getValueOrABITypeAlignment( MaybeAlign(FArg.getParamAlignment()), FArg.getParamByValType()); - Value *CpShadowPtr = + Value *CpShadowPtr, *CpOriginPtr; + std::tie(CpShadowPtr, CpOriginPtr) = getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign, - /*isStore*/ true) - .first; - // TODO(glider): need to copy origins. + /*isStore*/ true); if (!PropagateShadow || Overflow) { // ParamTLS overflow. EntryIRB.CreateMemSet( @@ -1735,6 +1735,19 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { CopyAlign, Size); LLVM_DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n"); (void)Cpy; + + if (MS.TrackOrigins) { + Value *OriginPtr = + getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset); + // FIXME: OriginSize should be: + // alignTo(V % kMinOriginAlignment + Size, kMinOriginAlignment) + unsigned OriginSize = alignTo(Size, kMinOriginAlignment); + EntryIRB.CreateMemCpy( + CpOriginPtr, + /* by getShadowOriginPtr */ kMinOriginAlignment, OriginPtr, + /* by origin_tls[ArgOffset] */ kMinOriginAlignment, + OriginSize); + } } } @@ -3701,7 +3714,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { insertShadowCheck(A, &CB); Size = DL.getTypeAllocSize(A->getType()); } else { - bool ArgIsInitialized = false; Value *Store = nullptr; // Compute the Shadow for arg even if it is ByVal, because // in that case getShadow() will copy the actual arg shadow to @@ -3722,10 +3734,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { MaybeAlign Alignment = llvm::None; if (ParamAlignment) Alignment = std::min(*ParamAlignment, kShadowTLSAlignment); - Value *AShadowPtr = + Value *AShadowPtr, *AOriginPtr; + std::tie(AShadowPtr, AOriginPtr) = getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), Alignment, - /*isStore*/ false) - .first; + /*isStore*/ false); if (!PropagateShadow) { Store = IRB.CreateMemSet(ArgShadowBase, Constant::getNullValue(IRB.getInt8Ty()), @@ -3733,6 +3745,17 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { } else { Store = IRB.CreateMemCpy(ArgShadowBase, Alignment, AShadowPtr, Alignment, Size); + if (MS.TrackOrigins) { + Value *ArgOriginBase = getOriginPtrForArgument(A, IRB, ArgOffset); + // FIXME: OriginSize should be: + // alignTo(A % kMinOriginAlignment + Size, kMinOriginAlignment) + unsigned OriginSize = alignTo(Size, kMinOriginAlignment); + IRB.CreateMemCpy( + ArgOriginBase, + /* by origin_tls[ArgOffset] */ kMinOriginAlignment, + AOriginPtr, + /* by getShadowOriginPtr */ kMinOriginAlignment, OriginSize); + } } } else { // Any other parameters mean we need bit-grained tracking of uninit @@ -3743,12 +3766,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { Store = IRB.CreateAlignedStore(ArgShadow, ArgShadowBase, kShadowTLSAlignment); Constant *Cst = dyn_cast<Constant>(ArgShadow); - if (Cst && Cst->isNullValue()) - ArgIsInitialized = true; + if (MS.TrackOrigins && !(Cst && Cst->isNullValue())) { + IRB.CreateStore(getOrigin(A), + getOriginPtrForArgument(A, IRB, ArgOffset)); + } } - if (MS.TrackOrigins && !ArgIsInitialized) - IRB.CreateStore(getOrigin(A), - getOriginPtrForArgument(A, IRB, ArgOffset)); (void)Store; assert(Store != nullptr); LLVM_DEBUG(dbgs() << " Param:" << *Store << "\n"); diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp index c46415e5b1f4..0902a94452e3 100644 --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -255,6 +255,11 @@ static cl::opt<bool> PGOInstrumentEntry( "pgo-instrument-entry", cl::init(false), cl::Hidden, cl::desc("Force to instrument function entry basicblock.")); +static cl::opt<bool> PGOFunctionEntryCoverage( + "pgo-function-entry-coverage", cl::init(false), cl::Hidden, cl::ZeroOrMore, + cl::desc( + "Use this option to enable function entry coverage instrumentation.")); + static cl::opt<bool> PGOFixEntryCount("pgo-fix-entry-count", cl::init(true), cl::Hidden, cl::desc("Fix function entry count in profile use.")); @@ -337,6 +342,33 @@ static const char *ValueProfKindDescr[] = { #include "llvm/ProfileData/InstrProfData.inc" }; +// Create a COMDAT variable INSTR_PROF_RAW_VERSION_VAR to make the runtime +// aware this is an ir_level profile so it can set the version flag. +static GlobalVariable *createIRLevelProfileFlagVar(Module &M, bool IsCS) { + const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR)); + Type *IntTy64 = Type::getInt64Ty(M.getContext()); + uint64_t ProfileVersion = (INSTR_PROF_RAW_VERSION | VARIANT_MASK_IR_PROF); + if (IsCS) + ProfileVersion |= VARIANT_MASK_CSIR_PROF; + if (PGOInstrumentEntry) + ProfileVersion |= VARIANT_MASK_INSTR_ENTRY; + if (DebugInfoCorrelate) + ProfileVersion |= VARIANT_MASK_DBG_CORRELATE; + if (PGOFunctionEntryCoverage) + ProfileVersion |= + VARIANT_MASK_BYTE_COVERAGE | VARIANT_MASK_FUNCTION_ENTRY_ONLY; + auto IRLevelVersionVariable = new GlobalVariable( + M, IntTy64, true, GlobalValue::WeakAnyLinkage, + Constant::getIntegerValue(IntTy64, APInt(64, ProfileVersion)), VarName); + IRLevelVersionVariable->setVisibility(GlobalValue::DefaultVisibility); + Triple TT(M.getTargetTriple()); + if (TT.supportsCOMDAT()) { + IRLevelVersionVariable->setLinkage(GlobalValue::ExternalLinkage); + IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName)); + } + return IRLevelVersionVariable; +} + namespace { /// The select instruction visitor plays three roles specified @@ -469,9 +501,7 @@ private: createProfileFileNameVar(M, InstrProfileOutput); // The variable in a comdat may be discarded by LTO. Ensure the // declaration will be retained. - appendToCompilerUsed(M, createIRLevelProfileFlagVar(M, /*IsCS=*/true, - PGOInstrumentEntry, - DebugInfoCorrelate)); + appendToCompilerUsed(M, createIRLevelProfileFlagVar(M, /*IsCS=*/true)); return false; } std::string InstrProfileOutput; @@ -914,22 +944,39 @@ static void instrumentOneFunc( FuncPGOInstrumentation<PGOEdge, BBInfo> FuncInfo( F, TLI, ComdatMembers, true, BPI, BFI, IsCS, PGOInstrumentEntry); + + Type *I8PtrTy = Type::getInt8PtrTy(M->getContext()); + auto Name = ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy); + auto CFGHash = ConstantInt::get(Type::getInt64Ty(M->getContext()), + FuncInfo.FunctionHash); + if (PGOFunctionEntryCoverage) { + assert(!IsCS && + "entry coverge does not support context-sensitive instrumentation"); + auto &EntryBB = F.getEntryBlock(); + IRBuilder<> Builder(&EntryBB, EntryBB.getFirstInsertionPt()); + // llvm.instrprof.cover(i8* <name>, i64 <hash>, i32 <num-counters>, + // i32 <index>) + Builder.CreateCall( + Intrinsic::getDeclaration(M, Intrinsic::instrprof_cover), + {Name, CFGHash, Builder.getInt32(1), Builder.getInt32(0)}); + return; + } + std::vector<BasicBlock *> InstrumentBBs; FuncInfo.getInstrumentBBs(InstrumentBBs); unsigned NumCounters = InstrumentBBs.size() + FuncInfo.SIVisitor.getNumOfSelectInsts(); uint32_t I = 0; - Type *I8PtrTy = Type::getInt8PtrTy(M->getContext()); for (auto *InstrBB : InstrumentBBs) { IRBuilder<> Builder(InstrBB, InstrBB->getFirstInsertionPt()); assert(Builder.GetInsertPoint() != InstrBB->end() && "Cannot get the Instrumentation point"); + // llvm.instrprof.increment(i8* <name>, i64 <hash>, i32 <num-counters>, + // i32 <index>) Builder.CreateCall( Intrinsic::getDeclaration(M, Intrinsic::instrprof_increment), - {ConstantExpr::getBitCast(FuncInfo.FuncNameVar, I8PtrTy), - Builder.getInt64(FuncInfo.FunctionHash), Builder.getInt32(NumCounters), - Builder.getInt32(I++)}); + {Name, CFGHash, Builder.getInt32(NumCounters), Builder.getInt32(I++)}); } // Now instrument select instructions: @@ -1502,6 +1549,8 @@ void PGOUseFunc::annotateIrrLoopHeaderWeights() { } void SelectInstVisitor::instrumentOneSelectInst(SelectInst &SI) { + if (PGOFunctionEntryCoverage) + return; Module *M = F.getParent(); IRBuilder<> Builder(&SI); Type *Int64Ty = Builder.getInt64Ty(); @@ -1622,8 +1671,7 @@ static bool InstrumentAllFunctions( // For the context-sensitve instrumentation, we should have a separated pass // (before LTO/ThinLTO linking) to create these variables. if (!IsCS) - createIRLevelProfileFlagVar(M, /*IsCS=*/false, PGOInstrumentEntry, - DebugInfoCorrelate); + createIRLevelProfileFlagVar(M, /*IsCS=*/false); std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers; collectComdatMembers(M, ComdatMembers); @@ -1645,9 +1693,7 @@ PGOInstrumentationGenCreateVar::run(Module &M, ModuleAnalysisManager &AM) { createProfileFileNameVar(M, CSInstrName); // The variable in a comdat may be discarded by LTO. Ensure the declaration // will be retained. - appendToCompilerUsed(M, createIRLevelProfileFlagVar(M, /*IsCS=*/true, - PGOInstrumentEntry, - DebugInfoCorrelate)); + appendToCompilerUsed(M, createIRLevelProfileFlagVar(M, /*IsCS=*/true)); return PreservedAnalyses::all(); } @@ -1844,6 +1890,18 @@ static bool annotateAllFunctions( ProfileFileName.data(), "Not an IR level instrumentation profile")); return false; } + if (PGOReader->hasSingleByteCoverage()) { + Ctx.diagnose(DiagnosticInfoPGOProfile( + ProfileFileName.data(), + "Cannot use coverage profiles for optimization")); + return false; + } + if (PGOReader->functionEntryOnly()) { + Ctx.diagnose(DiagnosticInfoPGOProfile( + ProfileFileName.data(), + "Function entry profiles are not yet supported for optimization")); + return false; + } // Add the profile summary (read from the header of the indexed summary) here // so that we can use it below when reading counters (which checks if the |
