Author: Bruno Cardoso Lopes Date: 2022-05-26T11:05:15-07:00 New Revision: ce54b22657f01d1c40de4941ceb6e7119848aecf
URL: https://github.com/llvm/llvm-project/commit/ce54b22657f01d1c40de4941ceb6e7119848aecf DIFF: https://github.com/llvm/llvm-project/commit/ce54b22657f01d1c40de4941ceb6e7119848aecf.diff LOG: [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 Added: Modified: clang/lib/CodeGen/CoverageMappingGen.cpp llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h llvm/lib/ProfileData/Coverage/CoverageMapping.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 9b81c8a670f59..8952125eeefcb 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 diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index e1f45019b1a92..e35751512245d 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -195,11 +195,11 @@ class CounterExpressionBuilder { ArrayRef<CounterExpression> getExpressions() const { return Expressions; } /// Return a counter that represents the expression that adds LHS and RHS. - Counter add(Counter LHS, Counter RHS); + Counter add(Counter LHS, Counter RHS, bool Simplify = true); /// Return a counter that represents the expression that subtracts RHS from /// LHS. - Counter subtract(Counter LHS, Counter RHS); + Counter subtract(Counter LHS, Counter RHS, bool Simplify = true); }; using LineColPair = std::pair<unsigned, unsigned>; diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 94c2bee3590cb..f9e58fd6afa50 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -123,13 +123,15 @@ Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) { return C; } -Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) { - return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS))); +Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS, bool Simplify) { + auto Cnt = get(CounterExpression(CounterExpression::Add, LHS, RHS)); + return Simplify ? simplify(Cnt) : Cnt; } -Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) { - return simplify( - get(CounterExpression(CounterExpression::Subtract, LHS, RHS))); +Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS, + bool Simplify) { + auto Cnt = get(CounterExpression(CounterExpression::Subtract, LHS, RHS)); + return Simplify ? simplify(Cnt) : Cnt; } void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits