Skip to content

[Coverage][Single] Enable Branch coverage for BinLAnd and BinLOr #113113

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

Open
wants to merge 10 commits into
base: users/chapuni/cov/single/binop-base
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
95 changes: 79 additions & 16 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4951,6 +4951,9 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
}

Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
auto HasLHSSkip = CGF.getIsCounterPair(E);
auto HasRHSSkip = CGF.getIsCounterPair(E->getRHS());

// Perform vector logical and on comparisons with zero vectors.
if (E->getType()->isVectorType()) {
CGF.incrementProfileCounter(E);
Expand Down Expand Up @@ -4979,7 +4982,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
bool LHSCondVal;
if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) {
if (LHSCondVal) { // If we have 1 && X, just emit X.
CGF.incrementProfileCounter(E);
CGF.incrementProfileCounter(CGF.UseExecPath, E, /*UseBoth=*/true);

// If the top of the logical operator nest, reset the MCDC temp to 0.
if (CGF.MCDCLogOpStack.empty())
Expand All @@ -4997,11 +5000,17 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
CGF.maybeUpdateMCDCCondBitmap(E->getRHS(), RHSCond);
llvm::BasicBlock *FBlock = CGF.createBasicBlock("land.end");
llvm::BasicBlock *RHSSkip =
(HasRHSSkip.second ? CGF.createBasicBlock("land.rhsskip") : FBlock);
llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("land.rhscnt");
Builder.CreateCondBr(RHSCond, RHSBlockCnt, FBlock);
Builder.CreateCondBr(RHSCond, RHSBlockCnt, RHSSkip);
CGF.EmitBlock(RHSBlockCnt);
CGF.incrementProfileCounter(E->getRHS());
CGF.incrementProfileCounter(CGF.UseExecPath, E->getRHS());
CGF.EmitBranch(FBlock);
if (HasRHSSkip.second) {
CGF.EmitBlock(RHSSkip);
CGF.incrementProfileCounter(CGF.UseSkipPath, E->getRHS());
}
CGF.EmitBlock(FBlock);
} else
CGF.markStmtMaybeUsed(E->getRHS());
Expand All @@ -5017,7 +5026,12 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {

// 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
if (!CGF.ContainsLabel(E->getRHS())) {
CGF.markStmtAsUsed(false, E);
if (HasLHSSkip.second)
CGF.incrementProfileCounter(CGF.UseSkipPath, E);

CGF.markStmtMaybeUsed(E->getRHS());

return llvm::Constant::getNullValue(ResTy);
}
}
Expand All @@ -5031,12 +5045,21 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("land.rhs");

llvm::BasicBlock *LHSFalseBlock =
(HasLHSSkip.second ? CGF.createBasicBlock("land.lhsskip") : ContBlock);

CodeGenFunction::ConditionalEvaluation eval(CGF);

// Branch on the LHS first. If it is false, go to the failure (cont) block.
CGF.EmitBranchOnBoolExpr(E->getLHS(), RHSBlock, ContBlock,
CGF.EmitBranchOnBoolExpr(E->getLHS(), RHSBlock, LHSFalseBlock,
CGF.getProfileCount(E->getRHS()));

if (HasLHSSkip.second) {
CGF.EmitBlock(LHSFalseBlock);
CGF.incrementProfileCounter(CGF.UseSkipPath, E);
CGF.EmitBranch(ContBlock);
}

// Any edges into the ContBlock are now from an (indeterminate number of)
// edges from this first condition. All of these values will be false. Start
// setting up the PHI node in the Cont Block for this.
Expand All @@ -5048,7 +5071,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {

eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
CGF.incrementProfileCounter(E);
CGF.incrementProfileCounter(CGF.UseExecPath, E);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
eval.end(CGF);

Expand All @@ -5058,15 +5081,24 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
// If we're generating for profiling or coverage, generate a branch on the
// RHS to a block that increments the RHS true counter needed to track branch
// condition coverage.
llvm::BasicBlock *ContIncoming = RHSBlock;
if (InstrumentRegions &&
CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
CGF.maybeUpdateMCDCCondBitmap(E->getRHS(), RHSCond);
llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("land.rhscnt");
Builder.CreateCondBr(RHSCond, RHSBlockCnt, ContBlock);
llvm::BasicBlock *RHSBlockSkip =
(HasRHSSkip.second ? CGF.createBasicBlock("land.rhsskip") : ContBlock);
Builder.CreateCondBr(RHSCond, RHSBlockCnt, RHSBlockSkip);
CGF.EmitBlock(RHSBlockCnt);
CGF.incrementProfileCounter(E->getRHS());
CGF.incrementProfileCounter(CGF.UseExecPath, E->getRHS());
CGF.EmitBranch(ContBlock);
PN->addIncoming(RHSCond, RHSBlockCnt);
if (HasRHSSkip.second) {
CGF.EmitBlock(RHSBlockSkip);
CGF.incrementProfileCounter(CGF.UseSkipPath, E->getRHS());
CGF.EmitBranch(ContBlock);
ContIncoming = RHSBlockSkip;
}
}

// Emit an unconditional branch from this block to ContBlock.
Expand All @@ -5076,7 +5108,7 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
CGF.EmitBlock(ContBlock);
}
// Insert an entry into the phi node for the edge with the value of RHSCond.
PN->addIncoming(RHSCond, RHSBlock);
PN->addIncoming(RHSCond, ContIncoming);

CGF.MCDCLogOpStack.pop_back();
// If the top of the logical operator nest, update the MCDC bitmap.
Expand All @@ -5094,6 +5126,9 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
}

Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
auto HasLHSSkip = CGF.getIsCounterPair(E);
auto HasRHSSkip = CGF.getIsCounterPair(E->getRHS());

// Perform vector logical or on comparisons with zero vectors.
if (E->getType()->isVectorType()) {
CGF.incrementProfileCounter(E);
Expand Down Expand Up @@ -5122,7 +5157,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
bool LHSCondVal;
if (CGF.ConstantFoldsToSimpleInteger(E->getLHS(), LHSCondVal)) {
if (!LHSCondVal) { // If we have 0 || X, just emit X.
CGF.incrementProfileCounter(E);
CGF.incrementProfileCounter(CGF.UseExecPath, E, /*UseBoth=*/true);

// If the top of the logical operator nest, reset the MCDC temp to 0.
if (CGF.MCDCLogOpStack.empty())
Expand All @@ -5140,11 +5175,17 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
CGF.maybeUpdateMCDCCondBitmap(E->getRHS(), RHSCond);
llvm::BasicBlock *FBlock = CGF.createBasicBlock("lor.end");
llvm::BasicBlock *RHSSkip =
(HasRHSSkip.second ? CGF.createBasicBlock("lor.rhsskip") : FBlock);
llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("lor.rhscnt");
Builder.CreateCondBr(RHSCond, FBlock, RHSBlockCnt);
Builder.CreateCondBr(RHSCond, RHSSkip, RHSBlockCnt);
CGF.EmitBlock(RHSBlockCnt);
CGF.incrementProfileCounter(E->getRHS());
CGF.incrementProfileCounter(CGF.UseExecPath, E->getRHS());
CGF.EmitBranch(FBlock);
if (HasRHSSkip.second) {
CGF.EmitBlock(RHSSkip);
CGF.incrementProfileCounter(CGF.UseSkipPath, E->getRHS());
}
CGF.EmitBlock(FBlock);
} else
CGF.markStmtMaybeUsed(E->getRHS());
Expand All @@ -5160,7 +5201,12 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {

// 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
if (!CGF.ContainsLabel(E->getRHS())) {
CGF.markStmtAsUsed(false, E);
if (HasLHSSkip.second)
CGF.incrementProfileCounter(CGF.UseSkipPath, E);

CGF.markStmtMaybeUsed(E->getRHS());

return llvm::ConstantInt::get(ResTy, 1);
}
}
Expand All @@ -5173,14 +5219,22 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {

llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("lor.rhs");
llvm::BasicBlock *LHSTrueBlock =
(HasLHSSkip.second ? CGF.createBasicBlock("lor.lhsskip") : ContBlock);

CodeGenFunction::ConditionalEvaluation eval(CGF);

// Branch on the LHS first. If it is true, go to the success (cont) block.
CGF.EmitBranchOnBoolExpr(E->getLHS(), ContBlock, RHSBlock,
CGF.EmitBranchOnBoolExpr(E->getLHS(), LHSTrueBlock, RHSBlock,
CGF.getCurrentProfileCount() -
CGF.getProfileCount(E->getRHS()));

if (HasLHSSkip.second) {
CGF.EmitBlock(LHSTrueBlock);
CGF.incrementProfileCounter(CGF.UseSkipPath, E);
CGF.EmitBranch(ContBlock);
}

// Any edges into the ContBlock are now from an (indeterminate number of)
// edges from this first condition. All of these values will be true. Start
// setting up the PHI node in the Cont Block for this.
Expand All @@ -5194,7 +5248,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {

// Emit the RHS condition as a bool value.
CGF.EmitBlock(RHSBlock);
CGF.incrementProfileCounter(E);
CGF.incrementProfileCounter(CGF.UseExecPath, E);
Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());

eval.end(CGF);
Expand All @@ -5205,21 +5259,30 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
// If we're generating for profiling or coverage, generate a branch on the
// RHS to a block that increments the RHS true counter needed to track branch
// condition coverage.
llvm::BasicBlock *ContIncoming = RHSBlock;
if (InstrumentRegions &&
CodeGenFunction::isInstrumentedCondition(E->getRHS())) {
CGF.maybeUpdateMCDCCondBitmap(E->getRHS(), RHSCond);
llvm::BasicBlock *RHSBlockCnt = CGF.createBasicBlock("lor.rhscnt");
Builder.CreateCondBr(RHSCond, ContBlock, RHSBlockCnt);
llvm::BasicBlock *RHSTrueBlock =
(HasRHSSkip.second ? CGF.createBasicBlock("lor.rhsskip") : ContBlock);
Builder.CreateCondBr(RHSCond, RHSTrueBlock, RHSBlockCnt);
CGF.EmitBlock(RHSBlockCnt);
CGF.incrementProfileCounter(E->getRHS());
CGF.incrementProfileCounter(CGF.UseExecPath, E->getRHS());
CGF.EmitBranch(ContBlock);
PN->addIncoming(RHSCond, RHSBlockCnt);
if (HasRHSSkip.second) {
CGF.EmitBlock(RHSTrueBlock);
CGF.incrementProfileCounter(CGF.UseSkipPath, E->getRHS());
CGF.EmitBranch(ContBlock);
ContIncoming = RHSTrueBlock;
}
}

// Emit an unconditional branch from this block to ContBlock. Insert an entry
// into the phi node for the edge with the value of RHSCond.
CGF.EmitBlock(ContBlock);
PN->addIncoming(RHSCond, RHSBlock);
PN->addIncoming(RHSCond, ContIncoming);

CGF.MCDCLogOpStack.pop_back();
// If the top of the logical operator nest, update the MCDC bitmap.
Expand Down
4 changes: 0 additions & 4 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ using namespace CodeGen;
// Statement Emission
//===----------------------------------------------------------------------===//

namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

void CodeGenFunction::EmitStopPoint(const Stmt *S) {
if (CGDebugInfo *DI = getDebugInfo()) {
SourceLocation Loc;
Expand Down
43 changes: 36 additions & 7 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1769,6 +1769,7 @@ void CodeGenFunction::EmitBranchToCounterBlock(
return EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount, LH);

const Stmt *CntrStmt = (CntrIdx ? CntrIdx : Cond);
auto HasSkip = getIsCounterPair(CntrStmt);

llvm::BasicBlock *ThenBlock = nullptr;
llvm::BasicBlock *ElseBlock = nullptr;
Expand All @@ -1777,6 +1778,10 @@ void CodeGenFunction::EmitBranchToCounterBlock(
// Create the block we'll use to increment the appropriate counter.
llvm::BasicBlock *CounterIncrBlock = createBasicBlock("lop.rhscnt");

llvm::BasicBlock *SkipIncrBlock =
(HasSkip.second ? createBasicBlock("lop.rhsskip") : nullptr);
llvm::BasicBlock *SkipNextBlock = nullptr;

// Set block pointers according to Logical-AND (BO_LAnd) semantics. This
// means we need to evaluate the condition and increment the counter on TRUE:
//
Expand All @@ -1790,8 +1795,9 @@ void CodeGenFunction::EmitBranchToCounterBlock(
// goto TrueBlock;

if (LOp == BO_LAnd) {
SkipNextBlock = FalseBlock;
ThenBlock = CounterIncrBlock;
ElseBlock = FalseBlock;
ElseBlock = (SkipIncrBlock ? SkipIncrBlock : SkipNextBlock);
NextBlock = TrueBlock;
}

Expand All @@ -1808,7 +1814,8 @@ void CodeGenFunction::EmitBranchToCounterBlock(
// goto FalseBlock;

else if (LOp == BO_LOr) {
ThenBlock = TrueBlock;
SkipNextBlock = TrueBlock;
ThenBlock = (SkipIncrBlock ? SkipIncrBlock : SkipNextBlock);
ElseBlock = CounterIncrBlock;
NextBlock = FalseBlock;
} else {
Expand All @@ -1818,11 +1825,17 @@ void CodeGenFunction::EmitBranchToCounterBlock(
// Emit Branch based on condition.
EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, TrueCount, LH);

if (SkipIncrBlock) {
EmitBlock(SkipIncrBlock);
incrementProfileCounter(UseSkipPath, CntrStmt);
EmitBranch(SkipNextBlock);
}

// Emit the block containing the counter increment(s).
EmitBlock(CounterIncrBlock);

// Increment corresponding counter; if index not provided, use Cond as index.
incrementProfileCounter(CntrStmt);
incrementProfileCounter(UseExecPath, CntrStmt);

// Go to the next block.
EmitBranch(NextBlock);
Expand All @@ -1841,6 +1854,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
Cond = Cond->IgnoreParens();

if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
auto HasSkip = getIsCounterPair(CondBOp);

// Handle X && Y in a condition.
if (CondBOp->getOpcode() == BO_LAnd) {
MCDCLogOpStack.push_back(CondBOp);
Expand Down Expand Up @@ -1872,6 +1887,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
// Emit the LHS as a conditional. If the LHS conditional is false, we
// want to jump to the FalseBlock.
llvm::BasicBlock *LHSTrue = createBasicBlock("land.lhs.true");
llvm::BasicBlock *LHSFalse =
(HasSkip.second ? createBasicBlock("land.lhsskip") : FalseBlock);
// The counter tells us how often we evaluate RHS, and all of TrueCount
// can be propagated to that branch.
uint64_t RHSCount = getProfileCount(CondBOp->getRHS());
Expand All @@ -1882,12 +1899,17 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
// Propagate the likelihood attribute like __builtin_expect
// __builtin_expect(X && Y, 1) -> X and Y are likely
// __builtin_expect(X && Y, 0) -> only Y is unlikely
EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, FalseBlock, RHSCount,
EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, LHSFalse, RHSCount,
LH == Stmt::LH_Unlikely ? Stmt::LH_None : LH);
if (HasSkip.second) {
EmitBlock(LHSFalse);
incrementProfileCounter(UseSkipPath, CondBOp);
EmitBranch(FalseBlock);
}
EmitBlock(LHSTrue);
}

incrementProfileCounter(CondBOp);
incrementProfileCounter(UseExecPath, CondBOp);
setCurrentProfileCount(getProfileCount(CondBOp->getRHS()));

// Any temporaries created here are conditional.
Expand Down Expand Up @@ -1927,6 +1949,8 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
}
// Emit the LHS as a conditional. If the LHS conditional is true, we
// want to jump to the TrueBlock.
llvm::BasicBlock *LHSTrue =
(HasSkip.second ? createBasicBlock("lor.lhsskip") : TrueBlock);
llvm::BasicBlock *LHSFalse = createBasicBlock("lor.lhs.false");
// We have the count for entry to the RHS and for the whole expression
// being true, so we can divy up True count between the short circuit and
Expand All @@ -1941,12 +1965,17 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
// __builtin_expect(X || Y, 1) -> only Y is likely
// __builtin_expect(X || Y, 0) -> both X and Y are unlikely
ApplyDebugLocation DL(*this, Cond);
EmitBranchOnBoolExpr(CondBOp->getLHS(), TrueBlock, LHSFalse, LHSCount,
EmitBranchOnBoolExpr(CondBOp->getLHS(), LHSTrue, LHSFalse, LHSCount,
LH == Stmt::LH_Likely ? Stmt::LH_None : LH);
if (HasSkip.second) {
EmitBlock(LHSTrue);
incrementProfileCounter(UseSkipPath, CondBOp);
EmitBranch(TrueBlock);
}
EmitBlock(LHSFalse);
}

incrementProfileCounter(CondBOp);
incrementProfileCounter(UseExecPath, CondBOp);
setCurrentProfileCount(getProfileCount(CondBOp->getRHS()));

// Any temporaries created here are conditional.
Expand Down
6 changes: 0 additions & 6 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2236,9 +2236,6 @@ struct CounterCoverageMappingBuilder
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());

if (llvm::EnableSingleByteCoverage)
return;

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

Expand Down Expand Up @@ -2297,9 +2294,6 @@ struct CounterCoverageMappingBuilder
extendRegion(E->getRHS());
propagateCounts(getRegionCounter(E), E->getRHS());

if (llvm::EnableSingleByteCoverage)
return;

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

Expand Down
Loading
Loading