Skip to content

[Coverage] Introduce getBranchCounterPair(). NFC. #112702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jan 9, 2025
Merged
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 116 additions & 82 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,37 @@ struct CounterCoverageMappingBuilder
return Counter::getCounter(CounterMap[S]);
}

struct BranchCounterPair {
Counter Executed;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments on member variables?

E.g.

/// Counter tracking number of times the branch was encountered and taken.
Counter Executed;

/// Counter tracking the number of times the branch was encountered, but not taken.
Counter Skipped;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still wonder which pair of names would fit best. I adopted "Exec" from BinOp stuff and applied "Skipped" since "Exit" would be an exaggeration. "Checked/Skipped" would make less sense. OTOH, "Taken/NotTaken" looks redundant. Better idea?

I want them self-explained.

Counter Skipped;
};

BranchCounterPair getBranchCounterPair(const Stmt *S, Counter ParentCnt) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add Doxygen comments for this?

I'd like to be able to know what, e.g. ParentCnt is only by looking at this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Counter ExecCnt = getRegionCounter(S);
return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
}

/// Returns {TrueCnt,FalseCnt} for "implicit default".
/// FalseCnt is considered as the False count on SwitchStmt.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment out of date?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSwitchImplicitDefaultCounterPair has been migrated to #113112. I suppose this explained what it did.
Note, I didn't migrate this using BranchCounterPair since I thought this was semantically different from others.

std::pair<Counter, Counter>
getSwitchImplicitDefaultCounterPair(const Stmt *Cond, Counter ParentCount,
Counter CaseCountSum) {
// Simplify is skipped while building the counters above: it can get
// really slow on top of switches with thousands of cases. Instead,
// trigger simplification by adding zero to the last counter.
CaseCountSum =
addCounters(CaseCountSum, Counter::getZero(), /*Simplify=*/true);

return {CaseCountSum, Builder.subtract(ParentCount, CaseCountSum)};
}

bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
if (OutCount == ParentCount)
return true;

return false;
}

/// Push a region onto the stack.
///
/// Returns the index on the stack where the region was pushed. This can be
Expand Down Expand Up @@ -1588,6 +1619,13 @@ struct CounterCoverageMappingBuilder
llvm::EnableSingleByteCoverage
? getRegionCounter(S->getCond())
: addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
auto [ExecCount, ExitCount] =
(llvm::EnableSingleByteCoverage
? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
: getBranchCounterPair(S, CondCount));
if (!llvm::EnableSingleByteCoverage) {
assert(ExecCount.isZero() || ExecCount == BodyCount);
}
propagateCounts(CondCount, S->getCond());
adjustForOutOfOrderTraversal(getEnd(S));

Expand All @@ -1596,13 +1634,11 @@ struct CounterCoverageMappingBuilder
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);

Counter OutCount =
llvm::EnableSingleByteCoverage
? getRegionCounter(S)
: addCounters(BC.BreakCount,
subtractCounters(CondCount, BodyCount));
Counter OutCount = llvm::EnableSingleByteCoverage
? getRegionCounter(S)
: addCounters(BC.BreakCount, ExitCount);

if (OutCount != ParentCount) {
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
if (BodyHasTerminateStmt)
Expand All @@ -1611,8 +1647,7 @@ struct CounterCoverageMappingBuilder

// Create Branch Region around condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(S->getCond(), BodyCount,
subtractCounters(CondCount, BodyCount));
createBranchRegion(S->getCond(), BodyCount, ExitCount);
}

void VisitDoStmt(const DoStmt *S) {
Expand Down Expand Up @@ -1641,22 +1676,26 @@ struct CounterCoverageMappingBuilder
Counter CondCount = llvm::EnableSingleByteCoverage
? getRegionCounter(S->getCond())
: addCounters(BackedgeCount, BC.ContinueCount);
auto [ExecCount, ExitCount] =
(llvm::EnableSingleByteCoverage
? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
: getBranchCounterPair(S, CondCount));
if (!llvm::EnableSingleByteCoverage) {
assert(ExecCount.isZero() || ExecCount == BodyCount);
}
propagateCounts(CondCount, S->getCond());

Counter OutCount =
llvm::EnableSingleByteCoverage
? getRegionCounter(S)
: addCounters(BC.BreakCount,
subtractCounters(CondCount, BodyCount));
if (OutCount != ParentCount) {
Counter OutCount = llvm::EnableSingleByteCoverage
? getRegionCounter(S)
: addCounters(BC.BreakCount, ExitCount);
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
}

// Create Branch Region around condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(S->getCond(), BodyCount,
subtractCounters(CondCount, BodyCount));
createBranchRegion(S->getCond(), BodyCount, ExitCount);

