Skip to content

Commit 397ac44

Browse files
authored
[Coverage] Introduce the type CounterPair for RegionCounterMap. NFC. (#112724)
`CounterPair` can hold `<uint32_t, uint32_t>` instead of current `unsigned`, to hold also the counter number of SkipPath. For now, this change provides the skeleton and only `CounterPair::Executed` is used. Each counter number can have `None` to suppress emitting counter increment. 2nd element `Skipped` is initialized as `None` by default, since most `Stmt*` don't have a pair of counters. This change also provides stubs for the verifier. I'll provide the impl of verifier for `+Asserts` later. `markStmtAsUsed(bool, Stmt*)` may be used to inform that other side counter may not emitted. `markStmtMaybeUsed(S)` may be used for the `Stmt` and its inner will be excluded for emission in the case of skipping by constant folding. I put it into places where I found. `verifyCounterMap()` will check the coverage map and the counter map, and can be used to report inconsistency. These verifier methods shall be eliminated in `-Asserts`. https://discourse.llvm.org/t/rfc-integrating-singlebytecoverage-with-branch-coverage/82492
1 parent d30a5fc commit 397ac44

File tree

11 files changed

+113
-16
lines changed

11 files changed

+113
-16
lines changed

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
361361
return GV;
362362
}
363363

364+
PGO.markStmtMaybeUsed(D.getInit()); // FIXME: Too lazy
365+
364366
#ifndef NDEBUG
365367
CharUnits VarSize = CGM.getContext().getTypeSizeInChars(D.getType()) +
366368
D.getFlexibleArrayInitChars(getContext());
@@ -1868,7 +1870,10 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
18681870
// If we are at an unreachable point, we don't need to emit the initializer
18691871
// unless it contains a label.
18701872
if (!HaveInsertPoint()) {
1871-
if (!Init || !ContainsLabel(Init)) return;
1873+
if (!Init || !ContainsLabel(Init)) {
1874+
PGO.markStmtMaybeUsed(Init);
1875+
return;
1876+
}
18721877
EnsureInsertPoint();
18731878
}
18741879

@@ -1979,6 +1984,8 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
19791984
return EmitExprAsInit(Init, &D, lv, capturedByInit);
19801985
}
19811986

1987+
PGO.markStmtMaybeUsed(Init);
1988+
19821989
if (!emission.IsConstantAggregate) {
19831990
// For simple scalar/complex initialization, store the value directly.
19841991
LValue lv = MakeAddrLValue(Loc, type);

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5148,6 +5148,7 @@ std::optional<LValue> HandleConditionalOperatorLValueSimpleCase(
51485148
// If the true case is live, we need to track its region.
51495149
if (CondExprBool)
51505150
CGF.incrementProfileCounter(E);
5151+
CGF.markStmtMaybeUsed(Dead);
51515152
// If a throw expression we emit it and return an undefined lvalue
51525153
// because it can't be used.
51535154
if (auto *ThrowExpr = dyn_cast<CXXThrowExpr>(Live->IgnoreParens())) {

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5003,7 +5003,8 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
50035003
CGF.incrementProfileCounter(E->getRHS());
50045004
CGF.EmitBranch(FBlock);
50055005
CGF.EmitBlock(FBlock);
5006-
}
5006+
} else
5007+
CGF.markStmtMaybeUsed(E->getRHS());
50075008

50085009
CGF.MCDCLogOpStack.pop_back();
50095010
// If the top of the logical operator nest, update the MCDC bitmap.
@@ -5015,8 +5016,10 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
50155016
}
50165017

50175018
// 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
5018-
if (!CGF.ContainsLabel(E->getRHS()))
5019+
if (!CGF.ContainsLabel(E->getRHS())) {
5020+
CGF.markStmtMaybeUsed(E->getRHS());
50195021
return llvm::Constant::getNullValue(ResTy);
5022+
}
50205023
}
50215024

