aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CoverageMappingGen.cpp
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2022-05-24 16:56:22 -0700
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2022-05-26 11:05:15 -0700
commitce54b22657f01d1c40de4941ceb6e7119848aecf (patch)
treed3b95e3df50eb0fcac295b96a600cde0a115761b /clang/lib/CodeGen/CoverageMappingGen.cpp
parentf15c60218d5c88c9f32942bce119e7ac25cb6d73 (diff)
downloadllvm-ce54b22657f01d1c40de4941ceb6e7119848aecf.zip
llvm-ce54b22657f01d1c40de4941ceb6e7119848aecf.tar.gz
llvm-ce54b22657f01d1c40de4941ceb6e7119848aecf.tar.bz2
[Clang][CoverageMapping] Fix switch counter codegen compile time explosion
C++ generated code with huge amount of switch cases chokes badly while emitting coverage mapping, in our specific testcase (~72k cases), it won't stop after hours. After this change, the frontend job now finishes in 4.5s and shrinks down `@__covrec_` by 288k when compared to disabling simplification altogether. There's probably no good way to create a testcase for this, but it's easy to reproduce, just add thousands of cases in the below switch, and build with `-fprofile-instr-generate -fcoverage-mapping`. ``` enum type : int { FEATURE_INVALID = 0, FEATURE_A = 1, ... }; const char *to_string(type e) { switch (e) { case type::FEATURE_INVALID: return "FEATURE_INVALID"; case type::FEATURE_A: return "FEATURE_A";} ... } ``` Differential Revision: https://reviews.llvm.org/D126345
Diffstat (limited to 'clang/lib/CodeGen/CoverageMappingGen.cpp')
-rw-r--r--clang/lib/CodeGen/CoverageMappingGen.cpp20
1 files changed, 13 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 9b81c8a..8952125 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -550,17 +550,18 @@ struct CounterCoverageMappingBuilder
Counter GapRegionCounter;
/// Return a counter for the subtraction of \c RHS from \c LHS
- Counter subtractCounters(Counter LHS, Counter RHS) {
- return Builder.subtract(LHS, RHS);
+ Counter subtractCounters(Counter LHS, Counter RHS, bool Simplify = true) {
+ return Builder.subtract(LHS, RHS, Simplify);
}
/// Return a counter for the sum of \c LHS and \c RHS.
- Counter addCounters(Counter LHS, Counter RHS) {
- return Builder.add(LHS, RHS);
+ Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
+ return Builder.add(LHS, RHS, Simplify);
}
- Counter addCounters(Counter C1, Counter C2, Counter C3) {
- return addCounters(addCounters(C1, C2), C3);
+ Counter addCounters(Counter C1, Counter C2, Counter C3,
+ bool Simplify = true) {
+ return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
}
/// Return the region counter for the given statement.
@@ -1317,11 +1318,16 @@ struct CounterCoverageMappingBuilder
const SwitchCase *Case = S->getSwitchCaseList();
for (; Case; Case = Case->getNextSwitchCase()) {
HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
- CaseCountSum = addCounters(CaseCountSum, getRegionCounter(Case));
+ CaseCountSum =
+ addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false);
createSwitchCaseRegion(
Case, getRegionCounter(Case),
subtractCounters(ParentCount, getRegionCounter(Case)));
}
+ // 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