aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CoverageMappingGen.cpp
diff options
context:
space:
mode:
authorNAKAMURA Takumi <geek4civic@gmail.com>2024-10-20 12:30:35 +0900
committerGitHub <noreply@github.com>2024-10-20 12:30:35 +0900
commit4a011ac84fa16f7eed34c309bdac5591d9553da7 (patch)
treea10ddc411322a8a737f84130e554fa36a0777f8f /clang/lib/CodeGen/CoverageMappingGen.cpp
parent1336e3d0b9a361fbbe2d97f225ef6757d20df51a (diff)
downloadllvm-4a011ac84fa16f7eed34c309bdac5591d9553da7.zip
llvm-4a011ac84fa16f7eed34c309bdac5591d9553da7.tar.gz
llvm-4a011ac84fa16f7eed34c309bdac5591d9553da7.tar.bz2
[Coverage] Introduce "partial fold" on BranchRegion (#112694)
Currently both True/False counts were folded. It lost the information, "It is True or False before folding." It prevented recalling branch counts in merging template instantiations. In `llvm-cov`, a folded branch is shown as: - `[True: n, Folded]` - `[Folded, False n]` In the case If `n` is zero, a branch is reported as "uncovered". This is distinguished from "folded" branch. When folded branches are merged, `Folded` may be dissolved. In the coverage map, either `Counter` is `Zero`. Currently both were `Zero`. Since "partial fold" has been introduced, either case in `switch` is omitted as `Folded`. Each `case:` in `switch` is reported as `[True: n, Folded]`, since `False` count doesn't show meaningful value. When `switch` doesn't have `default:`, `switch (Cond)` is reported as `[Folded, False: n]`, since `True` count was just the sum of `case`(s). `switch` with `default` can be considered as "the statement that doesn't have any `False`(s)".
Diffstat (limited to 'clang/lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r--clang/lib/CodeGen/CoverageMappingGen.cpp46
1 files changed, 17 insertions, 29 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 577a0f5..0a63c50 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1098,12 +1098,6 @@ struct CounterCoverageMappingBuilder
return ExitCount;
}
- /// Determine whether the given condition can be constant folded.
- bool ConditionFoldsToBool(const Expr *Cond) {
- Expr::EvalResult Result;
- return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
- }
-
/// Create a Branch Region around an instrumentable condition for coverage
/// and add it to the function's SourceRegions. A branch region tracks a
/// "True" counter and a "False" counter for boolean expressions that
@@ -1133,13 +1127,15 @@ struct CounterCoverageMappingBuilder
// Alternatively, we can prevent any optimization done via
// constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
// CodeGenFunction.c always returns false, but that is very heavy-handed.
- if (ConditionFoldsToBool(C))
- popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C),
- Counter::getZero(), BranchParams));
- else
- // Otherwise, create a region with the True counter and False counter.
- popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt,
- BranchParams));
+ Expr::EvalResult Result;
+ if (C->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext())) {
+ if (Result.Val.getInt().getBoolValue())
+ FalseCnt = Counter::getZero();
+ else
+ TrueCnt = Counter::getZero();
+ }
+ popRegions(
+ pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt, BranchParams));
}
}
@@ -1153,12 +1149,12 @@ struct CounterCoverageMappingBuilder
/// Create a Branch Region around a SwitchCase for code coverage
/// and add it to the function's SourceRegions.
- void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt,
- Counter FalseCnt) {
+ void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt) {
// Push region onto RegionStack but immediately pop it (which adds it to
// the function's SourceRegions) because it doesn't apply to any other
// source other than the SwitchCase.
- popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
+ popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(),
+ Counter::getZero()));
}
/// Check whether a region with bounds \c StartLoc and \c EndLoc
@@ -1870,24 +1866,16 @@ struct CounterCoverageMappingBuilder
const SwitchCase *Case = S->getSwitchCaseList();
for (; Case; Case = Case->getNextSwitchCase()) {
HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
- CaseCountSum =
- addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false);
- createSwitchCaseRegion(
- Case, getRegionCounter(Case),
- subtractCounters(ParentCount, getRegionCounter(Case)));
+ auto CaseCount = getRegionCounter(Case);
+ CaseCountSum = addCounters(CaseCountSum, CaseCount, /*Simplify=*/false);
+ createSwitchCaseRegion(Case, CaseCount);
}
- // Simplify is skipped while building the counters above: it can get really
- // slow on top of switches with thousands of cases. Instead, trigger
- // simplification by adding zero to the last counter.
- CaseCountSum = addCounters(CaseCountSum, Counter::getZero());
-
// If no explicit default case exists, create a branch region to represent
// the hidden branch, which will be added later by the CodeGen. This region
// will be associated with the switch statement's condition.
if (!HasDefaultCase) {
- Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum);
- Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue);
- createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse);
+ Counter DefaultCount = subtractCounters(ParentCount, CaseCountSum);
+ createBranchRegion(S->getCond(), Counter::getZero(), DefaultCount);
}
}