50225025
// If the top of the logical operator nest, reset the MCDC temp to 0.
@@ -5143,7 +5146,8 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
51435146
CGF.incrementProfileCounter(E->getRHS());
51445147
CGF.EmitBranch(FBlock);
51455148
CGF.EmitBlock(FBlock);
5146-
}
5149+
} else
5150+
CGF.markStmtMaybeUsed(E->getRHS());
51475151

51485152
CGF.MCDCLogOpStack.pop_back();
51495153
// If the top of the logical operator nest, update the MCDC bitmap.
@@ -5155,8 +5159,10 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
51555159
}
51565160

51575161
// 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
5158-
if (!CGF.ContainsLabel(E->getRHS()))
5162+
if (!CGF.ContainsLabel(E->getRHS())) {
5163+
CGF.markStmtMaybeUsed(E->getRHS());
51595164
return llvm::ConstantInt::get(ResTy, 1);
5165+
}
51605166
}
51615167

51625168
// If the top of the logical operator nest, reset the MCDC temp to 0.
@@ -5280,6 +5286,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
52805286
CGF.incrementProfileCounter(E);
52815287
}
52825288
Value *Result = Visit(live);
5289+
CGF.markStmtMaybeUsed(dead);
52835290

52845291
// If the live part is a throw expression, it acts like it has a void
52855292
// type, so evaluating it returns a null Value*. However, a conditional

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
7676
// Verify that any decl statements were handled as simple, they may be in
7777
// scope of subsequent reachable statements.
7878
assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!");
79+
PGO.markStmtMaybeUsed(S);
7980
return;
8081
}
8182

@@ -875,6 +876,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
875876
RunCleanupsScope ExecutedScope(*this);
876877
EmitStmt(Executed);
877878
}
879+
PGO.markStmtMaybeUsed(Skipped);
878880
return;
879881
}
880882
}
@@ -2197,6 +2199,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
21972199
for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
21982200
EmitStmt(CaseStmts[i]);
21992201
incrementProfileCounter(&S);
2202+
PGO.markStmtMaybeUsed(S.getBody());
22002203

22012204
// Now we want to restore the saved switch instance so that nested
22022205
// switches continue to function properly

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
16161616
// Emit the standard function epilogue.
16171617
FinishFunction(BodyRange.getEnd());
16181618

1619+
PGO.verifyCounterMap();
1620+
16191621
// If we haven't marked the function nothrow through other means, do
16201622
// a quick pass now to see if we can.
16211623
if (!CurFn->doesNotThrow())
@@ -1738,6 +1740,7 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
17381740
if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
17391741
return false; // Contains a label.
17401742

1743+
PGO.markStmtMaybeUsed(Cond);
17411744
ResultInt = Int;
17421745
return true;
17431746
}

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,13 @@ class CodeGenFunction : public CodeGenTypeCache {
16201620
uint64_t LoopCount) const;
16211621

16221622
public:
1623+
auto getIsCounterPair(const Stmt *S) const { return PGO.getIsCounterPair(S); }
1624+
1625+
void markStmtAsUsed(bool Skipped, const Stmt *S) {
1626+
PGO.markStmtAsUsed(Skipped, S);
1627+
}
1628+
void markStmtMaybeUsed(const Stmt *S) { PGO.markStmtMaybeUsed(S); }
1629+
16231630
/// Increment the profiler's counter for the given statement by \p StepV.
16241631
/// If \p StepV is null, the default increment is 1.
16251632
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) {

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,50 @@ enum ForDefinition_t : bool {
102102
ForDefinition = true
103103
};
104104

105+
/// The Counter with an optional additional Counter for
106+
/// branches. `Skipped` counter can be calculated with `Executed` and
107+
/// a common Counter (like `Parent`) as `(Parent-Executed)`.
108+
///
109+
/// In SingleByte mode, Counters are binary. Subtraction is not
110+
/// applicable (but addition is capable). In this case, both
111+
/// `Executed` and `Skipped` counters are required. `Skipped` is
112+
/// `None` by default. It is allocated in the coverage mapping.
113+
///
114+
/// There might be cases that `Parent` could be induced with
115+
/// `(Executed+Skipped)`. This is not always applicable.
116+
class CounterPair {
117+
public:
118+
/// Optional value.
119+
class ValueOpt {
120+
private:
121+
static constexpr uint32_t None = (1u << 31); /// None is allocated.
122+
static constexpr uint32_t Mask = None - 1;
123+
124+
uint32_t Val;
125+
126+
public:
127+
ValueOpt() : Val(None) {}
128+
129+
ValueOpt(unsigned InitVal) {
130+
assert(!(InitVal & ~Mask));
131+
Val = InitVal;
132+
}
133+
134+
bool hasValue() const { return !(Val & None); }
135+
136+
operator uint32_t() const { return Val; }
137+
};
138+
139+
ValueOpt Executed;
140+
ValueOpt Skipped; /// May be None.
141+
142+
/// Initialized with Skipped=None.
143+
CounterPair(unsigned Val) : Executed(Val) {}
144+
145+
// FIXME: Should work with {None, None}
146+
CounterPair() : Executed(0) {}
147+
};
148+
105149
struct OrderGlobalInitsOrStermFinalizers {
106150
unsigned int priority;
107151
unsigned int lex_order;

clang/lib/CodeGen/CodeGenPGO.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
163163
/// The function hash.
164164
PGOHash Hash;
165165
/// The map of statements to counters.
166-
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
166+
llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
167167
/// The state of MC/DC Coverage in this function.
168168
MCDC::State &MCDCState;
169169
/// Maximum number of supported MC/DC conditions in a boolean expression.
@@ -174,7 +174,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
174174
DiagnosticsEngine &Diag;
175175

176176
MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion,
177-
llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
177+
llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
178178
MCDC::State &MCDCState, unsigned MCDCMaxCond,
179179
DiagnosticsEngine &Diag)
180180
: NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
@@ -1083,7 +1083,7 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
10831083
(CGM.getCodeGenOpts().MCDCCoverage ? CGM.getCodeGenOpts().MCDCMaxConds
10841084
: 0);
10851085

1086-
RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
1086+
RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, CounterPair>);
10871087
RegionMCDCState.reset(new MCDC::State);
10881088
MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
10891089
*RegionMCDCState, MCDCMaxConditions, CGM.getDiags());
@@ -1185,12 +1185,23 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
11851185
Fn->setEntryCount(FunctionCount);
11861186
}
11871187

1188+
std::pair<bool, bool> CodeGenPGO::getIsCounterPair(const Stmt *S) const {
1189+
if (!RegionCounterMap)
1190+
return {false, false};
1191+
1192+
auto I = RegionCounterMap->find(S);
1193+
if (I == RegionCounterMap->end())
1194+
return {false, false};
1195+
1196+
return {I->second.Executed.hasValue(), I->second.Skipped.hasValue()};
1197+
}
1198+
11881199
void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
11891200
llvm::Value *StepV) {
11901201
if (!RegionCounterMap || !Builder.GetInsertBlock())
11911202
return;
11921203

1193-
unsigned Counter = (*RegionCounterMap)[S];
1204+
unsigned Counter = (*RegionCounterMap)[S].Executed;
11941205

11951206
// Make sure that pointer to global is passed in with zero addrspace
11961207
// This is relevant during GPU profiling

clang/lib/CodeGen/CodeGenPGO.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class CodeGenPGO {
3535
std::array <unsigned, llvm::IPVK_Last + 1> NumValueSites;
3636
unsigned NumRegionCounters;
3737
uint64_t FunctionHash;
38-
std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap;
38+
std::unique_ptr<llvm::DenseMap<const Stmt *, CounterPair>> RegionCounterMap;
3939
std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap;
4040
std::unique_ptr<llvm::InstrProfRecord> ProfRecord;
4141
std::unique_ptr<MCDC::State> RegionMCDCState;
@@ -110,6 +110,7 @@ class CodeGenPGO {
110110
bool canEmitMCDCCoverage(const CGBuilderTy &Builder);
111111

112112
public:
113+
std::pair<bool, bool> getIsCounterPair(const Stmt *S) const;
113114
void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
114115
llvm::Value *StepV);
115116
void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
@@ -122,6 +123,18 @@ class CodeGenPGO {
122123
Address MCDCCondBitmapAddr, llvm::Value *Val,
123124
CodeGenFunction &CGF);
124125

126+
void markStmtAsUsed(bool Skipped, const Stmt *S) {
127+
// Do nothing.
128+
}
129+
130+
void markStmtMaybeUsed(const Stmt *S) {
131+
// Do nothing.
132+
}
133+
134+
void verifyCounterMap() const {
135+
// Do nothing.
136+
}
137+
125138
/// Return the region count for the counter at the given index.
126139
uint64_t getRegionCount(const Stmt *S) {
127140
if (!RegionCounterMap)
@@ -130,7 +143,7 @@ class CodeGenPGO {
130143
return 0;
131144
// With profiles from a differing version of clang we can have mismatched
132145
// decl counts. Don't crash in such a case.
133-
auto Index = (*RegionCounterMap)[S];
146+
auto Index = (*RegionCounterMap)[S].Executed;
134147
if (Index >= RegionCounts.size())
135148
return 0;
136149
return RegionCounts[Index];

clang/lib/CodeGen/CoverageMappingGen.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ struct CounterCoverageMappingBuilder
882882
: public CoverageMappingBuilder,
883883
public ConstStmtVisitor<CounterCoverageMappingBuilder> {
884884
/// The map of statements to count values.
885-
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
885+
llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
886886

887887
MCDC::State &MCDCState;
888888

@@ -931,7 +931,7 @@ struct CounterCoverageMappingBuilder
931931
///
932932
/// This should only be called on statements that have a dedicated counter.
933933
Counter getRegionCounter(const Stmt *S) {
934-
return Counter::getCounter(CounterMap[S]);
934+
return Counter::getCounter(CounterMap[S].Executed);
935935
}
936936

937937
struct BranchCounterPair {
@@ -1457,7 +1457,7 @@ struct CounterCoverageMappingBuilder
14571457

14581458
CounterCoverageMappingBuilder(
14591459
CoverageMappingModuleGen &CVM,
1460-
llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
1460+
llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
14611461
MCDC::State &MCDCState, SourceManager &SM, const LangOptions &LangOpts)
14621462
: CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
14631463
MCDCState(MCDCState), MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {}

clang/lib/CodeGen/CoverageMappingGen.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class CoverageSourceInfo : public PPCallbacks,
9595
namespace CodeGen {
9696

9797
class CodeGenModule;
98+
class CounterPair;
9899

99100
namespace MCDC {
100101
struct State;
@@ -158,7 +159,7 @@ class CoverageMappingGen {
158159
CoverageMappingModuleGen &CVM;
159160
SourceManager &SM;
160161
const LangOptions &LangOpts;
161-
llvm::DenseMap<const Stmt *, unsigned> *CounterMap;
162+
llvm::DenseMap<const Stmt *, CounterPair> *CounterMap;
162163
MCDC::State *MCDCState;
163164

164165
public:
@@ -169,7 +170,7 @@ class CoverageMappingGen {
169170

170171
CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
171172
const LangOptions &LangOpts,
172-
llvm::DenseMap<const Stmt *, unsigned> *CounterMap,
173+
llvm::DenseMap<const Stmt *, CounterPair> *CounterMap,
173174
MCDC::State *MCDCState)
174175
: CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap),
175176
MCDCState(MCDCState) {}

0 commit comments

Comments
 (0)