Skip to content
Merged
Changes from 12 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
196 changes: 108 additions & 88 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -919,15 +919,11 @@ struct CounterCoverageMappingBuilder

/// Return a counter for the sum of \c LHS and \c RHS.
Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
assert(!llvm::EnableSingleByteCoverage &&
"cannot add counters when single byte coverage mode is enabled");
return Builder.add(LHS, RHS, Simplify);
}

Counter addCounters(Counter C1, Counter C2, Counter C3,
bool Simplify = true) {
assert(!llvm::EnableSingleByteCoverage &&
"cannot add counters when single byte coverage mode is enabled");
return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
}

Expand All @@ -938,6 +934,32 @@ 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,
std::optional<Counter> SkipCntForOld = std::nullopt) {
Counter ExecCnt = getRegionCounter(S);

// The old behavior of SingleByte shouldn't emit Branches.
if (llvm::EnableSingleByteCoverage) {
assert(SkipCntForOld);
return {ExecCnt, *SkipCntForOld};
}

return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
}

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 +1610,10 @@ struct CounterCoverageMappingBuilder
llvm::EnableSingleByteCoverage
? getRegionCounter(S->getCond())
: addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
llvm::EnableSingleByteCoverage);

propagateCounts(CondCount, S->getCond());
adjustForOutOfOrderTraversal(getEnd(S));

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

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

if (OutCount != ParentCount) {
assert(
!llvm::EnableSingleByteCoverage ||
(BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
if (BodyHasTerminateStmt)
Expand All @@ -1611,8 +1635,7 @@ struct CounterCoverageMappingBuilder

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

void VisitDoStmt(const DoStmt *S) {
Expand Down Expand Up @@ -1641,22 +1664,24 @@ struct CounterCoverageMappingBuilder
Counter CondCount = llvm::EnableSingleByteCoverage
? getRegionCounter(S->getCond())
: addCounters(BackedgeCount, BC.ContinueCount);
auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
llvm::EnableSingleByteCoverage);

propagateCounts(CondCount, S->getCond());

Counter OutCount =
llvm::EnableSingleByteCoverage
? getRegionCounter(S)
: addCounters(BC.BreakCount,
subtractCounters(CondCount, BodyCount));
if (OutCount != ParentCount) {
assert(
!llvm::EnableSingleByteCoverage ||
(BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
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, BranchCount.Skipped);

if (BodyHasTerminateStmt)
HasTerminateStmt = true;
Expand Down Expand Up @@ -1705,6 +1730,9 @@ struct CounterCoverageMappingBuilder
: addCounters(
addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
IncrementBC.ContinueCount);
auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
llvm::EnableSingleByteCoverage);

if (const Expr *Cond = S->getCond()) {
propagateCounts(CondCount, Cond);
Expand All @@ -1716,12 +1744,11 @@ struct CounterCoverageMappingBuilder
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);

Counter OutCount =
llvm::EnableSingleByteCoverage
? getRegionCounter(S)
: addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
subtractCounters(CondCount, BodyCount));
if (OutCount != ParentCount) {
assert(!llvm::EnableSingleByteCoverage ||
(BodyBC.BreakCount.isZero() && IncrementBC.BreakCount.isZero()));
Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
BranchCount.Skipped);
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
if (BodyHasTerminateStmt)
Expand All @@ -1730,8 +1757,7 @@ struct CounterCoverageMappingBuilder

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

void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
Expand Down Expand Up @@ -1759,16 +1785,17 @@ struct CounterCoverageMappingBuilder
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);

Counter OutCount;
Counter LoopCount;
if (llvm::EnableSingleByteCoverage)
OutCount = getRegionCounter(S);
else {
LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
OutCount =
addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
}
if (OutCount != ParentCount) {
Counter LoopCount =
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
auto BranchCount = getBranchCounterPair(S, LoopCount, getRegionCounter(S));
assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
llvm::EnableSingleByteCoverage);
assert(
!llvm::EnableSingleByteCoverage ||
(BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));

Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
if (BodyHasTerminateStmt)
Expand All @@ -1777,8 +1804,7 @@ struct CounterCoverageMappingBuilder

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

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

Counter LoopCount =
addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
Counter OutCount =
addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
if (OutCount != ParentCount) {
auto BranchCount = getBranchCounterPair(S, LoopCount);
assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount);
Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
}
Expand Down Expand Up @@ -2010,9 +2037,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 +2057,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 +2079,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 +2112,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 +2135,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 +2247,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 +2308,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