if (BodyHasTerminateStmt)
HasTerminateStmt = true;
Expand Down Expand Up @@ -1705,6 +1744,13 @@ struct CounterCoverageMappingBuilder
: addCounters(
addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
IncrementBC.ContinueCount);
auto [ExecCount, ExitCount] =
(llvm::EnableSingleByteCoverage
? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
: getBranchCounterPair(S, CondCount));
if (!llvm::EnableSingleByteCoverage) {
assert(ExecCount.isZero() || ExecCount == BodyCount);
}

if (const Expr *Cond = S->getCond()) {
propagateCounts(CondCount, Cond);
Expand All @@ -1719,9 +1765,8 @@ struct CounterCoverageMappingBuilder
Counter OutCount =
llvm::EnableSingleByteCoverage
? getRegionCounter(S)
: addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
subtractCounters(CondCount, BodyCount));
if (OutCount != ParentCount) {
: addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, ExitCount);
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
if (BodyHasTerminateStmt)
Expand All @@ -1730,8 +1775,7 @@ struct CounterCoverageMappingBuilder

// Create Branch Region around condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(S->getCond(), BodyCount,
subtractCounters(CondCount, BodyCount));
createBranchRegion(S->getCond(), BodyCount, ExitCount);
}

void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
Expand Down Expand Up @@ -1760,15 +1804,18 @@ struct CounterCoverageMappingBuilder
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);

Counter OutCount;
Counter ExitCount;
Counter LoopCount;
if (llvm::EnableSingleByteCoverage)
OutCount = getRegionCounter(S);
else {
LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
OutCount =
addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
auto [ExecCount, SkipCount] = getBranchCounterPair(S, LoopCount);
ExitCount = SkipCount;
assert(ExecCount.isZero() || ExecCount == BodyCount);
OutCount = addCounters(BC.BreakCount, ExitCount);
}
if (OutCount != ParentCount) {
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
if (BodyHasTerminateStmt)
Expand All @@ -1777,8 +1824,7 @@ struct CounterCoverageMappingBuilder

// Create Branch Region around condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(S->getCond(), BodyCount,
subtractCounters(LoopCount, BodyCount));
createBranchRegion(S->getCond(), BodyCount, ExitCount);
}

void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
Expand All @@ -1800,9 +1846,10 @@ struct CounterCoverageMappingBuilder

Counter LoopCount =
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
if (OutCount != ParentCount) {
auto [ExecCount, ExitCount] = getBranchCounterPair(S, LoopCount);
assert(ExecCount.isZero() || ExecCount == BodyCount);
Counter OutCount = addCounters(BC.BreakCount, ExitCount);
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
}
Expand Down Expand Up @@ -1873,15 +1920,9 @@ struct CounterCoverageMappingBuilder
// the hidden branch, which will be added later by the CodeGen. This region
// will be associated with the switch statement's condition.
if (!HasDefaultCase) {
// Simplify is skipped while building the counters above: it can get
// really slow on top of switches with thousands of cases. Instead,
// trigger simplification by adding zero to the last counter.
CaseCountSum =
addCounters(CaseCountSum, Counter::getZero(), /*Simplify=*/true);

// This is considered as the False count on SwitchStmt.
Counter SwitchFalse = subtractCounters(ParentCount, CaseCountSum);
createBranchRegion(S->getCond(), CaseCountSum, SwitchFalse);
auto Counters = getSwitchImplicitDefaultCounterPair(
S->getCond(), ParentCount, CaseCountSum);
createBranchRegion(S->getCond(), Counters.first, Counters.second);
}
}

Expand Down Expand Up @@ -2010,9 +2051,12 @@ struct CounterCoverageMappingBuilder
extendRegion(S->getCond());

Counter ParentCount = getRegion().getCounter();
Counter ThenCount = llvm::EnableSingleByteCoverage
? getRegionCounter(S->getThen())
: getRegionCounter(S);
auto [ThenCount, ElseCount] =
(llvm::EnableSingleByteCoverage
? BranchCounterPair{getRegionCounter(S->getThen()),
(S->getElse() ? getRegionCounter(S->getElse())
: Counter::getZero())}
: getBranchCounterPair(S, ParentCount));

// Emitting a counter for the condition makes it easier to interpret the
// counter for the body when looking at the coverage.
Expand All @@ -2027,12 +2071,6 @@ struct CounterCoverageMappingBuilder
extendRegion(S->getThen());
Counter OutCount = propagateCounts(ThenCount, S->getThen());

Counter ElseCount;
if (!llvm::EnableSingleByteCoverage)
ElseCount = subtractCounters(ParentCount, ThenCount);
else if (S->getElse())
ElseCount = getRegionCounter(S->getElse());

