aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CoverageMappingGen.cpp
diff options
context:
space:
mode:
authorNAKAMURA Takumi <geek4civic@gmail.com>2024-06-13 20:09:02 +0900
committerNAKAMURA Takumi <geek4civic@gmail.com>2024-06-14 19:31:56 +0900
commit71f8b441ed6a944ceb4530b49e8588dcbb1e0066 (patch)
treee03f6259e4ef7d0512f7c40238d2288f34ac210f /clang/lib/CodeGen/CoverageMappingGen.cpp
parent1ceede3318c29af83b219cca137f5e2c563fc871 (diff)
downloadllvm-71f8b441ed6a944ceb4530b49e8588dcbb1e0066.zip
llvm-71f8b441ed6a944ceb4530b49e8588dcbb1e0066.tar.gz
llvm-71f8b441ed6a944ceb4530b49e8588dcbb1e0066.tar.bz2
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
Diffstat (limited to 'clang/lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r--clang/lib/CodeGen/CoverageMappingGen.cpp77
1 files changed, 72 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 6ce2d32..ba483d8 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -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) {