Author: NAKAMURA Takumi Date: 2026-01-10T09:56:15+09:00 New Revision: 8a7d8c1690c444c2151852e983e4bccc3825250f
URL: https://github.com/llvm/llvm-project/commit/8a7d8c1690c444c2151852e983e4bccc3825250f DIFF: https://github.com/llvm/llvm-project/commit/8a7d8c1690c444c2151852e983e4bccc3825250f.diff LOG: [Coverage] Make additional counters available for BranchRegion. NFC. (#120930) `getBranchCounterPair()` allocates an additional Counter to SkipPath in `SingleByteCoverage`. `IsCounterEqual()` calculates the comparison with rewinding counter replacements. `NumRegionCounters` is updated to take additional counters in account. `incrementProfileCounter()` has a few additiona arguments. - `UseSkipPath=true`, to specify setting counters for SkipPath. It assumes `UseSkipPath=false` is used together. - `UseBoth` may be specified for marking another path. It introduces the same effect as issueing `markStmtAsUsed(!SkipPath, S)`. `llvm-cov` discovers counters in `FalseCount` to allocate `MaxCounterID` for empty profile data. https://discourse.llvm.org/t/rfc-integrating-singlebytecoverage-with-branch-coverage/82492 Resumes: #112730 Depends on: #112698 #112702 #112724 Added: Modified: clang/lib/CodeGen/CodeGenFunction.h clang/lib/CodeGen/CodeGenPGO.cpp clang/lib/CodeGen/CodeGenPGO.h clang/lib/CodeGen/CoverageMappingGen.cpp llvm/lib/ProfileData/Coverage/CoverageMapping.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 855e43631f436..13c8f2002aad9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1662,9 +1662,31 @@ class CodeGenFunction : public CodeGenTypeCache { void markStmtAsUsed(bool Skipped, const Stmt *S); void markStmtMaybeUsed(const Stmt *S); + /// Used to specify which counter in a pair shall be incremented. + /// For non-binary counters, a skip counter is derived as (Parent - Exec). + /// In contrast for binary counters, a skip counter cannot be computed from + /// the Parent counter. In such cases, dedicated SkipPath counters must be + /// allocated and marked (incremented as binary counters). (Parent can be + /// synthesized with (Exec + Skip) in simple cases) + enum CounterForIncrement { + UseExecPath = 0, ///< Exec (true) + UseSkipPath, ///< Skip (false) + }; + /// Increment the profiler's counter for the given statement by \p StepV. /// If \p StepV is null, the default increment is 1. - void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr); + void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) { + incrementProfileCounter(UseExecPath, S, false, StepV); + } + + /// Emit increment of Counter. + /// \param ExecSkip Use `Skipped` Counter if UseSkipPath is specified. + /// \param S The Stmt that Counter is associated. + /// \param UseBoth Mark both Exec/Skip as used. (for verification) + /// \param StepV The offset Value for adding to Counter. + void incrementProfileCounter(CounterForIncrement ExecSkip, const Stmt *S, + bool UseBoth = false, + llvm::Value *StepV = nullptr); bool isMCDCCoverageEnabled() const { return (CGM.getCodeGenOpts().hasProfileClangInstr() && diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 8731a2f93646a..d23f1a9aa5142 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1135,6 +1135,16 @@ void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { if (CoverageMapping.empty()) return; + // Scan max(FalseCnt) and update NumRegionCounters. + unsigned MaxNumCounters = NumRegionCounters; + for (const auto [_, V] : *RegionCounterMap) { + assert((!V.Executed.hasValue() || MaxNumCounters > V.Executed) && + "TrueCnt should not be reassigned"); + if (V.Skipped.hasValue()) + MaxNumCounters = std::max(MaxNumCounters, V.Skipped + 1); + } + NumRegionCounters = MaxNumCounters; + CGM.getCoverageMapping()->addFunctionMappingRecord( FuncNameVar, FuncName, FunctionHash, CoverageMapping); } @@ -1195,11 +1205,21 @@ std::pair<bool, bool> CodeGenPGO::getIsCounterPair(const Stmt *S) const { } void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, + bool UseSkipPath, bool UseBoth, llvm::Value *StepV) { - if (!RegionCounterMap || !Builder.GetInsertBlock()) + if (!RegionCounterMap) return; - unsigned Counter = (*RegionCounterMap)[S].Executed; + // Allocate S in the Map regardless of emission. + const auto &TheCounterPair = (*RegionCounterMap)[S]; + + if (!Builder.GetInsertBlock()) + return; + + const CounterPair::ValueOpt &Counter = + (UseSkipPath ? TheCounterPair.Skipped : TheCounterPair.Executed); + if (!Counter.hasValue()) + return; // Make sure that pointer to global is passed in with zero addrspace // This is relevant during GPU profiling @@ -1510,13 +1530,15 @@ CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond, std::max(*CondCount, LoopCount) - LoopCount); } -void CodeGenFunction::incrementProfileCounter(const Stmt *S, +void CodeGenFunction::incrementProfileCounter(CounterForIncrement ExecSkip, + const Stmt *S, bool UseBoth, llvm::Value *StepV) { if (CGM.getCodeGenOpts().hasProfileClangInstr() && !CurFn->hasFnAttribute(llvm::Attribute::NoProfile) && !CurFn->hasFnAttribute(llvm::Attribute::SkipProfile)) { auto AL = ApplyDebugLocation::CreateArtificial(*this); - PGO->emitCounterSetOrIncrement(Builder, S, StepV); + PGO->emitCounterSetOrIncrement(Builder, S, (ExecSkip == UseSkipPath), + UseBoth, StepV); } PGO->setCurrentStmt(S); } diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 1944b640951d5..da386f41c0aea 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -112,6 +112,7 @@ class CodeGenPGO { public: std::pair<bool, bool> getIsCounterPair(const Stmt *S) const; void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, + bool UseFalsePath, bool UseBoth, llvm::Value *StepV); void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr, diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 656f1466fddb6..9a6d3c9abecbd 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -886,6 +886,14 @@ struct CounterCoverageMappingBuilder /// The map of statements to count values. llvm::DenseMap<const Stmt *, CounterPair> &CounterMap; + /// Used to expand an allocatd SkipCnt to Expression with known counters. + /// Key: SkipCnt + /// Val: Subtract Expression + CounterExpressionBuilder::SubstMap MapToExpand; + + /// Index and number for additional counters for SkipCnt. + unsigned NextCounterNum; + MCDC::State &MCDCState; /// A stack of currently live regions. @@ -960,7 +968,8 @@ struct CounterCoverageMappingBuilder BranchCounterPair getBranchCounterPair(const Stmt *S, Counter ParentCnt, std::optional<Counter> SkipCntForOld = std::nullopt) { - Counter ExecCnt = getRegionCounter(S); + auto &TheMap = CounterMap[S]; + auto ExecCnt = Counter::getCounter(TheMap.Executed); // The old behavior of SingleByte is unaware of Branches. // Will be pruned after the migration of SingleByte. @@ -970,13 +979,44 @@ struct CounterCoverageMappingBuilder return {ExecCnt, *SkipCntForOld}; } - return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)}; + BranchCounterPair Counters = {ExecCnt, + Builder.subtract(ParentCnt, ExecCnt)}; + + if (!llvm::EnableSingleByteCoverage || !Counters.Skipped.isExpression()) { + assert( + !TheMap.Skipped.hasValue() && + "SkipCnt shouldn't be allocated but refer to an existing counter."); + return Counters; + } + + // Assign second if second is not assigned yet. + if (!TheMap.Skipped.hasValue()) + TheMap.Skipped = NextCounterNum++; + + // Replace an expression (ParentCnt - ExecCnt) with SkipCnt. + Counter SkipCnt = Counter::getCounter(TheMap.Skipped); + MapToExpand[SkipCnt] = Builder.subst(Counters.Skipped, MapToExpand); + Counters.Skipped = SkipCnt; + return Counters; } bool IsCounterEqual(Counter OutCount, Counter ParentCount) { if (OutCount == ParentCount) return true; + // Try comaparison with pre-replaced expressions. + // + // For example, getBranchCounterPair(#0) returns {#1, #0 - #1}. + // The sum of the pair should be equivalent to the Parent, #0. + // OTOH when (#0 - #1) is replaced with the new counter #2, + // The sum is (#1 + #2). If the reverse substitution #2 => (#0 - #1) + // can be applied, the sum can be transformed to (#1 + (#0 - #1)). + // To apply substitutions to both hand expressions, transform (LHS - RHS) + // and check isZero. + if (Builder.subst(Builder.subtract(OutCount, ParentCount), MapToExpand) + .isZero()) + return true; + return false; } @@ -1190,12 +1230,14 @@ struct CounterCoverageMappingBuilder /// and add it to the function's SourceRegions. /// Returns Counter that corresponds to SC. Counter createSwitchCaseRegion(const SwitchCase *SC, Counter ParentCount) { + Counter TrueCnt = getRegionCounter(SC); + Counter FalseCnt = (llvm::EnableSingleByteCoverage + ? Counter::getZero() // Folded + : subtractCounters(ParentCount, TrueCnt)); // Push region onto RegionStack but immediately pop it (which adds it to // the function's SourceRegions) because it doesn't apply to any other // source other than the SwitchCase. - Counter TrueCnt = getRegionCounter(SC); - popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), - subtractCounters(ParentCount, TrueCnt))); + popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt)); return TrueCnt; } @@ -1462,7 +1504,8 @@ struct CounterCoverageMappingBuilder llvm::DenseMap<const Stmt *, CounterPair> &CounterMap, MCDC::State &MCDCState, SourceManager &SM, const LangOptions &LangOpts) : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap), - MCDCState(MCDCState), MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {} + NextCounterNum(CounterMap.size()), MCDCState(MCDCState), + MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {} /// Write the mapping data to the output stream void write(llvm::raw_ostream &OS) { diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 429ec5c19f1f8..9d114afec9d51 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -637,6 +637,9 @@ static unsigned getMaxCounterID(const CounterMappingContext &Ctx, unsigned MaxCounterID = 0; for (const auto &Region : Record.MappingRegions) { MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count)); + if (Region.isBranch()) + MaxCounterID = + std::max(MaxCounterID, Ctx.getMaxCounterID(Region.FalseCount)); } return MaxCounterID; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
