Reapply: [MC/DC][Coverage] Loosen the limit of NumConds from 6 (#82448)

By storing possible test vectors instead of combinations of conditions,
the restriction is dramatically relaxed.

This introduces two options to `cc1`:

* `-fmcdc-max-conditions=32767`
* `-fmcdc-max-test-vectors=2147483646`

This change makes coverage mapping, profraw, and profdata incompatible
with Clang-18.

- Bitmap semantics changed. It is incompatible with previous format.
- `BitmapIdx` in `Decision` points to the end of the bitmap.
- Bitmap is packed per function.
- `llvm-cov` can understand `profdata` generated by `llvm-profdata-18`.

RFC:
https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798

--
Change(s) since llvmorg-19-init-14288-g7ead2d8c7e91

- Update compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c
This commit is contained in:
NAKAMURA Takumi 2024-06-13 20:09:02 +09:00
parent 1ceede3318
commit 71f8b441ed
43 changed files with 530 additions and 298 deletions

View File

@ -484,10 +484,31 @@ MC/DC Instrumentation
---------------------
When instrumenting for Modified Condition/Decision Coverage (MC/DC) using the
clang option ``-fcoverage-mcdc``, users are limited to at most **six** leaf-level
conditions in a boolean expression. A warning will be generated for boolean
expressions that contain more than six, and they will not be instrumented for
MC/DC.
clang option ``-fcoverage-mcdc``, there are two hard limits.
The maximum number of terms is limited to 32767, which is practical for
handwritten expressions. To be more restrictive in order to enforce coding rules,
use ``-Xclang -fmcdc-max-conditions=n``. Expressions with exceeded condition
counts ``n`` will generate warnings and will be excluded in the MC/DC coverage.
The number of test vectors (the maximum number of possible combinations of
expressions) is limited to 2,147,483,646. In this case, approximately
256MiB (==2GiB/8) is used to record test vectors.
To reduce memory usage, users can limit the maximum number of test vectors per
expression with ``-Xclang -fmcdc-max-test-vectors=m``.
If the number of test vectors resulting from the analysis of an expression
exceeds ``m``, a warning will be issued and the expression will be excluded
from the MC/DC coverage.
The number of test vectors ``m``, for ``n`` terms in an expression, can be
``m <= 2^n`` in the theoretical worst case, but is usually much smaller.
In simple cases, such as expressions consisting of a sequence of single
operators, ``m == n+1``. For example, ``(a && b && c && d && e && f && g)``
requires 8 test vectors.
Expressions such as ``((a0 && b0) || (a1 && b1) || ...)`` can cause the
number of test vectors to increase exponentially.
Also, if a boolean expression is embedded in the nest of another boolean
expression but separated by a non-logical operator, this is also not supported.

View File

@ -223,6 +223,8 @@ CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping
///< regions.
CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria.
VALUE_CODEGENOPT(MCDCMaxConds, 16, 32767) ///< MC/DC Maximum conditions.
VALUE_CODEGENOPT(MCDCMaxTVs, 32, 0x7FFFFFFE) ///< MC/DC Maximum test vectors.
/// If -fpcc-struct-return or -freg-struct-return is specified.
ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)

View File

@ -1790,6 +1790,14 @@ defm mcdc_coverage : BoolFOption<"coverage-mcdc",
"Enable MC/DC criteria when generating code coverage">,
NegFlag<SetFalse, [], [ClangOption], "Disable MC/DC coverage criteria">,
BothFlags<[], [ClangOption, CLOption]>>;
def fmcdc_max_conditions_EQ : Joined<["-"], "fmcdc-max-conditions=">,
Group<f_Group>, Visibility<[CC1Option]>,
HelpText<"Maximum number of conditions in MC/DC coverage">,
MarshallingInfoInt<CodeGenOpts<"MCDCMaxConds">, "32767">;
def fmcdc_max_test_vectors_EQ : Joined<["-"], "fmcdc-max-test-vectors=">,
Group<f_Group>, Visibility<[CC1Option]>,
HelpText<"Maximum number of test vectors in MC/DC coverage">,
MarshallingInfoInt<CodeGenOpts<"MCDCMaxTVs">, "0x7FFFFFFE">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
Group<f_Group>, Visibility<[ClangOption, CLOption]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;

View File