if (const Stmt *Else = S->getElse()) {
bool ThenHasTerminateStmt = HasTerminateStmt;
HasTerminateStmt = false;
Expand All @@ -2055,15 +2093,14 @@ struct CounterCoverageMappingBuilder
if (llvm::EnableSingleByteCoverage)
OutCount = getRegionCounter(S);

if (OutCount != ParentCount) {
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
}

if (!llvm::EnableSingleByteCoverage)
// Create Branch Region around condition.
createBranchRegion(S->getCond(), ThenCount,
subtractCounters(ParentCount, ThenCount));
createBranchRegion(S->getCond(), ThenCount, ElseCount);
}

void VisitCXXTryStmt(const CXXTryStmt *S) {
Expand All @@ -2089,9 +2126,11 @@ struct CounterCoverageMappingBuilder
extendRegion(E);

Counter ParentCount = getRegion().getCounter();
Counter TrueCount = llvm::EnableSingleByteCoverage
? getRegionCounter(E->getTrueExpr())
: getRegionCounter(E);
auto [TrueCount, FalseCount] =
(llvm::EnableSingleByteCoverage
? BranchCounterPair{getRegionCounter(E->getTrueExpr()),
getRegionCounter(E->getFalseExpr())}
: getBranchCounterPair(E, ParentCount));
Counter OutCount;

if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
Expand All @@ -2110,25 +2149,20 @@ struct CounterCoverageMappingBuilder
}

extendRegion(E->getFalseExpr());
Counter FalseCount = llvm::EnableSingleByteCoverage
? getRegionCounter(E->getFalseExpr())
: subtractCounters(ParentCount, TrueCount);

Counter FalseOutCount = propagateCounts(FalseCount, E->getFalseExpr());
if (llvm::EnableSingleByteCoverage)
OutCount = getRegionCounter(E);
else
OutCount = addCounters(OutCount, FalseOutCount);

if (OutCount != ParentCount) {
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
}

// Create Branch Region around condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(E->getCond(), TrueCount,
subtractCounters(ParentCount, TrueCount));
createBranchRegion(E->getCond(), TrueCount, FalseCount);
}

void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
Expand Down Expand Up @@ -2227,27 +2261,27 @@ struct CounterCoverageMappingBuilder
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());

if (llvm::EnableSingleByteCoverage)
return;

// Track RHS True/False Decision.
const auto DecisionRHS = MCDCBuilder.back();

// Extract the Parent Region Counter.
Counter ParentCnt = getRegion().getCounter();

// Extract the RHS's Execution Counter.
Counter RHSExecCnt = getRegionCounter(E);
auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);

// Extract the RHS's "True" Instance Counter.
Counter RHSTrueCnt = getRegionCounter(E->getRHS());

// Extract the Parent Region Counter.
Counter ParentCnt = getRegion().getCounter();
auto [RHSTrueCnt, RHSExitCnt] =
getBranchCounterPair(E->getRHS(), RHSExecCnt);

// Create Branch Region around LHS condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(E->getLHS(), RHSExecCnt,
subtractCounters(ParentCnt, RHSExecCnt), DecisionLHS);
createBranchRegion(E->getLHS(), RHSExecCnt, LHSExitCnt, DecisionLHS);

// Create Branch Region around RHS condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(E->getRHS(), RHSTrueCnt,
subtractCounters(RHSExecCnt, RHSTrueCnt), DecisionRHS);
createBranchRegion(E->getRHS(), RHSTrueCnt, RHSExitCnt, DecisionRHS);

// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
Expand Down Expand Up @@ -2288,31 +2322,31 @@ struct CounterCoverageMappingBuilder
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());

if (llvm::EnableSingleByteCoverage)
return;

// Track RHS True/False Decision.
const auto DecisionRHS = MCDCBuilder.back();

// Extract the Parent Region Counter.
Counter ParentCnt = getRegion().getCounter();

// Extract the RHS's Execution Counter.
Counter RHSExecCnt = getRegionCounter(E);
auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);

// Extract the RHS's "False" Instance Counter.
Counter RHSFalseCnt = getRegionCounter(E->getRHS());
auto [RHSFalseCnt, RHSExitCnt] =
getBranchCounterPair(E->getRHS(), RHSExecCnt);

if (!shouldVisitRHS(E->getLHS())) {
GapRegionCounter = OutCount;
}

// Extract the Parent Region Counter.
Counter ParentCnt = getRegion().getCounter();

// Create Branch Region around LHS condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
RHSExecCnt, DecisionLHS);
createBranchRegion(E->getLHS(), LHSExitCnt, RHSExecCnt, DecisionLHS);

// Create Branch Region around RHS condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
RHSFalseCnt, DecisionRHS);
createBranchRegion(E->getRHS(), RHSExitCnt, RHSFalseCnt, DecisionRHS);

// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
Expand Down
Loading