Skip to content

Commit ce54b22

Browse files
committed
[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
1 parent f15c602 commit ce54b22

File tree

3 files changed

+22
-14
lines changed

3 files changed

+22
-14
lines changed

clang/lib/CodeGen/CoverageMappingGen.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -550,17 +550,18 @@ struct CounterCoverageMappingBuilder
550550
Counter GapRegionCounter;
551551

552552
/// Return a counter for the subtraction of \c RHS from \c LHS
553-
Counter subtractCounters(Counter LHS, Counter RHS) {
554-
return Builder.subtract(LHS, RHS);
553+
Counter subtractCounters(Counter LHS, Counter RHS, bool Simplify = true) {
554+
return Builder.subtract(LHS, RHS, Simplify);
555555
}
556556

557557
/// Return a counter for the sum of \c LHS and \c RHS.
558-
Counter addCounters(Counter LHS, Counter RHS) {
559-
return Builder.add(LHS, RHS);
558+
Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
559+
return Builder.add(LHS, RHS, Simplify);
560560
}
561561

562-
Counter addCounters(Counter C1, Counter C2, Counter C3) {
563-
return addCounters(addCounters(C1, C2), C3);
562+
Counter addCounters(Counter C1, Counter C2, Counter C3,
563+
bool Simplify = true) {
564+
return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
564565
}
565566

566567
/// Return the region counter for the given statement.
@@ -1317,11 +1318,16 @@ struct CounterCoverageMappingBuilder
13171318
const SwitchCase *Case = S->getSwitchCaseList();
13181319
for (; Case; Case = Case->getNextSwitchCase()) {
13191320
HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
1320-
CaseCountSum = addCounters(CaseCountSum, getRegionCounter(Case));
1321+
CaseCountSum =
1322+
addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false);
13211323
createSwitchCaseRegion(
13221324
Case, getRegionCounter(Case),
13231325
subtractCounters(ParentCount, getRegionCounter(Case)));
13241326
}
1327+
// Simplify is skipped while building the counters above: it can get really
1328+
// slow on top of switches with thousands of cases. Instead, trigger
1329+
// simplification by adding zero to the last counter.
1330+
CaseCountSum = addCounters(CaseCountSum, Counter::getZero());
13251331

13261332
// If no explicit default case exists, create a branch region to represent
13271333
// the hidden branch, which will be added later by the CodeGen. This region

llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,11 @@ class CounterExpressionBuilder {
195195
ArrayRef<CounterExpression> getExpressions() const { return Expressions; }
196196

197197
/// Return a counter that represents the expression that adds LHS and RHS.
198-
Counter add(Counter LHS, Counter RHS);
198+
Counter add(Counter LHS, Counter RHS, bool Simplify = true);
199199

200200
/// Return a counter that represents the expression that subtracts RHS from
201201
/// LHS.
202-
Counter subtract(Counter LHS, Counter RHS);
202+
Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
203203
};
204204

205205
using LineColPair = std::pair<unsigned, unsigned>;

llvm/lib/ProfileData/Coverage/CoverageMapping.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,15 @@ Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
123123
return C;
124124
}
125125

126-
Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) {
127-
return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS)));
126+
Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS, bool Simplify) {
127+
auto Cnt = get(CounterExpression(CounterExpression::Add, LHS, RHS));
128+
return Simplify ? simplify(Cnt) : Cnt;
128129
}
129130

130-
Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) {
131-
return simplify(
132-
get(CounterExpression(CounterExpression::Subtract, LHS, RHS)));
131+
Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS,
132+
bool Simplify) {
133+
auto Cnt = get(CounterExpression(CounterExpression::Subtract, LHS, RHS));
134+
return Simplify ? simplify(Cnt) : Cnt;
133135
}
134136

135137
void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {

0 commit comments

Comments
 (0)