@ -167,8 +167,6 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
PGOHash Hash;
/// The map of statements to counters.
llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
/// The next bitmap byte index to assign.
unsigned NextMCDCBitmapIdx;
/// The state of MC/DC Coverage in this function.
MCDC::State &MCDCState;
/// Maximum number of supported MC/DC conditions in a boolean expression.
@ -183,7 +181,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
MCDC::State &MCDCState, unsigned MCDCMaxCond,
DiagnosticsEngine &Diag)
: NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
NextMCDCBitmapIdx(0), MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
ProfileVersion(ProfileVersion), Diag(Diag) {}
// Blocks and lambdas are handled as separate functions, so we need not
@ -314,11 +312,8 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
return true;
}
// Otherwise, allocate the number of bytes required for the bitmap
// based on the number of conditions. Must be at least 1-byte long.
MCDCState.DecisionByStmt[BinOp].BitmapIdx = NextMCDCBitmapIdx;
unsigned SizeInBits = std::max<unsigned>(1L << NumCond, CHAR_BIT);
NextMCDCBitmapIdx += SizeInBits / CHAR_BIT;
// Otherwise, allocate the Decision.
MCDCState.DecisionByStmt[BinOp].BitmapIdx = 0;
}
return true;
}
@ -1083,7 +1078,9 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
// for most embedded applications. Setting a maximum value prevents the
// bitmap footprint from growing too large without the user's knowledge. In
// the future, this value could be adjusted with a command-line option.
unsigned MCDCMaxConditions = (CGM.getCodeGenOpts().MCDCCoverage) ? 6 : 0;
unsigned MCDCMaxConditions =
(CGM.getCodeGenOpts().MCDCCoverage ? CGM.getCodeGenOpts().MCDCMaxConds
: 0);
RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
RegionMCDCState.reset(new MCDC::State);
@ -1099,7 +1096,6 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
NumRegionCounters = Walker.NextCounter;
RegionMCDCState->BitmapBytes = Walker.NextMCDCBitmapIdx;
FunctionHash = Walker.Hash.finalize();
}
@ -1232,7 +1228,7 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) {
// anything.
llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(RegionMCDCState->BitmapBytes)};
Builder.getInt32(RegionMCDCState->BitmapBits)};
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
}
@ -1250,6 +1246,11 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
return;
// Don't create tvbitmap_update if the record is allocated but excluded.
// Or `bitmap |= (1 << 0)` would be wrongly executed to the next bitmap.
if (DecisionStateIter->second.Indices.size() == 0)
return;
// Extract the offset of the global bitmap associated with this expression.
unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
@ -1261,7 +1262,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
// index represents an executed test vector.
llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(RegionMCDCState->BitmapBytes),
Builder.getInt32(0), // Unused
Builder.getInt32(MCDCTestVectorBitmapOffset),
MCDCCondBitmapAddr.emitRawPointer(CGF)};
Builder.CreateCall(
@ -1305,19 +1306,22 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
// Extract the ID of the condition we are setting in the bitmap.
const auto &Branch = BranchStateIter->second;
assert(Branch.ID >= 0 && "Condition has no ID!");
assert(Branch.DecisionStmt);
auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
// Cancel the emission if the Decision is erased after the allocation.
const auto DecisionIter =
RegionMCDCState->DecisionByStmt.find(Branch.DecisionStmt);
if (DecisionIter == RegionMCDCState->DecisionByStmt.end())
return;
// Emit intrinsic that updates a dedicated temporary value on the stack after
// a condition is evaluated. After the set of conditions has been updated,
// the resulting value is used to update the boolean expression's bitmap.
llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
Builder.getInt64(FunctionHash),
Builder.getInt32(Branch.ID),
MCDCCondBitmapAddr.emitRawPointer(CGF), Val};
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update),
Args);
const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];
auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
"mcdc." + Twine(Branch.ID + 1) + ".cur");
auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[true]));
NewTV = Builder.CreateSelect(
Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[false])));
Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
}
void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {

View File

@ -195,6 +195,10 @@ public:
return std::holds_alternative<mcdc::BranchParameters>(MCDCParams);
}
const auto &getMCDCBranchParams() const {
return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
}
bool isMCDCDecision() const {
return std::holds_alternative<mcdc::DecisionParameters>(MCDCParams);
}
@ -204,6 +208,8 @@ public:
}
const mcdc::Parameters &getMCDCParams() const { return MCDCParams; }
void resetMCDCParams() { MCDCParams = mcdc::Parameters(); }
};
/// Spelling locations for the start and end of a source region.
@ -748,6 +754,7 @@ private:
llvm::SmallVector<mcdc::ConditionIDs> DecisionStack;
MCDC::State &MCDCState;
const Stmt *DecisionStmt = nullptr;
mcdc::ConditionID NextID = 0;
bool NotMapped = false;
@ -777,7 +784,8 @@ public:
/// Set the given condition's ID.
void setCondID(const Expr *Cond, mcdc::ConditionID ID) {
MCDCState.BranchByStmt[CodeGenFunction::stripCond(Cond)].ID = ID;
MCDCState.BranchByStmt[CodeGenFunction::stripCond(Cond)] = {ID,
DecisionStmt};
}
/// Return the ID of a given condition.
@ -808,6 +816,11 @@ public:
if (NotMapped)
return;
if (NextID == 0) {
DecisionStmt = E;
assert(MCDCState.DecisionByStmt.contains(E));
}
const mcdc::ConditionIDs &ParentDecision = DecisionStack.back();
// If the operator itself has an assigned ID, this means it represents a
@ -2122,13 +2135,41 @@ struct CounterCoverageMappingBuilder
subtractCounters(ParentCount, TrueCount));
}
void createDecision(const BinaryOperator *E) {
void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
unsigned NumConds = MCDCBuilder.getTotalConditionsAndReset(E);
if (NumConds == 0)
return;
// Extract [ID, Conds] to construct the graph.
llvm::SmallVector<mcdc::ConditionIDs> CondIDs(NumConds);
for (const auto &SR : ArrayRef(SourceRegions).slice(Since)) {
if (SR.isMCDCBranch()) {
auto [ID, Conds] = SR.getMCDCBranchParams();
CondIDs[ID] = Conds;
}
}
// Construct the graph and calculate `Indices`.
mcdc::TVIdxBuilder Builder(CondIDs);
unsigned NumTVs = Builder.NumTestVectors;
unsigned MaxTVs = CVM.getCodeGenModule().getCodeGenOpts().MCDCMaxTVs;
assert(MaxTVs < mcdc::TVIdxBuilder::HardMaxTVs);
if (NumTVs > MaxTVs) {
// NumTVs exceeds MaxTVs -- warn and cancel the Decision.
cancelDecision(E, Since, NumTVs, MaxTVs);
return;
}
// Update the state for CodeGenPGO
assert(MCDCState.DecisionByStmt.contains(E));
MCDCState.DecisionByStmt[E] = {
MCDCState.BitmapBits, // Top
std::move(Builder.Indices),
};
auto DecisionParams = mcdc::DecisionParameters{
MCDCState.DecisionByStmt[E].BitmapIdx,
MCDCState.BitmapBits += NumTVs, // Tail
NumConds,
};
@ -2136,6 +2177,28 @@ struct CounterCoverageMappingBuilder
createDecisionRegion(E, DecisionParams);
}
// Warn and cancel the Decision.
void cancelDecision(const BinaryOperator *E, unsigned Since, int NumTVs,
int MaxTVs) {
auto &Diag = CVM.getCodeGenModule().getDiags();
unsigned DiagID =
Diag.getCustomDiagID(DiagnosticsEngine::Warning,
"unsupported MC/DC boolean expression; "
"number of test vectors (%0) exceeds max (%1). "
"Expression will not be covered");
Diag.Report(E->getBeginLoc(), DiagID) << NumTVs << MaxTVs;
// Restore MCDCBranch to Branch.
for (auto &SR : MutableArrayRef(SourceRegions).slice(Since)) {
assert(!SR.isMCDCDecision() && "Decision shouldn't be seen here");
if (SR.isMCDCBranch())
SR.resetMCDCParams();
}
// Tell CodeGenPGO not to instrument.
MCDCState.DecisionByStmt.erase(E);
}
/// Check if E belongs to system headers.
bool isExprInSystemHeader(const BinaryOperator *E) const {
return (!SystemHeadersCoverage &&
@ -2152,6 +2215,8 @@ struct CounterCoverageMappingBuilder
bool IsRootNode = MCDCBuilder.isIdle();
unsigned SourceRegionsSince = SourceRegions.size();
// Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);
@ -2190,7 +2255,7 @@ struct CounterCoverageMappingBuilder
// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
createDecision(E);
createOrCancelDecision(E, SourceRegionsSince);
}
// Determine whether the right side of OR operation need to be visited.
@ -2211,6 +2276,8 @@ struct CounterCoverageMappingBuilder
bool IsRootNode = MCDCBuilder.isIdle();
unsigned SourceRegionsSince = SourceRegions.size();
// Keep track of Binary Operator and assign MCDC condition IDs.
MCDCBuilder.pushAndAssignIDs(E);
@ -2253,7 +2320,7 @@ struct CounterCoverageMappingBuilder
// Create MCDC Decision Region if at top-level (root).
if (IsRootNode)
createDecision(E);
createOrCancelDecision(E, SourceRegionsSince);
}
void VisitLambdaExpr(const LambdaExpr *LE) {

View File

@ -27,16 +27,18 @@ using namespace llvm::coverage::mcdc;
/// Per-Function MC/DC state
struct State {
unsigned BitmapBytes = 0;
unsigned BitmapBits = 0;
struct Decision {
unsigned BitmapIdx;
llvm::SmallVector<std::array<int, 2>> Indices;
};
llvm::DenseMap<const Stmt *, Decision> DecisionByStmt;
struct Branch {
ConditionID ID;
const Stmt *DecisionStmt;
};
llvm::DenseMap<const Stmt *, Branch> BranchByStmt;

View File

@ -4,93 +4,93 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-constfolded.cpp %s | FileCheck %s -check-prefix=MCDC
// CHECK-LABEL: _Z6fand_0b:
bool fand_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
bool fand_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
return false && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #2, (#1 - #2)
// CHECK-LABEL: _Z6fand_1b:
bool fand_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
bool fand_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
return a && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1)
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
// CHECK-LABEL: _Z6fand_2bb:
bool fand_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:0, C:3
bool fand_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3
return false && a && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #4, (#3 - #4)
// CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = #2, (#1 - #2)
// CHECK-LABEL: _Z6fand_3bb:
bool fand_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:0, C:3
bool fand_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3
return a && true && b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3)
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
// CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = #2, (#1 - #2)
// CHECK-LABEL: _Z6fand_4bb:
bool fand_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:0, C:3
bool fand_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3
return a && b && false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3)
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = #4, (#3 - #4)
// CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:25 = 0, 0
// CHECK-LABEL: _Z6fand_5b:
bool fand_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:0, C:2
bool fand_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2
return false && true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:23 = 0, 0
// CHECK-LABEL: _Z6fand_6b:
bool fand_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
bool fand_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
return true && a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = #2, (#1 - #2)
// CHECK-LABEL: _Z6fand_7b:
bool fand_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
bool fand_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
return a && false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1)
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
// CHECK-LABEL: _Z5for_0b:
bool for_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
bool for_0(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
return true || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#1 - #2), #2
// CHECK-LABEL: _Z5for_1b:
bool for_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
bool for_1(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
return a || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
// CHECK-LABEL: _Z5for_2bb:
bool for_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:0, C:3
bool for_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3
return true || a || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#3 - #4), #4
// CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = (#1 - #2), #2
// CHECK-LABEL: _Z5for_3bb:
bool for_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:0, C:3
bool for_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3
return a || false || b; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
// CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = (#1 - #2), #2
// CHECK-LABEL: _Z5for_4bb:
bool for_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:0, C:3
bool for_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3
return a || b || true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = (#3 - #4), #4
// CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:24 = 0, 0
// CHECK-LABEL: _Z5for_5b:
bool for_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:0, C:2
bool for_5(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2
return true || false; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:23 = 0, 0
// CHECK-LABEL: _Z5for_6b:
bool for_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
bool for_6(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
return false || a; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
} // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = (#1 - #2), #2
// CHECK-LABEL: _Z5for_7b:
bool for_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
bool for_7(bool a) { // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
return a || true; // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1
} // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
// CHECK-LABEL: _Z5for_8b:
bool for_8(bool a) { // MCDC: Decision,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:20 = M:0, C:2
bool for_8(bool a) { // MCDC: Decision,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:20 = M:3, C:2
// CHECK: Branch,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:11 = 0, 0
// CHECK: Branch,File 0, [[@LINE+1]]:15 -> [[@LINE+1]]:20 = 0, 0
if (true && false)

View File

@ -3,22 +3,22 @@
int main() { // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+23]]:2 = #0
bool bt = true;
bool bf = false; // MCDC: Decision,File 0, [[@LINE+1]]:12 -> [[@LINE+1]]:20 = M:0, C:2
bool bf = false; // MCDC: Decision,File 0, [[@LINE+1]]:12 -> [[@LINE+1]]:20 = M:3, C:2
bool a = bt && bf; // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE]]:14 = #0
// CHECK-NEXT: Branch,File 0, [[@LINE-1]]:12 -> [[@LINE-1]]:14 = #1, (#0 - #1)
// CHECK-NEXT: File 0, [[@LINE-2]]:18 -> [[@LINE-2]]:20 = #1
// CHECK-NEXT: Branch,File 0, [[@LINE-3]]:18 -> [[@LINE-3]]:20 = #2, (#1 - #2)
// MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:1, C:2
// MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:6, C:2
a = bt && // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
bf; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #3, (#0 - #3)
// CHECK-NEXT: File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #3
// CHECK-NEXT: Branch,File 0, [[@LINE-2]]:7 -> [[@LINE-2]]:9 = #4, (#3 - #4)
// MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:15 = M:2, C:2
// MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:15 = M:9, C:2
a = bf || bt; // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
// CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = (#0 - #5), #5
// CHECK-NEXT: File 0, [[@LINE-2]]:13 -> [[@LINE-2]]:15 = #5
// CHECK-NEXT: Branch,File 0, [[@LINE-3]]:13 -> [[@LINE-3]]:15 = (#5 - #6), #6
// MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:3, C:2
// MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:12, C:2
a = bf || // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
bt; // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = (#0 - #7), #7
// CHECK-NEXT: File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #7

View File

@ -23,9 +23,9 @@ Value::~Value(void) {
bar();
}
// CHECK-LABEL: Decision,File 0, 18:7 -> 18:31 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 18:7 -> 18:31 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 18:7 -> 18:17 = (#0 - #2), #2 [1,0,2]
// CHECK: Branch,File 0, 18:21 -> 18:31 = (#2 - #3), #3 [2,0,0]
// CHECK-LABEL: Decision,File 0, 22:7 -> 22:31 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 22:7 -> 22:31 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 22:7 -> 22:17 = (#0 - #2), #2 [1,0,2]
// CHECK: Branch,File 0, 22:21 -> 22:31 = (#2 - #3), #3 [2,0,0]

View File

@ -1,7 +1,108 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s
// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,TV
// RUN: %clang_cc1 -fmcdc-max-test-vectors=8 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,TV
// RUN: %clang_cc1 -fmcdc-max-test-vectors=7 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,TV7,TV
// RUN: %clang_cc1 -fmcdc-max-conditions=287 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,TV
// RUN: %clang_cc1 -fmcdc-max-conditions=286 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,COND
// RUN: %clang_cc1 -fmcdc-max-conditions=7 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,COND
// RUN: %clang_cc1 -fmcdc-max-conditions=6 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND6,COND
bool func_conditions(bool a, bool b, bool c, bool d, bool e, bool f, bool g) {
// TV7: :[[@LINE+2]]:10: warning: unsupported MC/DC boolean expression; number of test vectors (8) exceeds max
// COND6: :[[@LINE+1]]:10: warning: unsupported MC/DC boolean expression; number of conditions (7) exceeds max
return a && b && c && d && e && f && g;
}
// CHECK: warning: unsupported MC/DC boolean expression; number of conditions{{.*}} exceeds max
// From clang-tidy/misc/MisleadingIdentifier.cpp
bool func_isR(unsigned CP) {
// TV: :[[@LINE+2]]:10: warning: unsupported MC/DC boolean expression; number of test vectors (2147483647) exceeds max
// COND: :[[@LINE+1]]:10: warning: unsupported MC/DC boolean expression; number of conditions (287) exceeds max
return (CP == 0x0590) || (CP == 0x05BE) || (CP == 0x05C0) || (CP == 0x05C3) ||
(CP == 0x05C6) || (0x05C8 <= CP && CP <= 0x05CF) ||
(0x05D0 <= CP && CP <= 0x05EA) || (0x05EB <= CP && CP <= 0x05EE) ||
(0x05EF <= CP && CP <= 0x05F2) || (0x05F3 <= CP && CP <= 0x05F4) ||
(0x05F5 <= CP && CP <= 0x05FF) || (0x07C0 <= CP && CP <= 0x07C9) ||
(0x07CA <= CP && CP <= 0x07EA) || (0x07F4 <= CP && CP <= 0x07F5) ||
(CP == 0x07FA) || (0x07FB <= CP && CP <= 0x07FC) ||
(0x07FE <= CP && CP <= 0x07FF) || (0x0800 <= CP && CP <= 0x0815) ||
(CP == 0x081A) || (CP == 0x0824) || (CP == 0x0828) ||
(0x082E <= CP && CP <= 0x082F) || (0x0830 <= CP && CP <= 0x083E) ||
(CP == 0x083F) || (0x0840 <= CP && CP <= 0x0858) ||
(0x085C <= CP && CP <= 0x085D) || (CP == 0x085E) || (CP == 0x085F) ||
(CP == 0x200F) || (CP == 0xFB1D) || (0xFB1F <= CP && CP <= 0xFB28) ||
(0xFB2A <= CP && CP <= 0xFB36) || (CP == 0xFB37) ||
(0xFB38 <= CP && CP <= 0xFB3C) || (CP == 0xFB3D) || (CP == 0xFB3E) ||
(CP == 0xFB3F) || (0xFB40 <= CP && CP <= 0xFB41) || (CP == 0xFB42) ||
(0xFB43 <= CP && CP <= 0xFB44) || (CP == 0xFB45) ||
(0xFB46 <= CP && CP <= 0xFB4F) || (0x10800 <= CP && CP <= 0x10805) ||
(0x10806 <= CP && CP <= 0x10807) || (CP == 0x10808) ||
(CP == 0x10809) || (0x1080A <= CP && CP <= 0x10835) ||
(CP == 0x10836) || (0x10837 <= CP && CP <= 0x10838) ||
(0x10839 <= CP && CP <= 0x1083B) || (CP == 0x1083C) ||
(0x1083D <= CP && CP <= 0x1083E) || (0x1083F <= CP && CP <= 0x10855) ||
(CP == 0x10856) || (CP == 0x10857) ||
(0x10858 <= CP && CP <= 0x1085F) || (0x10860 <= CP && CP <= 0x10876) ||
(0x10877 <= CP && CP <= 0x10878) || (0x10879 <= CP && CP <= 0x1087F) ||
(0x10880 <= CP && CP <= 0x1089E) || (0x1089F <= CP && CP <= 0x108A6) ||
(0x108A7 <= CP && CP <= 0x108AF) || (0x108B0 <= CP && CP <= 0x108DF) ||
(0x108E0 <= CP && CP <= 0x108F2) || (CP == 0x108F3) ||
(0x108F4 <= CP && CP <= 0x108F5) || (0x108F6 <= CP && CP <= 0x108FA) ||
(0x108FB <= CP && CP <= 0x108FF) || (0x10900 <= CP && CP <= 0x10915) ||
(0x10916 <= CP && CP <= 0x1091B) || (0x1091C <= CP && CP <= 0x1091E) ||
(0x10920 <= CP && CP <= 0x10939) || (0x1093A <= CP && CP <= 0x1093E) ||
(CP == 0x1093F) || (0x10940 <= CP && CP <= 0x1097F) ||
(0x10980 <= CP && CP <= 0x109B7) || (0x109B8 <= CP && CP <= 0x109BB) ||
(0x109BC <= CP && CP <= 0x109BD) || (0x109BE <= CP && CP <= 0x109BF) ||
(0x109C0 <= CP && CP <= 0x109CF) || (0x109D0 <= CP && CP <= 0x109D1) ||
(0x109D2 <= CP && CP <= 0x109FF) || (CP == 0x10A00) ||
(CP == 0x10A04) || (0x10A07 <= CP && CP <= 0x10A0B) ||
(0x10A10 <= CP && CP <= 0x10A13) || (CP == 0x10A14) ||
(0x10A15 <= CP && CP <= 0x10A17) || (CP == 0x10A18) ||
(0x10A19 <= CP && CP <= 0x10A35) || (0x10A36 <= CP && CP <= 0x10A37) ||
(0x10A3B <= CP && CP <= 0x10A3E) || (0x10A40 <= CP && CP <= 0x10A48) ||
(0x10A49 <= CP && CP <= 0x10A4F) || (0x10A50 <= CP && CP <= 0x10A58) ||
(0x10A59 <= CP && CP <= 0x10A5F) || (0x10A60 <= CP && CP <= 0x10A7C) ||
(0x10A7D <= CP && CP <= 0x10A7E) || (CP == 0x10A7F) ||
(0x10A80 <= CP && CP <= 0x10A9C) || (0x10A9D <= CP && CP <= 0x10A9F) ||
(0x10AA0 <= CP && CP <= 0x10ABF) || (0x10AC0 <= CP && CP <= 0x10AC7) ||
(CP == 0x10AC8) || (0x10AC9 <= CP && CP <= 0x10AE4) ||
(0x10AE7 <= CP && CP <= 0x10AEA) || (0x10AEB <= CP && CP <= 0x10AEF) ||
(0x10AF0 <= CP && CP <= 0x10AF6) || (0x10AF7 <= CP && CP <= 0x10AFF) ||
(0x10B00 <= CP && CP <= 0x10B35) || (0x10B36 <= CP && CP <= 0x10B38) ||
(0x10B40 <= CP && CP <= 0x10B55) || (0x10B56 <= CP && CP <= 0x10B57) ||
(0x10B58 <= CP && CP <= 0x10B5F) || (0x10B60 <= CP && CP <= 0x10B72) ||
(0x10B73 <= CP && CP <= 0x10B77) || (0x10B78 <= CP && CP <= 0x10B7F) ||
(0x10B80 <= CP && CP <= 0x10B91) || (0x10B92 <= CP && CP <= 0x10B98) ||
(0x10B99 <= CP && CP <= 0x10B9C) || (0x10B9D <= CP && CP <= 0x10BA8) ||
(0x10BA9 <= CP && CP <= 0x10BAF) || (0x10BB0 <= CP && CP <= 0x10BFF) ||
(0x10C00 <= CP && CP <= 0x10C48) || (0x10C49 <= CP && CP <= 0x10C7F) ||
(0x10C80 <= CP && CP <= 0x10CB2) || (0x10CB3 <= CP && CP <= 0x10CBF) ||
(0x10CC0 <= CP && CP <= 0x10CF2) || (0x10CF3 <= CP && CP <= 0x10CF9) ||
(0x10CFA <= CP && CP <= 0x10CFF) || (0x10D40 <= CP && CP <= 0x10E5F) ||
(CP == 0x10E7F) || (0x10E80 <= CP && CP <= 0x10EA9) ||
(CP == 0x10EAA) || (CP == 0x10EAD) ||
(0x10EAE <= CP && CP <= 0x10EAF) || (0x10EB0 <= CP && CP <= 0x10EB1) ||
(0x10EB2 <= CP && CP <= 0x10EFF) || (0x10F00 <= CP && CP <= 0x10F1C) ||
(0x10F1D <= CP && CP <= 0x10F26) || (CP == 0x10F27) ||
(0x10F28 <= CP && CP <= 0x10F2F) || (0x10F70 <= CP && CP <= 0x10F81) ||
(0x10F86 <= CP && CP <= 0x10F89) || (0x10F8A <= CP && CP <= 0x10FAF) ||
(0x10FB0 <= CP && CP <= 0x10FC4) || (0x10FC5 <= CP && CP <= 0x10FCB) ||
(0x10FCC <= CP && CP <= 0x10FDF) || (0x10FE0 <= CP && CP <= 0x10FF6) ||
(0x10FF7 <= CP && CP <= 0x10FFF) || (0x1E800 <= CP && CP <= 0x1E8C4) ||
(0x1E8C5 <= CP && CP <= 0x1E8C6) || (0x1E8C7 <= CP && CP <= 0x1E8CF) ||
(0x1E8D7 <= CP && CP <= 0x1E8FF) || (0x1E900 <= CP && CP <= 0x1E943) ||
(CP == 0x1E94B) || (0x1E94C <= CP && CP <= 0x1E94F) ||
(0x1E950 <= CP && CP <= 0x1E959) || (0x1E95A <= CP && CP <= 0x1E95D) ||
(0x1E95E <= CP && CP <= 0x1E95F) || (0x1E960 <= CP && CP <= 0x1EC6F) ||
(0x1ECC0 <= CP && CP <= 0x1ECFF) || (0x1ED50 <= CP && CP <= 0x1EDFF);
}
// CHECK: _Z15func_conditionsbbbbbbb:
// TV8-NOT: Decision,
// COND6-NOT: Decision,
// COND7: Decision,File 0, {{[0-9]+}}:10 -> {{[0-9]+}}:41 = M:8, C:7
// CHECK: _Z8func_isRj:
// CHECK-NOT: Decision,
// CHECK-NOT: Branch,{{.*}}]
// CHECK: Branch,File 0, [[@LINE-10]]:64 -> [[@LINE-10]]:77 =

View File

@ -10,25 +10,25 @@ bool func_scalar_and(bool a, bool b, bool c, bool d, bool e, bool f) {
return bar(res1, res2, res3, res4, res5);
}
// CHECK-LABEL: Decision,File 0, 5:17 -> 5:23 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 5:17 -> 5:23 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 5:17 -> 5:18 = #1, (#0 - #1) [1,2,0]
// CHECK: Branch,File 0, 5:22 -> 5:23 = #2, (#1 - #2) [2,0,0]
// CHECK-LABEL: Decision,File 0, 6:17 -> 6:28 = M:1, C:3
// CHECK-LABEL: Decision,File 0, 6:17 -> 6:28 = M:7, C:3
// CHECK-NEXT: Branch,File 0, 6:17 -> 6:18 = #5, (#0 - #5) [1,3,0]
// CHECK: Branch,File 0, 6:22 -> 6:23 = #6, (#5 - #6) [3,2,0]
// CHECK: Branch,File 0, 6:27 -> 6:28 = #4, (#3 - #4) [2,0,0]
// CHECK-LABEL: Decision,File 0, 7:17 -> 7:33 = M:2, C:4
// CHECK-LABEL: Decision,File 0, 7:17 -> 7:33 = M:12, C:4
// CHECK-NEXT: Branch,File 0, 7:17 -> 7:18 = #11, (#0 - #11) [1,4,0]
// CHECK: Branch,File 0, 7:22 -> 7:23 = #12, (#11 - #12) [4,3,0]
// CHECK: Branch,File 0, 7:27 -> 7:28 = #10, (#9 - #10) [3,2,0]
// CHECK: Branch,File 0, 7:32 -> 7:33 = #8, (#7 - #8) [2,0,0]
// CHECK-LABEL: Decision,File 0, 8:17 -> 8:38 = M:4, C:5
// CHECK-LABEL: Decision,File 0, 8:17 -> 8:38 = M:18, C:5
// CHECK-NEXT: Branch,File 0, 8:17 -> 8:18 = #19, (#0 - #19) [1,5,0]
// CHECK: Branch,File 0, 8:22 -> 8:23 = #20, (#19 - #20) [5,4,0]
// CHECK: Branch,File 0, 8:27 -> 8:28 = #18, (#17 - #18) [4,3,0]
// CHECK: Branch,File 0, 8:32 -> 8:33 = #16, (#15 - #16) [3,2,0]
// CHECK: Branch,File 0, 8:37 -> 8:38 = #14, (#13 - #14) [2,0,0]
// CHECK-LABEL: Decision,File 0, 9:17 -> 9:43 = M:8, C:6
// CHECK-LABEL: Decision,File 0, 9:17 -> 9:43 = M:25, C:6
// CHECK-NEXT: Branch,File 0, 9:17 -> 9:18 = #29, (#0 - #29) [1,6,0]
// CHECK: Branch,File 0, 9:22 -> 9:23 = #30, (#29 - #30) [6,5,0]
// CHECK: Branch,File 0, 9:27 -> 9:28 = #28, (#27 - #28) [5,4,0]
@ -45,25 +45,25 @@ bool func_scalar_or(bool a, bool b, bool c, bool d, bool e, bool f) {
return bar(res1, res2, res3, res4, res5);
}
// CHECK-LABEL: Decision,File 0, 40:17 -> 40:23 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 40:17 -> 40:23 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 40:17 -> 40:18 = (#0 - #1), #1 [1,0,2]
// CHECK: Branch,File 0, 40:22 -> 40:23 = (#1 - #2), #2 [2,0,0]
// CHECK-LABEL: Decision,File 0, 41:17 -> 41:28 = M:1, C:3
// CHECK-LABEL: Decision,File 0, 41:17 -> 41:28 = M:7, C:3
// CHECK-NEXT: Branch,File 0, 41:17 -> 41:18 = (#0 - #5), #5 [1,0,3]
// CHECK: Branch,File 0, 41:22 -> 41:23 = (#5 - #6), #6 [3,0,2]
// CHECK: Branch,File 0, 41:27 -> 41:28 = (#3 - #4), #4 [2,0,0]
// CHECK-LABEL: Decision,File 0, 42:17 -> 42:33 = M:2, C:4
// CHECK-LABEL: Decision,File 0, 42:17 -> 42:33 = M:12, C:4
// CHECK-NEXT: Branch,File 0, 42:17 -> 42:18 = (#0 - #11), #11 [1,0,4]
// CHECK: Branch,File 0, 42:22 -> 42:23 = (#11 - #12), #12 [4,0,3]
// CHECK: Branch,File 0, 42:27 -> 42:28 = (#9 - #10), #10 [3,0,2]
// CHECK: Branch,File 0, 42:32 -> 42:33 = (#7 - #8), #8 [2,0,0]
// CHECK-LABEL: Decision,File 0, 43:17 -> 43:38 = M:4, C:5
// CHECK-LABEL: Decision,File 0, 43:17 -> 43:38 = M:18, C:5
// CHECK-NEXT: Branch,File 0, 43:17 -> 43:18 = (#0 - #19), #19 [1,0,5]
// CHECK: Branch,File 0, 43:22 -> 43:23 = (#19 - #20), #20 [5,0,4]
// CHECK: Branch,File 0, 43:27 -> 43:28 = (#17 - #18), #18 [4,0,3]
// CHECK: Branch,File 0, 43:32 -> 43:33 = (#15 - #16), #16 [3,0,2]
// CHECK: Branch,File 0, 43:37 -> 43:38 = (#13 - #14), #14 [2,0,0]
// CHECK-LABEL: Decision,File 0, 44:17 -> 44:43 = M:8, C:6
// CHECK-LABEL: Decision,File 0, 44:17 -> 44:43 = M:25, C:6
// CHECK-NEXT: Branch,File 0, 44:17 -> 44:18 = (#0 - #29), #29 [1,0,6]
// CHECK: Branch,File 0, 44:22 -> 44:23 = (#29 - #30), #30 [6,0,5]
// CHECK: Branch,File 0, 44:27 -> 44:28 = (#27 - #28), #28 [5,0,4]
@ -81,26 +81,26 @@ bool func_scalar_mix(bool a, bool b, bool c, bool d, bool e, bool f) {
return bar(res1, res2, res3, res4, res5);
}
// CHECK-LABEL: Decision,File 0, 76:17 -> 76:23 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 76:17 -> 76:23 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 76:17 -> 76:18 = (#0 - #1), #1 [1,0,2]
// CHECK: Branch,File 0, 76:22 -> 76:23 = (#1 - #2), #2 [2,0,0]
// CHECK-LABEL: Decision,File 0, 77:17 -> 77:30 = M:1, C:3
// CHECK-LABEL: Decision,File 0, 77:17 -> 77:30 = M:7, C:3
// CHECK-NEXT: Branch,File 0, 77:17 -> 77:18 = #3, (#0 - #3) [1,2,0]
// CHECK: Branch,File 0, 77:23 -> 77:24 = (#3 - #4), #4 [2,0,3]
// CHECK: Branch,File 0, 77:28 -> 77:29 = (#4 - #5), #5 [3,0,0]
// CHECK-LABEL: Decision,File 0, 78:17 -> 78:37 = M:2, C:4
// CHECK-LABEL: Decision,File 0, 78:17 -> 78:37 = M:14, C:4
// CHECK-NEXT: File 0
// CHECK-NEXT: Branch,File 0, 78:18 -> 78:19 = (#0 - #7), #7 [1,2,3]
// CHECK: Branch,File 0, 78:23 -> 78:24 = (#7 - #8), #8 [3,2,0]
// CHECK: Branch,File 0, 78:30 -> 78:31 = (#6 - #9), #9 [2,0,4]
// CHECK: Branch,File 0, 78:35 -> 78:36 = (#9 - #10), #10 [4,0,0]
// CHECK-LABEL: Decision,File 0, 79:17 -> 79:42 = M:4, C:5
// CHECK-LABEL: Decision,File 0, 79:17 -> 79:42 = M:22, C:5
// CHECK-NEXT: Branch,File 0, 79:17 -> 79:18 = #12, (#0 - #12) [1,3,0]
// CHECK: Branch,File 0, 79:23 -> 79:24 = (#12 - #13), #13 [3,2,4]
// CHECK: Branch,File 0, 79:28 -> 79:29 = (#13 - #14), #14 [4,2,0]
// CHECK: Branch,File 0, 79:35 -> 79:36 = (#11 - #15), #15 [2,0,5]
// CHECK: Branch,File 0, 79:40 -> 79:41 = (#15 - #16), #16 [5,0,0]
// CHECK-LABEL: Decision,File 0, 80:17 -> 80:49 = M:8, C:6
// CHECK-LABEL: Decision,File 0, 80:17 -> 80:49 = M:37, C:6
// CHECK-NEXT: File 0
// CHECK-NEXT: Branch,File 0, 80:18 -> 80:19 = (#0 - #19), #19 [1,3,4]
// CHECK: Branch,File 0, 80:23 -> 80:24 = (#19 - #20), #20 [4,3,0]

View File

@ -6,7 +6,7 @@ bool func_if_and(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 4:7 -> 4:33 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 4:7 -> 4:33 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 4:7 -> 4:8 = #10, (#0 - #10) [1,6,0]
// CHECK: Branch,File 0, 4:12 -> 4:13 = #11, (#10 - #11) [6,5,0]
// CHECK: Branch,File 0, 4:17 -> 4:18 = #9, (#8 - #9) [5,4,0]
@ -20,7 +20,7 @@ bool func_if_or(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 18:7 -> 18:33 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 18:7 -> 18:33 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 18:7 -> 18:8 = (#0 - #10), #10 [1,0,6]
// CHECK: Branch,File 0, 18:12 -> 18:13 = (#10 - #11), #11 [6,0,5]
// CHECK: Branch,File 0, 18:17 -> 18:18 = (#8 - #9), #9 [5,0,4]
@ -33,7 +33,7 @@ bool func_while_and(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 32:10 -> 32:36 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 32:10 -> 32:36 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 32:10 -> 32:11 = #10, (#0 - #10) [1,6,0]
// CHECK: Branch,File 0, 32:15 -> 32:16 = #11, (#10 - #11) [6,5,0]
// CHECK: Branch,File 0, 32:20 -> 32:21 = #9, (#8 - #9) [5,4,0]
@ -46,7 +46,7 @@ bool func_while_or(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 45:10 -> 45:36 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 45:10 -> 45:36 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 45:10 -> 45:11 = (#0 - #10), #10 [1,0,6]
// CHECK: Branch,File 0, 45:15 -> 45:16 = (#10 - #11), #11 [6,0,5]
// CHECK: Branch,File 0, 45:20 -> 45:21 = (#8 - #9), #9 [5,0,4]
@ -59,7 +59,7 @@ bool func_for_and(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 58:9 -> 58:35 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 58:9 -> 58:35 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 58:9 -> 58:10 = #10, (#0 - #10) [1,6,0]
// CHECK: Branch,File 0, 58:14 -> 58:15 = #11, (#10 - #11) [6,5,0]
// CHECK: Branch,File 0, 58:19 -> 58:20 = #9, (#8 - #9) [5,4,0]
@ -72,7 +72,7 @@ bool func_for_or(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 71:9 -> 71:35 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 71:9 -> 71:35 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 71:9 -> 71:10 = (#0 - #10), #10 [1,0,6]
// CHECK: Branch,File 0, 71:14 -> 71:15 = (#10 - #11), #11 [6,0,5]
// CHECK: Branch,File 0, 71:19 -> 71:20 = (#8 - #9), #9 [5,0,4]
@ -85,7 +85,7 @@ bool func_do_and(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 84:16 -> 84:42 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 84:16 -> 84:42 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 84:16 -> 84:17 = #10, ((#0 + #1) - #10) [1,6,0]
// CHECK: Branch,File 0, 84:21 -> 84:22 = #11, (#10 - #11) [6,5,0]
// CHECK: Branch,File 0, 84:26 -> 84:27 = #9, (#8 - #9) [5,4,0]
@ -98,7 +98,7 @@ bool func_do_or(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 97:16 -> 97:42 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 97:16 -> 97:42 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 97:16 -> 97:17 = ((#0 + #1) - #10), #10 [1,0,6]
// CHECK: Branch,File 0, 97:21 -> 97:22 = (#10 - #11), #11 [6,0,5]
// CHECK: Branch,File 0, 97:26 -> 97:27 = (#8 - #9), #9 [5,0,4]
@ -110,7 +110,7 @@ bool func_ternary_and(bool a, bool b, bool c, bool d, bool e, bool f) {
return (a && b && c && d && e && f) ? true : false;
}
// CHECK-LABEL: Decision,File 0, 110:11 -> 110:37 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 110:11 -> 110:37 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 110:11 -> 110:12 = #10, (#0 - #10) [1,6,0]
// CHECK: Branch,File 0, 110:16 -> 110:17 = #11, (#10 - #11) [6,5,0]
// CHECK: Branch,File 0, 110:21 -> 110:22 = #9, (#8 - #9) [5,4,0]
@ -122,7 +122,7 @@ bool func_ternary_or(bool a, bool b, bool c, bool d, bool e, bool f) {
return (a || b || c || d || e || f) ? true : false;
}
// CHECK-LABEL: Decision,File 0, 122:11 -> 122:37 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 122:11 -> 122:37 = M:7, C:6
// CHECK-NEXT: Branch,File 0, 122:11 -> 122:12 = (#0 - #10), #10 [1,0,6]
// CHECK: Branch,File 0, 122:16 -> 122:17 = (#10 - #11), #11 [6,0,5]
// CHECK: Branch,File 0, 122:21 -> 122:22 = (#8 - #9), #9 [5,0,4]
@ -137,7 +137,7 @@ bool func_if_nested_if(bool a, bool b, bool c, bool d, bool e) {
return false;
}
// CHECK-LABEL: Decision,File 0, 134:7 -> 134:30 = M:0, C:5
// CHECK-LABEL: Decision,File 0, 134:7 -> 134:30 = M:8, C:5
// CHECK-NEXT: Branch,File 0, 134:7 -> 134:8 = (#0 - #6), #6 [1,0,4]
// CHECK: Branch,File 0, 134:13 -> 134:14 = #7, (#6 - #7) [4,5,3]
// CHECK: Branch,File 0, 134:18 -> 134:19 = #8, (#7 - #8) [5,0,3]
@ -148,7 +148,7 @@ bool func_ternary_nested_if(bool a, bool b, bool c, bool d, bool e) {
return (a || (b && c) || d || e) ? true : false;
}
// CHECK-LABEL: Decision,File 0, 148:11 -> 148:34 = M:0, C:5
// CHECK-LABEL: Decision,File 0, 148:11 -> 148:34 = M:8, C:5
// CHECK-NEXT: Branch,File 0, 148:11 -> 148:12 = (#0 - #6), #6 [1,0,4]
// CHECK: Branch,File 0, 148:17 -> 148:18 = #7, (#6 - #7) [4,5,3]
// CHECK: Branch,File 0, 148:22 -> 148:23 = #8, (#7 - #8) [5,0,3]
@ -162,7 +162,7 @@ bool func_if_nested_if_2(bool a, bool b, bool c, bool d, bool e) {
return false;
}
// CHECK-LABEL: Decision,File 0, 159:7 -> 159:32 = M:0, C:5
// CHECK-LABEL: Decision,File 0, 159:7 -> 159:32 = M:9, C:5
// CHECK-NEXT: Branch,File 0, 159:7 -> 159:8 = (#0 - #2), #2 [1,0,2]
// CHECK: Branch,File 0, 159:14 -> 159:15 = #7, (#2 - #7) [2,5,4]
// CHECK: Branch,File 0, 159:19 -> 159:20 = #8, (#7 - #8) [5,3,4]
@ -173,7 +173,7 @@ bool func_ternary_nested_if_2(bool a, bool b, bool c, bool d, bool e) {
return (a || ((b && c) || d) && e) ? true : false;
}
// CHECK-LABEL: Decision,File 0, 173:11 -> 173:36 = M:0, C:5
// CHECK-LABEL: Decision,File 0, 173:11 -> 173:36 = M:9, C:5
// CHECK-NEXT: Branch,File 0, 173:11 -> 173:12 = (#0 - #2), #2 [1,0,2]
// CHECK: Branch,File 0, 173:18 -> 173:19 = #7, (#2 - #7) [2,5,4]
// CHECK: Branch,File 0, 173:23 -> 173:24 = #8, (#7 - #8) [5,3,4]
@ -187,7 +187,7 @@ bool func_if_nested_if_3(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 184:7 -> 184:39 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 184:7 -> 184:39 = M:12, C:6
// CHECK: Branch,File 0, 184:8 -> 184:9 = #5, (#0 - #5) [1,4,3]
// CHECK: Branch,File 0, 184:14 -> 184:15 = (#5 - #6), #6 [4,2,5]
// CHECK: Branch,File 0, 184:19 -> 184:20 = (#6 - #7), #7 [5,2,3]
@ -199,7 +199,7 @@ bool func_ternary_nested_if_3(bool a, bool b, bool c, bool d, bool e, bool f) {
return ((a && (b || c) || (d && e)) && f) ? true : false;
}
// CHECK-LABEL: Decision,File 0, 199:11 -> 199:43 = M:0, C:6
// CHECK-LABEL: Decision,File 0, 199:11 -> 199:43 = M:12, C:6
// CHECK: Branch,File 0, 199:12 -> 199:13 = #5, (#0 - #5) [1,4,3]
// CHECK: Branch,File 0, 199:18 -> 199:19 = (#5 - #6), #6 [4,2,5]
// CHECK: Branch,File 0, 199:23 -> 199:24 = (#6 - #7), #7 [5,2,3]

View File

@ -10,25 +10,25 @@ bool func_if_and(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 4:7 -> 4:13 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 4:7 -> 4:13 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 4:7 -> 4:8 = #2, (#0 - #2) [1,2,0]
// CHECK: Branch,File 0, 4:12 -> 4:13 = #3, (#2 - #3) [2,0,0]
// CHECK-LABEL: Decision,File 0, 5:9 -> 5:20 = M:1, C:3
// CHECK-LABEL: Decision,File 0, 5:9 -> 5:20 = M:7, C:3
// CHECK-NEXT: Branch,File 0, 5:9 -> 5:10 = #7, (#1 - #7) [1,3,0]
// CHECK: Branch,File 0, 5:14 -> 5:15 = #8, (#7 - #8) [3,2,0]
// CHECK: Branch,File 0, 5:19 -> 5:20 = #6, (#5 - #6) [2,0,0]
// CHECK-LABEL: Decision,File 0, 6:11 -> 6:27 = M:2, C:4
// CHECK-LABEL: Decision,File 0, 6:11 -> 6:27 = M:12, C:4
// CHECK-NEXT: Branch,File 0, 6:11 -> 6:12 = #14, (#4 - #14) [1,4,0]
// CHECK: Branch,File 0, 6:16 -> 6:17 = #15, (#14 - #15) [4,3,0]
// CHECK: Branch,File 0, 6:21 -> 6:22 = #13, (#12 - #13) [3,2,0]
// CHECK: Branch,File 0, 6:26 -> 6:27 = #11, (#10 - #11) [2,0,0]
// CHECK-LABEL: Decision,File 0, 7:13 -> 7:34 = M:4, C:5
// CHECK-LABEL: Decision,File 0, 7:13 -> 7:34 = M:18, C:5
// CHECK-NEXT: Branch,File 0, 7:13 -> 7:14 = #23, (#9 - #23) [1,5,0]
// CHECK: Branch,File 0, 7:18 -> 7:19 = #24, (#23 - #24) [5,4,0]
// CHECK: Branch,File 0, 7:23 -> 7:24 = #22, (#21 - #22) [4,3,0]
// CHECK: Branch,File 0, 7:28 -> 7:29 = #20, (#19 - #20) [3,2,0]
// CHECK: Branch,File 0, 7:33 -> 7:34 = #18, (#17 - #18) [2,0,0]
// CHECK-LABEL: Decision,File 0, 8:16 -> 8:42 = M:8, C:6
// CHECK-LABEL: Decision,File 0, 8:16 -> 8:42 = M:25, C:6
// CHECK-NEXT: Branch,File 0, 8:16 -> 8:17 = #34, (#16 - #34) [1,6,0]
// CHECK: Branch,File 0, 8:21 -> 8:22 = #35, (#34 - #35) [6,5,0]
// CHECK: Branch,File 0, 8:26 -> 8:27 = #33, (#32 - #33) [5,4,0]
@ -46,25 +46,25 @@ bool func_if_or(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 40:7 -> 40:13 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 40:7 -> 40:13 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 40:7 -> 40:8 = (#0 - #2), #2 [1,0,2]
// CHECK: Branch,File 0, 40:12 -> 40:13 = (#2 - #3), #3 [2,0,0]
// CHECK-LABEL: Decision,File 0, 41:9 -> 41:20 = M:1, C:3
// CHECK-LABEL: Decision,File 0, 41:9 -> 41:20 = M:7, C:3
// CHECK-NEXT: Branch,File 0, 41:9 -> 41:10 = (#1 - #7), #7 [1,0,3]
// CHECK: Branch,File 0, 41:14 -> 41:15 = (#7 - #8), #8 [3,0,2]
// CHECK: Branch,File 0, 41:19 -> 41:20 = (#5 - #6), #6 [2,0,0]
// CHECK-LABEL: Decision,File 0, 42:11 -> 42:27 = M:2, C:4
// CHECK-LABEL: Decision,File 0, 42:11 -> 42:27 = M:12, C:4
// CHECK-NEXT: Branch,File 0, 42:11 -> 42:12 = (#4 - #14), #14 [1,0,4]
// CHECK: Branch,File 0, 42:16 -> 42:17 = (#14 - #15), #15 [4,0,3]
// CHECK: Branch,File 0, 42:21 -> 42:22 = (#12 - #13), #13 [3,0,2]
// CHECK: Branch,File 0, 42:26 -> 42:27 = (#10 - #11), #11 [2,0,0]
// CHECK-LABEL: Decision,File 0, 43:13 -> 43:34 = M:4, C:5
// CHECK-LABEL: Decision,File 0, 43:13 -> 43:34 = M:18, C:5
// CHECK-NEXT: Branch,File 0, 43:13 -> 43:14 = (#9 - #23), #23 [1,0,5]
// CHECK: Branch,File 0, 43:18 -> 43:19 = (#23 - #24), #24 [5,0,4]
// CHECK: Branch,File 0, 43:23 -> 43:24 = (#21 - #22), #22 [4,0,3]
// CHECK: Branch,File 0, 43:28 -> 43:29 = (#19 - #20), #20 [3,0,2]
// CHECK: Branch,File 0, 43:33 -> 43:34 = (#17 - #18), #18 [2,0,0]
// CHECK-LABEL: Decision,File 0, 44:16 -> 44:42 = M:8, C:6
// CHECK-LABEL: Decision,File 0, 44:16 -> 44:42 = M:25, C:6
// CHECK-NEXT: Branch,File 0, 44:16 -> 44:17 = (#16 - #34), #34 [1,0,6]
// CHECK: Branch,File 0, 44:21 -> 44:22 = (#34 - #35), #35 [6,0,5]
// CHECK: Branch,File 0, 44:26 -> 44:27 = (#32 - #33), #33 [5,0,4]
@ -82,26 +82,26 @@ bool func_if_mix(bool a, bool b, bool c, bool d, bool e, bool f) {
return false;
}
// CHECK-LABEL: Decision,File 0, 76:7 -> 76:13 = M:0, C:2
// CHECK-LABEL: Decision,File 0, 76:7 -> 76:13 = M:3, C:2
// CHECK-NEXT: Branch,File 0, 76:7 -> 76:8 = (#0 - #2), #2 [1,0,2]
// CHECK: Branch,File 0, 76:12 -> 76:13 = (#2 - #3), #3 [2,0,0]
// CHECK-LABEL: Decision,File 0, 77:9 -> 77:22 = M:1, C:3
// CHECK-LABEL: Decision,File 0, 77:9 -> 77:22 = M:7, C:3
// CHECK-NEXT: Branch,File 0, 77:9 -> 77:10 = #5, (#1 - #5) [1,2,0]
// CHECK: Branch,File 0, 77:15 -> 77:16 = (#5 - #6), #6 [2,0,3]
// CHECK: Branch,File 0, 77:20 -> 77:21 = (#6 - #7), #7 [3,0,0]
// CHECK-LABEL: Decision,File 0, 78:11 -> 78:31 = M:2, C:4
// CHECK-LABEL: Decision,File 0, 78:11 -> 78:31 = M:14, C:4
// CHECK-NEXT: File 0
// CHECK-NEXT: Branch,File 0, 78:12 -> 78:13 = (#4 - #10), #10 [1,2,3]
// CHECK: Branch,File 0, 78:17 -> 78:18 = (#10 - #11), #11 [3,2,0]
// CHECK: Branch,File 0, 78:24 -> 78:25 = (#9 - #12), #12 [2,0,4]
// CHECK: Branch,File 0, 78:29 -> 78:30 = (#12 - #13), #13 [4,0,0]
// CHECK-LABEL: Decision,File 0, 79:13 -> 79:38 = M:4, C:5
// CHECK-LABEL: Decision,File 0, 79:13 -> 79:38 = M:22, C:5
// CHECK-NEXT: Branch,File 0, 79:13 -> 79:14 = #16, (#8 - #16) [1,3,0]
// CHECK: Branch,File 0, 79:19 -> 79:20 = (#16 - #17), #17 [3,2,4]
// CHECK: Branch,File 0, 79:24 -> 79:25 = (#17 - #18), #18 [4,2,0]
// CHECK: Branch,File 0, 79:31 -> 79:32 = (#15 - #19), #19 [2,0,5]
// CHECK: Branch,File 0, 79:36 -> 79:37 = (#19 - #20), #20 [5,0,0]
// CHECK-LABEL: Decision,File 0, 80:15 -> 80:47 = M:8, C:6
// CHECK-LABEL: Decision,File 0, 80:15 -> 80:47 = M:37, C:6
// CHECK-NEXT: File 0
// CHECK-NEXT: Branch,File 0, 80:16 -> 80:17 = (#14 - #24), #24 [1,3,4]
// CHECK: Branch,File 0, 80:21 -> 80:22 = (#24 - #25), #25 [4,3,0]

View File

@ -2,14 +2,14 @@
// CHECK: builtin_macro0:
int builtin_macro0(int a) {
// CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:15 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:15 = M:3, C:2
return (__LINE__ // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:11 = 0, 0 [1,2,0]
&& a); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:15 = #2, (#1 - #2) [2,0,0]
}
// CHECK: builtin_macro1:
int builtin_macro1(int a) {
// CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:22 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:22 = M:3, C:2
return (a // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = (#0 - #1), #1 [1,0,2]
|| __LINE__); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:14 = 0, 0 [2,0,0]
}
@ -18,7 +18,7 @@ int builtin_macro1(int a) {
// CHECK: pre0:
int pre0(int pre_a, int b_post) {
// CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:20 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:20 = M:3, C:2
// CHECK: Expansion,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:14 = #0 (Expanded file = 1)
return (PRE(a)
&& b_post);
@ -30,7 +30,7 @@ int pre0(int pre_a, int b_post) {
// CHECK: pre1:
int pre1(int pre_a, int b_post) {
// CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:20 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:20 = M:3, C:2
// CHECK: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:14 = #0 (Expanded file = 1)
// CHECK: Branch,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #2, (#1 - #2) [2,0,0]
return (PRE(foo)
@ -43,7 +43,7 @@ int pre1(int pre_a, int b_post) {
// CHECK: post0:
int post0(int pre_a, int b_post) {
// CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:18 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:18 = M:3, C:2
// CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:16 = (#0 - #1), #1 [1,0,2]
return (pre_a
|| POST(b));
@ -55,7 +55,7 @@ int post0(int pre_a, int b_post) {
// CHECK: post1:
int post1(int pre_a, int b_post) {
// CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:18 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:18 = M:3, C:2
// CHECK: Branch,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = (#0 - #1), #1 [1,0,2]
// CHECK: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:18 = 0 (Expanded file = 1)
return (pre_a

View File

@ -15,7 +15,7 @@
// CHECK: _Z5func0i:
int func0(int a) {
// CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:3, C:2
// W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1)
// X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = 0, 0 [1,2,0]
return (CONST && a);
@ -25,7 +25,7 @@ int func0(int a) {
// CHECK: _Z5func1ii:
int func1(int a, int b) {
// CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:0, C:2
// CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:3, C:2
// CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:12 = (#0 - #1), #1 [1,0,2]
return (a || EXPR1(b));
// W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 (Expanded file = 1)
@ -35,8 +35,8 @@ int func1(int a, int b) {
// CHECK: _Z5func2ii:
int func2(int a, int b) {
// W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:0, C:3
// X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:0, C:2
// W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:4, C:3
// X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:3, C:2
// W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 (Expanded file = 1)
// W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 (Expanded file = 2)
// X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, (#0 - #1) [1,2,0]

View File

@ -36,23 +36,24 @@ Value::~Value(void) {
// SHIFT FIRST CONDITION WITH ID = 0.
// MCDCCTOR: %[[LAB1:[0-9]+]] = load i32, ptr %value, align 4
// MCDCCTOR-DAG: %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 2
// MCDCCTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCCTOR-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDCCTOR-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
// MCDCCTOR-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDCCTOR-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDCCTOR-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDCCTOR-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDCCTOR-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDCCTOR-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT SECOND CONDITION WITH ID = 1.
// MCDCCTOR: %[[LAB1:[0-9]+]] = load i32, ptr %value2, align 4
// MCDCCTOR-DAG: %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 6
// MCDCCTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCCTOR-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDCCTOR-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
// MCDCCTOR-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDCCTOR-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDCCTOR-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 2
// MCDCCTOR-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
// MCDCCTOR-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDCCTOR-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// UPDATE FINAL BITMASK WITH RESULT.
// MCDCCTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCCTOR-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCCTOR: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
// MCDCCTOR: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDCCTOR: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm__ZN5ValueC2Ev, i32 %[[LAB1]]
// MCDCCTOR: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
@ -73,23 +74,24 @@ Value::~Value(void) {
// SHIFT FIRST CONDITION WITH ID = 0.
// MCDCDTOR: %[[LAB1:[0-9]+]] = load i32, ptr %value, align 4
// MCDCDTOR-DAG: %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 2
// MCDCDTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCDTOR-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDCDTOR-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
// MCDCDTOR-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDCDTOR-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDCDTOR-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDCDTOR-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDCDTOR-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDCDTOR-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT SECOND CONDITION WITH ID = 1.
// MCDCDTOR: %[[LAB1:[0-9]+]] = load i32, ptr %value2, align 4
// MCDCDTOR-DAG: %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 3
// MCDCDTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCDTOR-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDCDTOR-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
// MCDCDTOR-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDCDTOR-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDCDTOR-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 2
// MCDCDTOR-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
// MCDCDTOR-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDCDTOR-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// UPDATE FINAL BITMASK WITH RESULT.
// MCDCDTOR-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCDTOR-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDCDTOR: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
// MCDCDTOR: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDCDTOR: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm__ZN5ValueD2Ev, i32 %[[LAB1]]
// MCDCDTOR: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7

View File

@ -9,7 +9,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// NOMCDC-NOT: __profbm_test
// MCDC BOOKKEEPING.
// MCDC: @__profbm_test = private global [3 x i8] zeroinitializer
// MCDC: @__profbm_test = private global [2 x i8] zeroinitializer
// ALLOCATE MCDC TEMP AND ZERO IT.
// MCDC-LABEL: @test(
@ -18,7 +18,8 @@ int test(int a, int b, int c, int d, int e, int f) {
// TERNARY TRUE SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 0.
// MCDC-LABEL: cond.true:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
@ -34,9 +35,10 @@ int test(int a, int b, int c, int d, int e, int f) {
// TERNARY TRUE YIELDS TERNARY LHS LOGICAL-AND.
// TERNARY LHS LOGICAL-AND SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 1.
// MCDC-LABEL: land.end:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 3
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 1), i32 %[[LAB1]]
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]
@ -46,7 +48,8 @@ int test(int a, int b, int c, int d, int e, int f) {
// TERNARY FALSE SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 0.
// MCDC-LABEL: cond.false:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
@ -62,9 +65,10 @@ int test(int a, int b, int c, int d, int e, int f) {
// TERNARY FALSE YIELDS TERNARY RHS LOGICAL-OR.
// TERNARY RHS LOGICAL-OR SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 2.
// MCDC-LABEL: lor.end:
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 6
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 2), i32 %[[LAB1]]
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
// MCDC: %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
// MCDC: %[[LAB7:[0-9]+]] = shl i8 1, %[[LAB6]]

View File

@ -20,42 +20,43 @@ int test(int b, int c, int d, int e, int f) {
// MCDC-LABEL: cond.true:
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %c.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// TERNARY FALSE SHOULD SHIFT ID = 0 FOR CONDITION 'd'.
// MCDC-LABEL: cond.false:
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %d.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT SECOND CONDITION WITH ID = 2.
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %e.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 2
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT THIRD CONDITION WITH ID = 1.
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %f.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 3
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 2
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// UPDATE FINAL BITMASK WITH RESULT.
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7

View File

@ -9,7 +9,7 @@ int test(int a, int b, int c, int d, int e, int f) {
// NOMCDC-NOT: __profbm_test
// MCDC BOOKKEEPING.
// MCDC: @__profbm_test = private global [8 x i8] zeroinitializer
// MCDC: @__profbm_test = private global [2 x i8] zeroinitializer
// MCDC: @__profc_test = private global [9 x i64] zeroinitializer
// ALLOCATE MCDC TEMP AND ZERO IT.
@ -21,61 +21,62 @@ int test(int a, int b, int c, int d, int e, int f) {
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %a.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[LNOT:lnot[0-9]*]] = xor i1 %[[BOOL]]
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[LNOT]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[LNOT]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT SECOND CONDITION WITH ID = 2.
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %b.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 2
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 14
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT THIRD CONDITION WITH ID = 1.
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %c.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[LNOT:lnot[0-9]*]] = xor i1 %[[BOOL]]
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[LNOT]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[LNOT]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT FOURTH CONDITION WITH ID = 4.
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %d.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 4
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 12
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 2
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT FIFTH CONDITION WITH ID = 3.
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %e.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 3
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT SIXTH CONDITION WITH ID = 5.
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %f.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[LNOT:lnot[0-9]*]] = xor i1 %[[BOOL]]
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[LNOT]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 5
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 8
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 4
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[LNOT]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// UPDATE FINAL BITMASK WITH RESULT.
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7

View File

@ -11,85 +11,80 @@ int test(int a, int b, int c, int d, int e, int f) {
// NOPROFPASS-NOT: __profbm_test
// MCDC BOOKKEEPING.
// MCDC: @__profbm_test = private global [8 x i8] zeroinitializer
// MCDC: @__profbm_test = private global [2 x i8] zeroinitializer
// MCDC: @__profc_test = private global [9 x i64] zeroinitializer
// ALLOCATE MCDC TEMP AND ZERO IT.
// NOPROFPASS-LABEL: @test(
// NOPROFPASS: call void @llvm.instrprof.mcdc.parameters(ptr @__profn_test, i64 [[HASH:[0-9]+]], i32 8)
// NOPROFPASS: call void @llvm.instrprof.mcdc.parameters(ptr @__profn_test, i64 [[HASH:[0-9]+]], i32 15)
// MCDC-LABEL: @test(
// MCDC: %mcdc.addr = alloca i32, align 4
// MCDC: store i32 0, ptr %mcdc.addr, align 4
// SHIFT FIRST CONDITION WITH ID = 0.
// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 0, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %a.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT SECOND CONDITION WITH ID = 2.
// NOPROFPASS-LABEL: land.lhs.true:
// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 2, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %b.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 2
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 14
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT THIRD CONDITION WITH ID = 1.
// NOPROFPASS-LABEL: lor.rhs:
// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 1, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %c.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT FOURTH CONDITION WITH ID = 4.
// NOPROFPASS-LABEL: land.lhs.true3:
// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 4, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %d.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 4
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 12
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 2
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT FIFTH CONDITION WITH ID = 3.
// NOPROFPASS-LABEL: lor.rhs6:
// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 3, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %e.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 3
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// SHIFT SIXTH CONDITION WITH ID = 5.
// NOPROFPASS-LABEL: land.rhs:
// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 5, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
// MCDC: %[[LAB1:[0-9]+]] = load i32, ptr %f.addr, align 4
// MCDC-DAG: %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
// MCDC-DAG: %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 5
// MCDC-DAG: %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
// MCDC-DAG: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
// MCDC-DAG: %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 8
// MCDC-DAG: %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 4
// MCDC-DAG: %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
// MCDC-DAG: store i32 %[[LAB4]], ptr %mcdc.addr, align 4
// UPDATE FINAL BITMASK WITH RESULT.
// NOPROFPASS-LABEL: lor.end:
// NOPROFPASS: call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 8, i32 0, ptr %mcdc.addr)
// MCDC-DAG: %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// NOPROFPASS: call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 0, i32 0, ptr %mcdc.addr)
// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
// MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
// MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
// MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]]
// MCDC: %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7

View File

@ -7,7 +7,7 @@
// CHECK: Num Bitmap Bytes:
// CHECK-NEXT: $1
// CHECK-NEXT: Bitmap Byte Values:
// CHECK-NEXT: 8
// CHECK-NEXT: 0x4
#include <stdio.h>
#include <stdlib.h>
extern int __llvm_profile_is_continuous_mode_enabled(void);

View File

@ -148,7 +148,7 @@ There are several kinds of mapping regions:
* Decision regions associate multiple branch regions with a boolean
expression in the source code. This information also includes the number of
bitmap bytes needed to represent the expression's executed test vectors as
bitmap bits needed to represent the expression's executed test vectors as
well as the total number of instrumentable branch conditions that comprise
the expression. Decision regions are used to visualize Modified
Condition/Decision Coverage (MC/DC) in *llvm-cov* for each boolean

View File

@ -14411,7 +14411,7 @@ Syntax:
::
declare void @llvm.instrprof.mcdc.parameters(ptr <name>, i64 <hash>,
i32 <bitmap-bytes>)
i32 <bitmap-bits>)
Overview:
"""""""""
@ -14429,7 +14429,7 @@ name of the entity being instrumented. This should generally be the
The second argument is a hash value that can be used by the consumer
of the profile data to detect changes to the instrumented source.
The third argument is the number of bitmap bytes required by the function to
The third argument is the number of bitmap bits required by the function to
record the number of test vectors executed for each boolean expression.
Semantics:
@ -14496,7 +14496,7 @@ Syntax:
::
declare void @llvm.instrprof.mcdc.tvbitmap.update(ptr <name>, i64 <hash>,
i32 <bitmap-bytes>)
i32 <unused>)
i32 <bitmap-index>,
ptr <mcdc-temp-addr>)
@ -14506,10 +14506,9 @@ Overview:
The '``llvm.instrprof.mcdc.tvbitmap.update``' intrinsic is used to track MC/DC
test vector execution after each boolean expression has been fully executed.
The overall value of the condition bitmap, after it has been successively
updated using the '``llvm.instrprof.mcdc.condbitmap.update``' intrinsic with
the true or false evaluation of each condition, uniquely identifies an executed
MC/DC test vector and is used as a bit index into the global test vector
bitmap.
updated with the true or false evaluation of each condition, uniquely identifies
an executed MC/DC test vector and is used as a bit index into the global test
vector bitmap.
Arguments:
""""""""""
@ -14521,10 +14520,9 @@ name of the entity being instrumented. This should generally be the
The second argument is a hash value that can be used by the consumer
of the profile data to detect changes to the instrumented source.
The third argument is the number of bitmap bytes required by the function to
record the number of test vectors executed for each boolean expression.
The third argument is not used.
The fourth argument is the byte index into the global test vector bitmap
The fourth argument is the bit index into the global test vector bitmap
corresponding to the function.
The fifth argument is the address of the condition bitmap, which contains a

View File

@ -33,6 +33,7 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <cstdint>
#include <optional>
@ -1580,10 +1581,16 @@ public:
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
/// \return The number of bits used for the MCDC bitmaps for the instrumented
/// function.
ConstantInt *getNumBitmapBits() const {
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
}
/// \return The number of bytes used for the MCDC bitmaps for the instrumented
/// function.
ConstantInt *getNumBitmapBytes() const {
return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
auto getNumBitmapBytes() const {
return alignTo(getNumBitmapBits()->getZExtValue(), CHAR_BIT) / CHAR_BIT;
}
};

View File

@ -677,7 +677,8 @@ public:
/// pairs.
Expected<MCDCRecord>
evaluateMCDCRegion(const CounterMappingRegion &Region,
ArrayRef<const CounterMappingRegion *> Branches);
ArrayRef<const CounterMappingRegion *> Branches,
bool IsVersion11);
unsigned getMaxCounterID(const Counter &C) const;
};

View File

@ -1161,7 +1161,7 @@ enum ProfVersion {
Version10 = 10,
// An additional field is used for bitmap bytes.
Version11 = 11,
// VTable profiling,
// VTable profiling, decision record and bitmap are modified for mcdc.
Version12 = 12,
// The current version is 12.
CurrentVersion = INSTR_PROF_INDEX_VERSION

View File

@ -384,15 +384,18 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
DenseSet<unsigned> TVIdxs;
#endif
bool IsVersion11;
public:
MCDCRecordProcessor(const BitVector &Bitmap,
const CounterMappingRegion &Region,
ArrayRef<const CounterMappingRegion *> Branches)
ArrayRef<const CounterMappingRegion *> Branches,
bool IsVersion11)
: NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
Region(Region), DecisionParams(Region.getDecisionParams()),
Branches(Branches), NumConditions(DecisionParams.NumConditions),
Folded(NumConditions, false), IndependencePairs(NumConditions),
ExecVectors(ExecVectorsByCond[false]) {}
ExecVectors(ExecVectorsByCond[false]), IsVersion11(IsVersion11) {}
private:
// Walk the binary decision diagram and try assigning both false and true to
@ -415,7 +418,9 @@ private:
assert(TVIdx < SavedNodes[ID].Width);
assert(TVIdxs.insert(NextTVIdx).second && "Duplicate TVIdx");
if (!Bitmap[DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()])
if (!Bitmap[IsVersion11
? DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()
: DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
continue;
// Copy the completed test vector to the vector of testvectors.
@ -521,9 +526,9 @@ public:
Expected<MCDCRecord> CounterMappingContext::evaluateMCDCRegion(
const CounterMappingRegion &Region,
ArrayRef<const CounterMappingRegion *> Branches) {
ArrayRef<const CounterMappingRegion *> Branches, bool IsVersion11) {
MCDCRecordProcessor MCDCProcessor(Bitmap, Region, Branches);
MCDCRecordProcessor MCDCProcessor(Bitmap, Region, Branches, IsVersion11);
return MCDCProcessor.processMCDCRecord();
}
@ -610,8 +615,8 @@ static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
}
/// Returns the bit count
static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx,
const CoverageMappingRecord &Record) {
static unsigned getMaxBitmapSize(const CoverageMappingRecord &Record,
bool IsVersion11) {
unsigned MaxBitmapIdx = 0;
unsigned NumConditions = 0;
// Scan max(BitmapIdx).
@ -626,8 +631,12 @@ static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx,
NumConditions = DecisionParams.NumConditions;
}
}
unsigned SizeInBits = llvm::alignTo(uint64_t(1) << NumConditions, CHAR_BIT);
return MaxBitmapIdx * CHAR_BIT + SizeInBits;
if (IsVersion11)
MaxBitmapIdx = MaxBitmapIdx * CHAR_BIT +
llvm::alignTo(uint64_t(1) << NumConditions, CHAR_BIT);
return MaxBitmapIdx;
}
namespace {
@ -815,6 +824,9 @@ Error CoverageMapping::loadFunctionRecord(
}
Ctx.setCounts(Counts);
bool IsVersion11 =
ProfileReader.getVersion() < IndexedInstrProf::ProfVersion::Version12;
BitVector Bitmap;
if (Error E = ProfileReader.getFunctionBitmap(Record.FunctionName,
Record.FunctionHash, Bitmap)) {
@ -826,7 +838,7 @@ Error CoverageMapping::loadFunctionRecord(
}
if (IPE != instrprof_error::unknown_function)
return make_error<InstrProfError>(IPE);
Bitmap = BitVector(getMaxBitmapSize(Ctx, Record));
Bitmap = BitVector(getMaxBitmapSize(Record, IsVersion11));
}
Ctx.setBitmap(std::move(Bitmap));
@ -884,7 +896,7 @@ Error CoverageMapping::loadFunctionRecord(
// DecisionRegion, all of the information is now available to process.
// This is where the bulk of the MC/DC progressing takes place.
Expected<MCDCRecord> Record =
Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches);
Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
if (auto E = Record.takeError()) {
consumeError(std::move(E));
return Error::success();

View File

@ -936,9 +936,6 @@ Value *InstrLowerer::getBitmapAddress(InstrProfMCDCTVBitmapUpdate *I) {
auto *Bitmaps = getOrCreateRegionBitmaps(I);
IRBuilder<> Builder(I);
auto *Addr = Builder.CreateConstInBoundsGEP2_32(
Bitmaps->getValueType(), Bitmaps, 0, I->getBitmapIndex()->getZExtValue());
if (isRuntimeCounterRelocationEnabled()) {
LLVMContext &Ctx = M.getContext();
Ctx.diagnose(DiagnosticInfoPGOProfile(
@ -948,7 +945,7 @@ Value *InstrLowerer::getBitmapAddress(InstrProfMCDCTVBitmapUpdate *I) {
DS_Warning));
}
return Addr;
return Bitmaps;
}
void InstrLowerer::lowerCover(InstrProfCoverInst *CoverInstruction) {
@ -1018,9 +1015,11 @@ void InstrLowerer::lowerMCDCTestVectorBitmapUpdate(
auto *MCDCCondBitmapAddr = Update->getMCDCCondBitmapAddr();
auto *BitmapAddr = getBitmapAddress(Update);
// Load Temp Val.
// Load Temp Val + BitmapIdx.
// %mcdc.temp = load i32, ptr %mcdc.addr, align 4
auto *Temp = Builder.CreateLoad(Int32Ty, MCDCCondBitmapAddr, "mcdc.temp");
auto *Temp = Builder.CreateAdd(
Builder.CreateLoad(Int32Ty, MCDCCondBitmapAddr, "mcdc.temp"),
Update->getBitmapIndex());
// Calculate byte offset using div8.
// %1 = lshr i32 %mcdc.temp, 3
@ -1415,7 +1414,7 @@ GlobalVariable *
InstrLowerer::createRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc,
StringRef Name,
GlobalValue::LinkageTypes Linkage) {
uint64_t NumBytes = Inc->getNumBitmapBytes()->getZExtValue();
uint64_t NumBytes = Inc->getNumBitmapBytes();
auto *BitmapTy = ArrayType::get(Type::getInt8Ty(M.getContext()), NumBytes);
auto GV = new GlobalVariable(M, BitmapTy, false, Linkage,
Constant::getNullValue(BitmapTy), Name);
@ -1434,7 +1433,7 @@ InstrLowerer::getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc) {
// the corresponding profile section.
auto *BitmapPtr = setupProfileSection(Inc, IPSK_bitmap);
PD.RegionBitmaps = BitmapPtr;
PD.NumBitmapBytes = Inc->getNumBitmapBytes()->getZExtValue();
PD.NumBitmapBytes = Inc->getNumBitmapBytes();
return PD.RegionBitmaps;
}

View File

@ -27,21 +27,21 @@ declare void @llvm.instrprof.mcdc.parameters(ptr %0, i64 %1, i32 %2)
define internal void @foobar() {
call void @llvm.instrprof.increment(ptr @__profn_foobar, i64 123456, i32 32, i32 0)
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foobar, i64 123456, i32 99)
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foobar, i64 123456, i32 792)
ret void
}
define void @foo() {
call void @llvm.instrprof.increment(ptr @__profn_foo, i64 123456, i32 32, i32 0)
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foo, i64 123456, i32 21)
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foo, i64 123456, i32 168)
call void @foobar()
ret void
}
define void @bar() {
call void @llvm.instrprof.increment(ptr @__profn_bar, i64 123456, i32 32, i32 0)
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_bar, i64 123456, i32 23)
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_bar, i64 123456, i32 184)
call void @foobar()
ret void
}

View File

@ -30,7 +30,8 @@ entry:
; CHECK-NEXT: store i32 %[[LAB3]], ptr %mcdc.addr, align 4
call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 99278, i32 1, i32 0, ptr %mcdc.addr)
; CHECK: %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
; CHECK: %[[TEMP0:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
; CHECK-NEXT: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
; CHECK-NEXT: %[[LAB4:[0-9]+]] = lshr i32 %[[TEMP]], 3
; CHECK-NEXT: %[[LAB7:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB4]]
; CHECK-NEXT: %[[LAB8:[0-9]+]] = and i32 %[[TEMP]], 7

View File

@ -40,7 +40,7 @@ _Z5case2b
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0xa
0x6
_Z5case3b
@ -55,7 +55,7 @@ _Z5case3b
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x9
0x5
_Z5case4b
@ -70,7 +70,7 @@ _Z5case4b
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x2
0x1
_Z5case5b
@ -85,7 +85,7 @@ _Z5case5b
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x6
0x5
_Z5case6b
@ -100,7 +100,7 @@ _Z5case6b
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x5
0x6
_Z5case7b
@ -166,7 +166,7 @@ _Z5caseabb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0xa2
0xe
_Z5casebbb
@ -183,7 +183,7 @@ _Z5casebbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0xa1
0xd
_Z5casecbb
@ -200,7 +200,7 @@ _Z5casecbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x2
0x1
_Z5casedbb
@ -217,7 +217,7 @@ _Z5casedbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x12
0x3
_Z5caseebb
@ -234,7 +234,7 @@ _Z5caseebb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x14
0xa
_Z5casefbb
@ -251,7 +251,7 @@ _Z5casefbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x6
0x9
_Z5casegbb
@ -268,7 +268,7 @@ _Z5casegbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x23
0x7
_Z5casehbb
@ -302,7 +302,7 @@ _Z5caseibb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x83
0xb
_Z5casejbb
@ -319,7 +319,7 @@ _Z5casejbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0xa1
0xd
_Z5casekbb
@ -336,7 +336,7 @@ _Z5casekbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x12
0x3
_Z5caselbb
@ -353,7 +353,7 @@ _Z5caselbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x12
0x3
_Z5casembb
@ -370,7 +370,7 @@ _Z5casembb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x12
0x3
_Z5casenbb
@ -387,7 +387,7 @@ _Z5casenbb
# Num Bitmap Bytes:
$1
# Bitmap Byte Values:
0x6
0x9
main

View File

@ -14,12 +14,10 @@ _Z4testbbbb
0
0
# Num Bitmap Bytes:
$4
$2
# Bitmap Byte Values:
0x1
0x2
0x0
0x0
0x4
main

Binary file not shown.

View File

@ -24,14 +24,11 @@ _Z4testbbbb
2
1
# Num Bitmap Bytes:
$6
$3
# Bitmap Byte Values:
0x2f
0x8
0xb
0x9
0x83
0x80
0xef
0x77
0x3
main

View File

@ -27,21 +27,12 @@ func
0
0
# Num Bitmap Bytes:
$13
$4
# Bitmap Byte Values:
0x0
0x9
0x0
0x0
0x20
0x8
0x0
0x20
0x0
0x0
0x0
0x0
0x0
0x0
0x1
func1

View File

@ -0,0 +1,20 @@
// Test Version11 (clang-18) files.
// mcdc-general.test is used as test patterns.
// RUN: llvm-cov show --show-mcdc %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/mcdc-general.test
// RUN: llvm-cov report --show-mcdc-summary %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %S/mcdc-general.test -check-prefix=REPORT
// Turn off MC/DC visualization.
// RUN: llvm-cov show %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/mcdc-general.test -check-prefix=NOMCDC
// Turn off MC/DC summary.
// RUN: llvm-cov report %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %S/mcdc-general.test -check-prefix=REPORT_NOMCDC
// Test file-level report.
// RUN: llvm-cov report --show-mcdc-summary %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %S/mcdc-general.test -check-prefix=FILEREPORT
// Test html output.
// RUN: rm -rf %t.html.dir
// RUN: llvm-cov show --show-mcdc-summary --show-mcdc %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs -format html -o %t.html.dir
// RUN: FileCheck -check-prefix=HTML -input-file=%t.html.dir/coverage/mcdc-general.cpp.html %S/mcdc-general.test
// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %S/mcdc-general.test

View File

@ -872,7 +872,7 @@ TEST_P(CoverageMappingTest, non_code_region_bitmask) {
addCMR(Counter::getCounter(2), "file", 1, 1, 5, 5);
addCMR(Counter::getCounter(3), "file", 1, 1, 5, 5);
addMCDCDecisionCMR(0, 2, "file", 7, 1, 7, 6);
addMCDCDecisionCMR(3, 2, "file", 7, 1, 7, 6);
addMCDCBranchCMR(Counter::getCounter(0), Counter::getCounter(1), 0, {-1, 1},
"file", 7, 2, 7, 3);
addMCDCBranchCMR(Counter::getCounter(2), Counter::getCounter(3), 1, {-1, -1},
@ -895,7 +895,7 @@ TEST_P(CoverageMappingTest, decision_before_expansion) {
addCMR(Counter::getCounter(0), "foo", 3, 23, 5, 2);
// This(4:11) was put after Expansion(4:11) before the fix
addMCDCDecisionCMR(0, 2, "foo", 4, 11, 4, 20);
addMCDCDecisionCMR(3, 2, "foo", 4, 11, 4, 20);
addExpansionCMR("foo", "A", 4, 11, 4, 12);
addExpansionCMR("foo", "B", 4, 19, 4, 20);