[clang] [llvm] [Coverage] Make additional counters available for BranchRegion. NFC. (PR #120930)

NAKAMURA Takumi via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 5 18:03:09 PST 2026


https://github.com/chapuni updated https://github.com/llvm/llvm-project/pull/120930

>From 618e63946923a460b2684738e636c77b1706322a Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 17 Oct 2024 01:22:54 +0900
Subject: [PATCH 01/36] Introduce CounterExpressionBuilder::replace(C, Map)

This return a counter for each term in the expression replaced by
ReplaceMap.

At the moment, this doesn't update the Map, so Map is marked as `const`.
---
 .../ProfileData/Coverage/CoverageMapping.h    |  6 ++++
 .../ProfileData/Coverage/CoverageMapping.cpp  | 32 +++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index fa07b3a9e8b14..d6528bd407ef3 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -34,6 +34,7 @@
 #include <cassert>
 #include <cstdint>
 #include <iterator>
+#include <map>
 #include <memory>
 #include <sstream>
 #include <string>
@@ -213,6 +214,11 @@ class CounterExpressionBuilder {
   /// Return a counter that represents the expression that subtracts RHS from
   /// LHS.
   Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
+
+  using ReplaceMap = std::map<Counter, Counter>;
+
+  /// Return a counter for each term in the expression replaced by ReplaceMap.
+  Counter replace(Counter C, const ReplaceMap &Map);
 };
 
 using LineColPair = std::pair<unsigned, unsigned>;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index c713371da81e4..b50f025d261e1 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -135,6 +135,38 @@ Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS,
   return Simplify ? simplify(Cnt) : Cnt;
 }
 
+Counter CounterExpressionBuilder::replace(Counter C, const ReplaceMap &Map) {
+  auto I = Map.find(C);
+
+  // Replace C with the Map even if C is Expression.
+  if (I != Map.end())
+    return I->second;
+
+  // Traverse only Expression.
+  if (!C.isExpression())
+    return C;
+
+  auto CE = Expressions[C.getExpressionID()];
+  auto NewLHS = replace(CE.LHS, Map);
+  auto NewRHS = replace(CE.RHS, Map);
+
+  // Reconstruct Expression with induced subexpressions.
+  switch (CE.Kind) {
+  case CounterExpression::Add:
+    C = add(NewLHS, NewRHS);
+    break;
+  case CounterExpression::Subtract:
+    C = subtract(NewLHS, NewRHS);
+    break;
+  }
+
+  // Reconfirm if the reconstructed expression would hit the Map.
+  if ((I = Map.find(C)) != Map.end())
+    return I->second;
+
+  return C;
+}
+
 void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const {
   switch (C.getKind()) {
   case Counter::Zero:

>From fc697f04fd6c9f3c217ce04e3f1dd082c1f1a705 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 16 Oct 2024 23:16:53 +0900
Subject: [PATCH 02/36] [Coverage] Introduce `getBranchCounterPair()`. NFC.

This aggregates the generation of branch counter pair as `ExecCnt` and
`SkipCnt`, to aggregate `CounterExpr::subtract`. At the moment:

- This change preserves the behavior of
  `llvm::EnableSingleByteCoverage`. Almost of SingleByteCoverage will
  be cleaned up by coming commits.

- `getBranchCounterPair()` is not called in
  `llvm::EnableSingleByteCoverage`. I will implement the new behavior
  of SingleByteCoverage in it.

- `IsCounterEqual(Out, Par)` is introduced instead of
  `Counter::operator==`. Tweaks would be required for the comparison
  for additional counters.

- Braces around `assert()` is intentional. I will add a statement there.

https://discourse.llvm.org/t/rfc-integrating-singlebytecoverage-with-branch-coverage/82492
---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 177 +++++++++++++----------
 1 file changed, 102 insertions(+), 75 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 07015834bc84f..0bfad9cbcbe12 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -941,6 +941,19 @@ struct CounterCoverageMappingBuilder
     return Counter::getCounter(CounterMap[S]);
   }
 
+  std::pair<Counter, Counter> getBranchCounterPair(const Stmt *S,
+                                                   Counter ParentCnt) {
+    Counter ExecCnt = getRegionCounter(S);
+    return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
+  }
+
+  bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
+    if (OutCount == ParentCount)
+      return true;
+
+    return false;
+  }
+
   /// Push a region onto the stack.
   ///
   /// Returns the index on the stack where the region was pushed. This can be
@@ -1592,6 +1605,13 @@ struct CounterCoverageMappingBuilder
         llvm::EnableSingleByteCoverage
             ? getRegionCounter(S->getCond())
             : addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+    auto [ExecCount, ExitCount] =
+        (llvm::EnableSingleByteCoverage
+             ? std::make_pair(getRegionCounter(S), Counter::getZero())
+             : getBranchCounterPair(S, CondCount));
+    if (!llvm::EnableSingleByteCoverage) {
+      assert(ExecCount.isZero() || ExecCount == BodyCount);
+    }
     propagateCounts(CondCount, S->getCond());
     adjustForOutOfOrderTraversal(getEnd(S));
 
@@ -1600,13 +1620,11 @@ struct CounterCoverageMappingBuilder
     if (Gap)
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
-    Counter OutCount =
-        llvm::EnableSingleByteCoverage
-            ? getRegionCounter(S)
-            : addCounters(BC.BreakCount,
-                          subtractCounters(CondCount, BodyCount));
+    Counter OutCount = llvm::EnableSingleByteCoverage
+                           ? getRegionCounter(S)
+                           : addCounters(BC.BreakCount, ExitCount);
 
-    if (OutCount != ParentCount) {
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
       if (BodyHasTerminateStmt)
@@ -1615,8 +1633,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(CondCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, ExitCount);
   }
 
   void VisitDoStmt(const DoStmt *S) {
@@ -1645,22 +1662,26 @@ struct CounterCoverageMappingBuilder
     Counter CondCount = llvm::EnableSingleByteCoverage
                             ? getRegionCounter(S->getCond())
                             : addCounters(BackedgeCount, BC.ContinueCount);
+    auto [ExecCount, ExitCount] =
+        (llvm::EnableSingleByteCoverage
+             ? std::make_pair(getRegionCounter(S), Counter::getZero())
+             : getBranchCounterPair(S, CondCount));
+    if (!llvm::EnableSingleByteCoverage) {
+      assert(ExecCount.isZero() || ExecCount == BodyCount);
+    }
     propagateCounts(CondCount, S->getCond());
 
-    Counter OutCount =
-        llvm::EnableSingleByteCoverage
-            ? getRegionCounter(S)
-            : addCounters(BC.BreakCount,
-                          subtractCounters(CondCount, BodyCount));
-    if (OutCount != ParentCount) {
+    Counter OutCount = llvm::EnableSingleByteCoverage
+                           ? getRegionCounter(S)
+                           : addCounters(BC.BreakCount, ExitCount);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(CondCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, ExitCount);
 
     if (BodyHasTerminateStmt)
       HasTerminateStmt = true;
@@ -1709,6 +1730,13 @@ struct CounterCoverageMappingBuilder
             : addCounters(
                   addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
                   IncrementBC.ContinueCount);
+    auto [ExecCount, ExitCount] =
+        (llvm::EnableSingleByteCoverage
+             ? std::make_pair(getRegionCounter(S), Counter::getZero())
+             : getBranchCounterPair(S, CondCount));
+    if (!llvm::EnableSingleByteCoverage) {
+      assert(ExecCount.isZero() || ExecCount == BodyCount);
+    }
 
     if (const Expr *Cond = S->getCond()) {
       propagateCounts(CondCount, Cond);
@@ -1723,9 +1751,8 @@ struct CounterCoverageMappingBuilder
     Counter OutCount =
         llvm::EnableSingleByteCoverage
             ? getRegionCounter(S)
-            : addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
-                          subtractCounters(CondCount, BodyCount));
-    if (OutCount != ParentCount) {
+            : addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, ExitCount);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
       if (BodyHasTerminateStmt)
@@ -1734,8 +1761,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(CondCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, ExitCount);
   }
 
   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
@@ -1764,15 +1790,21 @@ struct CounterCoverageMappingBuilder
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
     Counter OutCount;
+    Counter ExitCount;
     Counter LoopCount;
     if (llvm::EnableSingleByteCoverage)
       OutCount = getRegionCounter(S);
     else {
-      LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-      OutCount =
-          addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
+      LoopCount =
+          (ParentCount.isZero()
+               ? ParentCount
+               : addCounters(ParentCount, BackedgeCount, BC.ContinueCount));
+      auto [ExecCount, SkipCount] = getBranchCounterPair(S, LoopCount);
+      ExitCount = SkipCount;
+      assert(ExecCount.isZero() || ExecCount == BodyCount);
+      OutCount = addCounters(BC.BreakCount, ExitCount);
     }
-    if (OutCount != ParentCount) {
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
       if (BodyHasTerminateStmt)
@@ -1781,8 +1813,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(LoopCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, ExitCount);
   }
 
   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
@@ -1803,10 +1834,13 @@ struct CounterCoverageMappingBuilder
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
     Counter LoopCount =
-        addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-    Counter OutCount =
-        addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
-    if (OutCount != ParentCount) {
+        (ParentCount.isZero()
+             ? ParentCount
+             : addCounters(ParentCount, BackedgeCount, BC.ContinueCount));
+    auto [ExecCount, ExitCount] = getBranchCounterPair(S, LoopCount);
+    assert(ExecCount.isZero() || ExecCount == BodyCount);
+    Counter OutCount = addCounters(BC.BreakCount, ExitCount);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
@@ -2016,9 +2050,12 @@ struct CounterCoverageMappingBuilder
     extendRegion(S->getCond());
 
     Counter ParentCount = getRegion().getCounter();
-    Counter ThenCount = llvm::EnableSingleByteCoverage
-                            ? getRegionCounter(S->getThen())
-                            : getRegionCounter(S);
+    auto [ThenCount, ElseCount] =
+        (llvm::EnableSingleByteCoverage
+             ? std::make_pair(getRegionCounter(S->getThen()),
+                              (S->getElse() ? getRegionCounter(S->getElse())
+                                            : Counter::getZero()))
+             : getBranchCounterPair(S, ParentCount));
 
     // Emitting a counter for the condition makes it easier to interpret the
     // counter for the body when looking at the coverage.
@@ -2033,12 +2070,6 @@ struct CounterCoverageMappingBuilder
     extendRegion(S->getThen());
     Counter OutCount = propagateCounts(ThenCount, S->getThen());
 
-    Counter ElseCount;
-    if (!llvm::EnableSingleByteCoverage)
-      ElseCount = subtractCounters(ParentCount, ThenCount);
-    else if (S->getElse())
-      ElseCount = getRegionCounter(S->getElse());
-
     if (const Stmt *Else = S->getElse()) {
       bool ThenHasTerminateStmt = HasTerminateStmt;
       HasTerminateStmt = false;
@@ -2061,15 +2092,14 @@ struct CounterCoverageMappingBuilder
     if (llvm::EnableSingleByteCoverage)
       OutCount = getRegionCounter(S);
 
-    if (OutCount != ParentCount) {
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
 
     if (!S->isConsteval() && !llvm::EnableSingleByteCoverage)
       // Create Branch Region around condition.
-      createBranchRegion(S->getCond(), ThenCount,
-                         subtractCounters(ParentCount, ThenCount));
+      createBranchRegion(S->getCond(), ThenCount, ElseCount);
   }
 
   void VisitCXXTryStmt(const CXXTryStmt *S) {
@@ -2095,9 +2125,11 @@ struct CounterCoverageMappingBuilder
     extendRegion(E);
 
     Counter ParentCount = getRegion().getCounter();
-    Counter TrueCount = llvm::EnableSingleByteCoverage
-                            ? getRegionCounter(E->getTrueExpr())
-                            : getRegionCounter(E);
+    auto [TrueCount, FalseCount] =
+        (llvm::EnableSingleByteCoverage
+             ? std::make_pair(getRegionCounter(E->getTrueExpr()),
+                              getRegionCounter(E->getFalseExpr()))
+             : getBranchCounterPair(E, ParentCount));
     Counter OutCount;
 
     if (const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
@@ -2116,25 +2148,20 @@ struct CounterCoverageMappingBuilder
     }
 
     extendRegion(E->getFalseExpr());
-    Counter FalseCount = llvm::EnableSingleByteCoverage
-                             ? getRegionCounter(E->getFalseExpr())
-                             : subtractCounters(ParentCount, TrueCount);
-
     Counter FalseOutCount = propagateCounts(FalseCount, E->getFalseExpr());
     if (llvm::EnableSingleByteCoverage)
       OutCount = getRegionCounter(E);
     else
       OutCount = addCounters(OutCount, FalseOutCount);
 
-    if (OutCount != ParentCount) {
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getCond(), TrueCount,
-                         subtractCounters(ParentCount, TrueCount));
+      createBranchRegion(E->getCond(), TrueCount, FalseCount);
   }
 
   void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
@@ -2233,27 +2260,27 @@ struct CounterCoverageMappingBuilder
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
 
+    if (llvm::EnableSingleByteCoverage)
+      return;
+
     // Track RHS True/False Decision.
     const auto DecisionRHS = MCDCBuilder.back();
 
+    // Extract the Parent Region Counter.
+    Counter ParentCnt = getRegion().getCounter();
+
     // Extract the RHS's Execution Counter.
-    Counter RHSExecCnt = getRegionCounter(E);
+    auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);
 
     // Extract the RHS's "True" Instance Counter.
-    Counter RHSTrueCnt = getRegionCounter(E->getRHS());
-
-    // Extract the Parent Region Counter.
-    Counter ParentCnt = getRegion().getCounter();
+    auto [RHSTrueCnt, RHSExitCnt] =
+        getBranchCounterPair(E->getRHS(), RHSExecCnt);
 
     // Create Branch Region around LHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getLHS(), RHSExecCnt,
-                         subtractCounters(ParentCnt, RHSExecCnt), DecisionLHS);
+    createBranchRegion(E->getLHS(), RHSExecCnt, LHSExitCnt, DecisionLHS);
 
     // Create Branch Region around RHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getRHS(), RHSTrueCnt,
-                         subtractCounters(RHSExecCnt, RHSTrueCnt), DecisionRHS);
+    createBranchRegion(E->getRHS(), RHSTrueCnt, RHSExitCnt, DecisionRHS);
 
     // Create MCDC Decision Region if at top-level (root).
     if (IsRootNode)
@@ -2294,31 +2321,31 @@ struct CounterCoverageMappingBuilder
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
 
+    if (llvm::EnableSingleByteCoverage)
+      return;
+
     // Track RHS True/False Decision.
     const auto DecisionRHS = MCDCBuilder.back();
 
+    // Extract the Parent Region Counter.
+    Counter ParentCnt = getRegion().getCounter();
+
     // Extract the RHS's Execution Counter.
-    Counter RHSExecCnt = getRegionCounter(E);
+    auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);
 
     // Extract the RHS's "False" Instance Counter.
-    Counter RHSFalseCnt = getRegionCounter(E->getRHS());
+    auto [RHSFalseCnt, RHSExitCnt] =
+        getBranchCounterPair(E->getRHS(), RHSExecCnt);
 
     if (!shouldVisitRHS(E->getLHS())) {
       GapRegionCounter = OutCount;
     }
 
-    // Extract the Parent Region Counter.
-    Counter ParentCnt = getRegion().getCounter();
-
     // Create Branch Region around LHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
-                         RHSExecCnt, DecisionLHS);
+    createBranchRegion(E->getLHS(), LHSExitCnt, RHSExecCnt, DecisionLHS);
 
     // Create Branch Region around RHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
-                         RHSFalseCnt, DecisionRHS);
+    createBranchRegion(E->getRHS(), RHSExitCnt, RHSFalseCnt, DecisionRHS);
 
     // Create MCDC Decision Region if at top-level (root).
     if (IsRootNode)

>From e4172ca273a6fdfcbfc4662c9e37276ef34c2df4 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 17 Oct 2024 00:32:26 +0900
Subject: [PATCH 03/36] Introduce the type `CounterPair` for RegionCounterMap

`CounterPair` can hold `<uint32_t, uint32_t>` instead of current
`unsigned`, to hold also the counter number of SkipPath. For now, this
change provides the skeleton and only `CounterPair::first` is used.

Each counter number can have `None` to suppress emitting counter
increment. `second` is initialized as `None` by default, since most
`Stmt*` don't have a pair of counters.

This change also provides stubs for the verifyer. I'll provide the
impl of verifier for `+Asserts` later.

`markStmtAsUsed(bool, Stmt*)` may be used to inform that other side
counter may not emitted.

`markStmtMaybeUsed(S)` may be used for the `Stmt` and its inner will
be excluded for emission in the case of skipping by constant
folding. I put it into places where I found.

`verifyCounterMap()` will check the coverage map the counter map and
can be used to report inconsistency.

These verifier methods shall be eliminated in `-Asserts`.

https://discourse.llvm.org/t/rfc-integrating-singlebytecoverage-with-branch-coverage/82492
---
 clang/lib/CodeGen/CGDecl.cpp             |  9 ++++++++-
 clang/lib/CodeGen/CGExpr.cpp             |  1 +
 clang/lib/CodeGen/CGExprScalar.cpp       |  9 +++++++--
 clang/lib/CodeGen/CGStmt.cpp             |  3 +++
 clang/lib/CodeGen/CodeGenFunction.cpp    |  3 +++
 clang/lib/CodeGen/CodeGenFunction.h      |  6 ++++++
 clang/lib/CodeGen/CodeGenModule.h        | 19 +++++++++++++++++++
 clang/lib/CodeGen/CodeGenPGO.cpp         | 14 ++++++++++----
 clang/lib/CodeGen/CodeGenPGO.h           | 17 +++++++++++++++--
 clang/lib/CodeGen/CoverageMappingGen.cpp |  6 +++---
 clang/lib/CodeGen/CoverageMappingGen.h   |  5 +++--
 11 files changed, 78 insertions(+), 14 deletions(-)

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 563f728e29d78..ed5f41b624b62 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -362,6 +362,8 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
     return GV;
   }
 
+  PGO.markStmtMaybeUsed(D.getInit()); // FIXME: Too lazy
+
 #ifndef NDEBUG
   CharUnits VarSize = CGM.getContext().getTypeSizeInChars(D.getType()) +
                       D.getFlexibleArrayInitChars(getContext());
@@ -1869,7 +1871,10 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
   // If we are at an unreachable point, we don't need to emit the initializer
   // unless it contains a label.
   if (!HaveInsertPoint()) {
-    if (!Init || !ContainsLabel(Init)) return;
+    if (!Init || !ContainsLabel(Init)) {
+      PGO.markStmtMaybeUsed(Init);
+      return;
+    }
     EnsureInsertPoint();
   }
 
@@ -1978,6 +1983,8 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
     return EmitExprAsInit(Init, &D, lv, capturedByInit);
   }
 
+  PGO.markStmtMaybeUsed(Init);
+
   if (!emission.IsConstantAggregate) {
     // For simple scalar/complex initialization, store the value directly.
     LValue lv = MakeAddrLValue(Loc, type);
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 52d2f6d52abf9..2fd6b02a3395e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5134,6 +5134,7 @@ std::optional<LValue> HandleConditionalOperatorLValueSimpleCase(
       // If the true case is live, we need to track its region.
       if (CondExprBool)
         CGF.incrementProfileCounter(E);
+      CGF.markStmtMaybeUsed(Dead);
       // If a throw expression we emit it and return an undefined lvalue
       // because it can't be used.
       if (auto *ThrowExpr = dyn_cast<CXXThrowExpr>(Live->IgnoreParens())) {
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index b7f5b932c56b6..74e93f889f426 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4982,8 +4982,10 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
     }
 
     // 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
-    if (!CGF.ContainsLabel(E->getRHS()))
+    if (!CGF.ContainsLabel(E->getRHS())) {
+      CGF.markStmtMaybeUsed(E->getRHS());
       return llvm::Constant::getNullValue(ResTy);
+    }
   }
 
   // If the top of the logical operator nest, reset the MCDC temp to 0.
@@ -5122,8 +5124,10 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
     }
 
     // 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
-    if (!CGF.ContainsLabel(E->getRHS()))
+    if (!CGF.ContainsLabel(E->getRHS())) {
+      CGF.markStmtMaybeUsed(E->getRHS());
       return llvm::ConstantInt::get(ResTy, 1);
+    }
   }
 
   // If the top of the logical operator nest, reset the MCDC temp to 0.
@@ -5247,6 +5251,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
         CGF.incrementProfileCounter(E);
       }
       Value *Result = Visit(live);
+      CGF.markStmtMaybeUsed(dead);
 
       // If the live part is a throw expression, it acts like it has a void
       // type, so evaluating it returns a null Value*.  However, a conditional
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 41dc91c578c80..dbc1ce9bf993c 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -76,6 +76,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
       // Verify that any decl statements were handled as simple, they may be in
       // scope of subsequent reachable statements.
       assert(!isa<DeclStmt>(*S) && "Unexpected DeclStmt!");
+      PGO.markStmtMaybeUsed(S);
       return;
     }
 
@@ -845,6 +846,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
         RunCleanupsScope ExecutedScope(*this);
         EmitStmt(Executed);
       }
+      PGO.markStmtMaybeUsed(Skipped);
       return;
     }
   }
@@ -2170,6 +2172,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
       for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
         EmitStmt(CaseStmts[i]);
       incrementProfileCounter(&S);
+      PGO.markStmtMaybeUsed(S.getBody());
 
       // Now we want to restore the saved switch instance so that nested
       // switches continue to function properly
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 24723e392c2a3..371aa494e014b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1606,6 +1606,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
   // Emit the standard function epilogue.
   FinishFunction(BodyRange.getEnd());
 
+  PGO.verifyCounterMap();
+
   // If we haven't marked the function nothrow through other means, do
   // a quick pass now to see if we can.
   if (!CurFn->doesNotThrow())
@@ -1728,6 +1730,7 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
   if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
     return false;  // Contains a label.
 
+  PGO.markStmtMaybeUsed(Cond);
   ResultInt = Int;
   return true;
 }
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 9ba0ed02a564d..89ac3b342d0a7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1620,6 +1620,12 @@ class CodeGenFunction : public CodeGenTypeCache {
                                             uint64_t LoopCount) const;
 
 public:
+  std::pair<bool, bool> getIsCounterPair(const Stmt *S) const {
+    return PGO.getIsCounterPair(S);
+  }
+
+  void markStmtMaybeUsed(const Stmt *S) { PGO.markStmtMaybeUsed(S); }
+
   /// Increment the profiler's counter for the given statement by \p StepV.
   /// If \p StepV is null, the default increment is 1.
   void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index c58bb88035ca8..9dc497321b42a 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -101,6 +101,25 @@ enum ForDefinition_t : bool {
   ForDefinition = true
 };
 
+class CounterPair : public std::pair<uint32_t, uint32_t> {
+private:
+  static constexpr uint32_t None = (1u << 31); /// None is set
+
+public:
+  static constexpr uint32_t Mask = None - 1;
+
+public:
+  CounterPair(unsigned Val = 0) {
+    assert(!(Val & ~Mask));
+    first = Val;
+    second = None;
+  }
+
+  std::pair<bool, bool> getIsCounterPair() const {
+    return {!(first & None), !(second & None)};
+  }
+};
+
 struct OrderGlobalInitsOrStermFinalizers {
   unsigned int priority;
   unsigned int lex_order;
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 820bb521ccf85..069469e3de856 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -164,7 +164,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
   /// The function hash.
   PGOHash Hash;
   /// The map of statements to counters.
-  llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
+  llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
   /// The state of MC/DC Coverage in this function.
   MCDC::State &MCDCState;
   /// Maximum number of supported MC/DC conditions in a boolean expression.
@@ -175,7 +175,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
   DiagnosticsEngine &Diag;
 
   MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion,
-                    llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
+                    llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
                     MCDC::State &MCDCState, unsigned MCDCMaxCond,
                     DiagnosticsEngine &Diag)
       : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
@@ -1084,7 +1084,7 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
       (CGM.getCodeGenOpts().MCDCCoverage ? CGM.getCodeGenOpts().MCDCMaxConds
                                          : 0);
 
-  RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
+  RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, CounterPair>);
   RegionMCDCState.reset(new MCDC::State);
   MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
                            *RegionMCDCState, MCDCMaxConditions, CGM.getDiags());
@@ -1186,12 +1186,18 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
   Fn->setEntryCount(FunctionCount);
 }
 
+std::pair<bool, bool> CodeGenPGO::getIsCounterPair(const Stmt *S) const {
+  if (!RegionCounterMap || RegionCounterMap->count(S) == 0)
+    return {false, false};
+  return (*RegionCounterMap)[S].getIsCounterPair();
+}
+
 void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
                                            llvm::Value *StepV) {
   if (!RegionCounterMap || !Builder.GetInsertBlock())
     return;
 
-  unsigned Counter = (*RegionCounterMap)[S];
+  unsigned Counter = (*RegionCounterMap)[S].first;
 
   // Make sure that pointer to global is passed in with zero addrspace
   // This is relevant during GPU profiling
diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 9d66ffad6f435..83f35785e5327 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -35,7 +35,7 @@ class CodeGenPGO {
   std::array <unsigned, llvm::IPVK_Last + 1> NumValueSites;
   unsigned NumRegionCounters;
   uint64_t FunctionHash;
-  std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap;
+  std::unique_ptr<llvm::DenseMap<const Stmt *, CounterPair>> RegionCounterMap;
   std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap;
   std::unique_ptr<llvm::InstrProfRecord> ProfRecord;
   std::unique_ptr<MCDC::State> RegionMCDCState;
@@ -110,6 +110,7 @@ class CodeGenPGO {
   bool canEmitMCDCCoverage(const CGBuilderTy &Builder);
 
 public:
+  std::pair<bool, bool> getIsCounterPair(const Stmt *S) const;
   void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
                                  llvm::Value *StepV);
   void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
@@ -122,6 +123,18 @@ class CodeGenPGO {
                                 Address MCDCCondBitmapAddr, llvm::Value *Val,
                                 CodeGenFunction &CGF);
 
+  void markStmtAsUsed(bool Skipped, const Stmt *S) {
+    // Do nothing.
+  }
+
+  void markStmtMaybeUsed(const Stmt *S) {
+    // Do nothing.
+  }
+
+  void verifyCounterMap() {
+    // Do nothing.
+  }
+
   /// Return the region count for the counter at the given index.
   uint64_t getRegionCount(const Stmt *S) {
     if (!RegionCounterMap)
@@ -130,7 +143,7 @@ class CodeGenPGO {
       return 0;
     // With profiles from a differing version of clang we can have mismatched
     // decl counts. Don't crash in such a case.
-    auto Index = (*RegionCounterMap)[S];
+    auto Index = (*RegionCounterMap)[S].first;
     if (Index >= RegionCounts.size())
       return 0;
     return RegionCounts[Index];
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 07015834bc84f..08e4ac80e0e87 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -885,7 +885,7 @@ struct CounterCoverageMappingBuilder
     : public CoverageMappingBuilder,
       public ConstStmtVisitor<CounterCoverageMappingBuilder> {
   /// The map of statements to count values.
-  llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
+  llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
 
   MCDC::State &MCDCState;
 
@@ -938,7 +938,7 @@ struct CounterCoverageMappingBuilder
   ///
   /// This should only be called on statements that have a dedicated counter.
   Counter getRegionCounter(const Stmt *S) {
-    return Counter::getCounter(CounterMap[S]);
+    return Counter::getCounter(CounterMap[S].first);
   }
 
   /// Push a region onto the stack.
@@ -1421,7 +1421,7 @@ struct CounterCoverageMappingBuilder
 
   CounterCoverageMappingBuilder(
       CoverageMappingModuleGen &CVM,
-      llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
+      llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
       MCDC::State &MCDCState, SourceManager &SM, const LangOptions &LangOpts)
       : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
         MCDCState(MCDCState), MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {}
diff --git a/clang/lib/CodeGen/CoverageMappingGen.h b/clang/lib/CodeGen/CoverageMappingGen.h
index fe4b93f3af856..0ed50597e1dc3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.h
+++ b/clang/lib/CodeGen/CoverageMappingGen.h
@@ -95,6 +95,7 @@ class CoverageSourceInfo : public PPCallbacks,
 namespace CodeGen {
 
 class CodeGenModule;
+class CounterPair;
 
 namespace MCDC {
 struct State;
@@ -158,7 +159,7 @@ class CoverageMappingGen {
   CoverageMappingModuleGen &CVM;
   SourceManager &SM;
   const LangOptions &LangOpts;
-  llvm::DenseMap<const Stmt *, unsigned> *CounterMap;
+  llvm::DenseMap<const Stmt *, CounterPair> *CounterMap;
   MCDC::State *MCDCState;
 
 public:
@@ -169,7 +170,7 @@ class CoverageMappingGen {
 
   CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
                      const LangOptions &LangOpts,
-                     llvm::DenseMap<const Stmt *, unsigned> *CounterMap,
+                     llvm::DenseMap<const Stmt *, CounterPair> *CounterMap,
                      MCDC::State *MCDCState)
       : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap),
         MCDCState(MCDCState) {}

>From 5e460594c8a2550c38c759b2e6f1c5dc4152f820 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 17 Oct 2024 22:15:12 +0900
Subject: [PATCH 04/36] [Coverage] Make additional counters available for
 BranchRegion. NFC.

`getBranchCounterPair()` allocates an additional Counter to SkipPath
in `SingleByteCoverage`.

`IsCounterEqual()` calculates the comparison with rewinding counter
replacements.

`NumRegionCounters` is updated to take additional counters in account.

`incrementProfileCounter()` has a few additiona arguments.

- `UseSkipPath=true`, to specify setting counters for SkipPath. It
  assumes `UseSkipPath=false` is used together.

- `UseBoth` may be specified for marking another path. It introduces
  the same effect as issueing `markStmtAsUsed(!SkipPath, S)`.

`llvm-cov` discovers counters in `FalseCount` to allocate
`MaxCounterID` for empty profile data.
---
 clang/lib/CodeGen/CodeGenFunction.h           |  8 ++++-
 clang/lib/CodeGen/CodeGenPGO.cpp              | 31 +++++++++++++++++--
 clang/lib/CodeGen/CodeGenPGO.h                |  1 +
 clang/lib/CodeGen/CoverageMappingGen.cpp      | 31 ++++++++++++++-----
 .../ProfileData/Coverage/CoverageMapping.cpp  |  4 +++
 5 files changed, 65 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 89ac3b342d0a7..cb1192bf6e11f 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1629,11 +1629,17 @@ class CodeGenFunction : public CodeGenTypeCache {
   /// Increment the profiler's counter for the given statement by \p StepV.
   /// If \p StepV is null, the default increment is 1.
   void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) {
+    incrementProfileCounter(false, S, false, StepV);
+  }
+
+  void incrementProfileCounter(bool UseSkipPath, const Stmt *S,
+                               bool UseBoth = false,
+                               llvm::Value *StepV = nullptr) {
     if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
         !CurFn->hasFnAttribute(llvm::Attribute::NoProfile) &&
         !CurFn->hasFnAttribute(llvm::Attribute::SkipProfile)) {
       auto AL = ApplyDebugLocation::CreateArtificial(*this);
-      PGO.emitCounterSetOrIncrement(Builder, S, StepV);
+      PGO.emitCounterSetOrIncrement(Builder, S, UseSkipPath, UseBoth, StepV);
     }
     PGO.setCurrentStmt(S);
   }
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 069469e3de856..aefd53e12088b 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1138,6 +1138,19 @@ void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
   if (CoverageMapping.empty())
     return;
 
+  // Scan max(FalseCnt) and update NumRegionCounters.
+  unsigned MaxNumCounters = NumRegionCounters;
+  for (const auto [_, V] : *RegionCounterMap) {
+    auto HasCounters = V.getIsCounterPair();
+    assert((!HasCounters.first ||
+            MaxNumCounters > (V.first & CounterPair::Mask)) &&
+           "TrueCnt should not be reassigned");
+    if (HasCounters.second)
+      MaxNumCounters =
+          std::max(MaxNumCounters, (V.second & CounterPair::Mask) + 1);
+  }
+  NumRegionCounters = MaxNumCounters;
+
   CGM.getCoverageMapping()->addFunctionMappingRecord(
       FuncNameVar, FuncName, FunctionHash, CoverageMapping);
 }
@@ -1193,11 +1206,25 @@ std::pair<bool, bool> CodeGenPGO::getIsCounterPair(const Stmt *S) const {
 }
 
 void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
+                                           bool UseSkipPath, bool UseBoth,
                                            llvm::Value *StepV) {
-  if (!RegionCounterMap || !Builder.GetInsertBlock())
+  if (!RegionCounterMap)
     return;
 
-  unsigned Counter = (*RegionCounterMap)[S].first;
+  unsigned Counter;
+  auto &TheMap = (*RegionCounterMap)[S];
+  auto IsCounter = TheMap.getIsCounterPair();
+  if (!UseSkipPath) {
+    assert(IsCounter.first);
+    Counter = (TheMap.first & CounterPair::Mask);
+  } else {
+    if (!IsCounter.second)
+      return;
+    Counter = (TheMap.second & CounterPair::Mask);
+  }
+
+  if (!Builder.GetInsertBlock())
+    return;
 
   // Make sure that pointer to global is passed in with zero addrspace
   // This is relevant during GPU profiling
diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 83f35785e5327..8b769dd88d7f1 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -112,6 +112,7 @@ class CodeGenPGO {
 public:
   std::pair<bool, bool> getIsCounterPair(const Stmt *S) const;
   void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
+                                 bool UseFalsePath, bool UseBoth,
                                  llvm::Value *StepV);
   void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
                                       Address MCDCCondBitmapAddr,
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index a5d83e7a743bb..0bcbd20593ae2 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -887,6 +887,9 @@ struct CounterCoverageMappingBuilder
   /// The map of statements to count values.
   llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
 
+  CounterExpressionBuilder::ReplaceMap MapToExpand;
+  unsigned NextCounterNum;
+
   MCDC::State &MCDCState;
 
   /// A stack of currently live regions.
@@ -922,15 +925,11 @@ struct CounterCoverageMappingBuilder
 
   /// Return a counter for the sum of \c LHS and \c RHS.
   Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
-    assert(!llvm::EnableSingleByteCoverage &&
-           "cannot add counters when single byte coverage mode is enabled");
     return Builder.add(LHS, RHS, Simplify);
   }
 
   Counter addCounters(Counter C1, Counter C2, Counter C3,
                       bool Simplify = true) {
-    assert(!llvm::EnableSingleByteCoverage &&
-           "cannot add counters when single byte coverage mode is enabled");
     return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
   }
 
@@ -943,14 +942,31 @@ struct CounterCoverageMappingBuilder
 
   std::pair<Counter, Counter> getBranchCounterPair(const Stmt *S,
                                                    Counter ParentCnt) {
-    Counter ExecCnt = getRegionCounter(S);
-    return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
+    auto &TheMap = CounterMap[S];
+    auto ExecCnt = Counter::getCounter(TheMap.first);
+    auto SkipExpr = Builder.subtract(ParentCnt, ExecCnt);
+
+    if (!llvm::EnableSingleByteCoverage)
+      return {ExecCnt, SkipExpr};
+
+    // Assign second if second is not assigned yet.
+    if (!TheMap.getIsCounterPair().second)
+      TheMap.second = NextCounterNum++;
+
+    Counter SkipCnt = Counter::getCounter(TheMap.second);
+    MapToExpand[SkipCnt] = SkipExpr;
+    return {ExecCnt, SkipCnt};
   }
 
   bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
     if (OutCount == ParentCount)
       return true;
 
+    // Try comaparison with pre-replaced expressions.
+    if (Builder.replace(Builder.subtract(OutCount, ParentCount), MapToExpand)
+            .isZero())
+      return true;
+
     return false;
   }
 
@@ -1437,7 +1453,8 @@ struct CounterCoverageMappingBuilder
       llvm::DenseMap<const Stmt *, CounterPair> &CounterMap,
       MCDC::State &MCDCState, SourceManager &SM, const LangOptions &LangOpts)
       : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
-        MCDCState(MCDCState), MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {}
+        NextCounterNum(CounterMap.size()), MCDCState(MCDCState),
+        MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {}
 
   /// Write the mapping data to the output stream
   void write(llvm::raw_ostream &OS) {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index b50f025d261e1..fc7f36c8599f5 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -640,6 +640,10 @@ static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
   unsigned MaxCounterID = 0;
   for (const auto &Region : Record.MappingRegions) {
     MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count));
+    if (Region.Kind == CounterMappingRegion::BranchRegion ||
+        Region.Kind == CounterMappingRegion::MCDCBranchRegion)
+      MaxCounterID =
+          std::max(MaxCounterID, Ctx.getMaxCounterID(Region.FalseCount));
   }
   return MaxCounterID;
 }

>From ad136910aad1c8e53a8c6091999ad2f90d180761 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 18 Oct 2024 09:37:18 +0900
Subject: [PATCH 05/36] Rewind changes for folding

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 0bfad9cbcbe12..8bd9ab402f4e5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1795,10 +1795,7 @@ struct CounterCoverageMappingBuilder
     if (llvm::EnableSingleByteCoverage)
       OutCount = getRegionCounter(S);
     else {
-      LoopCount =
-          (ParentCount.isZero()
-               ? ParentCount
-               : addCounters(ParentCount, BackedgeCount, BC.ContinueCount));
+      LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
       auto [ExecCount, SkipCount] = getBranchCounterPair(S, LoopCount);
       ExitCount = SkipCount;
       assert(ExecCount.isZero() || ExecCount == BodyCount);
@@ -1834,9 +1831,7 @@ struct CounterCoverageMappingBuilder
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
     Counter LoopCount =
-        (ParentCount.isZero()
-             ? ParentCount
-             : addCounters(ParentCount, BackedgeCount, BC.ContinueCount));
+        addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
     auto [ExecCount, ExitCount] = getBranchCounterPair(S, LoopCount);
     assert(ExecCount.isZero() || ExecCount == BodyCount);
     Counter OutCount = addCounters(BC.BreakCount, ExitCount);

>From 209ea4cfdb4f93d3c8fc60dc9af29af39fd24758 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 20 Oct 2024 11:58:16 +0900
Subject: [PATCH 06/36] Update comments

---
 llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index b50f025d261e1..6f44797be20e3 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -138,14 +138,14 @@ Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS,
 Counter CounterExpressionBuilder::replace(Counter C, const ReplaceMap &Map) {
   auto I = Map.find(C);
 
-  // Replace C with the Map even if C is Expression.
+  // Replace C with the value found in Map even if C is Expression.
   if (I != Map.end())
     return I->second;
 
-  // Traverse only Expression.
   if (!C.isExpression())
     return C;
 
+  // Traverse both sides of Expression.
   auto CE = Expressions[C.getExpressionID()];
   auto NewLHS = replace(CE.LHS, Map);
   auto NewRHS = replace(CE.RHS, Map);

>From f0afd04dd86573f1e7d868cc6e1c677d1779aa5f Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 20 Oct 2024 12:00:23 +0900
Subject: [PATCH 07/36] Use initializer statements

---
 llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 6f44797be20e3..7ff2e5ba69e19 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -136,10 +136,8 @@ Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS,
 }
 
 Counter CounterExpressionBuilder::replace(Counter C, const ReplaceMap &Map) {
-  auto I = Map.find(C);
-
   // Replace C with the value found in Map even if C is Expression.
-  if (I != Map.end())
+  if (auto I = Map.find(C); I != Map.end())
     return I->second;
 
   if (!C.isExpression())
@@ -161,7 +159,7 @@ Counter CounterExpressionBuilder::replace(Counter C, const ReplaceMap &Map) {
   }
 
   // Reconfirm if the reconstructed expression would hit the Map.
-  if ((I = Map.find(C)) != Map.end())
+  if (auto I = Map.find(C); I != Map.end())
     return I->second;
 
   return C;

>From be516faa39e1152d637ac425229f8a88480ba41b Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 20 Oct 2024 11:57:03 +0900
Subject: [PATCH 08/36] `first` may be cancelled.

Currently `first` is not None by default.
---
 clang/lib/CodeGen/CodeGenPGO.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index aefd53e12088b..0f2090da47a37 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1215,7 +1215,8 @@ void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
   auto &TheMap = (*RegionCounterMap)[S];
   auto IsCounter = TheMap.getIsCounterPair();
   if (!UseSkipPath) {
-    assert(IsCounter.first);
+    if (!IsCounter.first)
+      return;
     Counter = (TheMap.first & CounterPair::Mask);
   } else {
     if (!IsCounter.second)

>From 03cfce188cb45adbe78f7e77c2fdd244650f5a3c Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 23 Oct 2024 14:39:35 +0000
Subject: [PATCH 09/36] CGF::markStmtAsUsed

---
 clang/lib/CodeGen/CodeGenFunction.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 89ac3b342d0a7..fcad1cbcae5e3 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1624,6 +1624,9 @@ class CodeGenFunction : public CodeGenTypeCache {
     return PGO.getIsCounterPair(S);
   }
 
+  void markStmtAsUsed(bool Skipped, const Stmt *S) {
+    PGO.markStmtAsUsed(Skipped, S);
+  }
   void markStmtMaybeUsed(const Stmt *S) { PGO.markStmtMaybeUsed(S); }
 
   /// Increment the profiler's counter for the given statement by \p StepV.

>From afc8481f7cf20da7de4e95a60bf3ccdb04bd08f3 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 23 Oct 2024 14:39:35 +0000
Subject: [PATCH 10/36] CGF.markStmtMaybeUsed for binop

---
 clang/lib/CodeGen/CGExprScalar.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 74e93f889f426..9e8533ca90a5c 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4970,7 +4970,8 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
         CGF.incrementProfileCounter(E->getRHS());
         CGF.EmitBranch(FBlock);
         CGF.EmitBlock(FBlock);
-      }
+      } else
+        CGF.markStmtMaybeUsed(E->getRHS());
 
       CGF.MCDCLogOpStack.pop_back();
       // If the top of the logical operator nest, update the MCDC bitmap.
@@ -5112,7 +5113,8 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
         CGF.incrementProfileCounter(E->getRHS());
         CGF.EmitBranch(FBlock);
         CGF.EmitBlock(FBlock);
-      }
+      } else
+        CGF.markStmtMaybeUsed(E->getRHS());
 
       CGF.MCDCLogOpStack.pop_back();
       // If the top of the logical operator nest, update the MCDC bitmap.

>From ab84f17fc181cb4b38693dc6ea80ac44f44bf990 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 27 Oct 2024 20:28:26 +0900
Subject: [PATCH 11/36] Introduce skeleton getSwitchImplicitDefaultCounter()

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 1782434bdb9aa..532f6e8ba1820 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -947,6 +947,11 @@ struct CounterCoverageMappingBuilder
     return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
   }
 
+  Counter getSwitchImplicitDefaultCounter(const Stmt *Cond, Counter ParentCount,
+                                          Counter CaseCountSum) {
+    return Builder.subtract(ParentCount, CaseCountSum);
+  }
+
   bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
     if (OutCount == ParentCount)
       return true;
@@ -1903,7 +1908,8 @@ struct CounterCoverageMappingBuilder
     // 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 DefaultCount = subtractCounters(ParentCount, CaseCountSum);
+      Counter DefaultCount = getSwitchImplicitDefaultCounter(
+          S->getCond(), ParentCount, CaseCountSum);
       createBranchRegion(S->getCond(), Counter::getZero(), DefaultCount);
     }
   }

>From a4608854e1b727817db3cc01234f97e78285f8c7 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 27 Oct 2024 20:40:44 +0900
Subject: [PATCH 12/36] Update getSwitchImplicitDefaultCounter

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index d4a1b2613eab9..cb861e61d3272 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -960,7 +960,10 @@ struct CounterCoverageMappingBuilder
 
   Counter getSwitchImplicitDefaultCounter(const Stmt *Cond, Counter ParentCount,
                                           Counter CaseCountSum) {
-    return Builder.subtract(ParentCount, CaseCountSum);
+    return (
+        llvm::EnableSingleByteCoverage
+            ? Counter::getCounter(CounterMap[Cond].second = NextCounterNum++)
+            : Builder.subtract(ParentCount, CaseCountSum));
   }
 
   bool IsCounterEqual(Counter OutCount, Counter ParentCount) {

>From 02853943407a5c550554e4920586b8724dd63a76 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 28 Oct 2024 00:55:49 +0900
Subject: [PATCH 13/36] Don't allocate second if SkipExpr isn't Expr.

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index cb861e61d3272..8584f58548eae 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -946,8 +946,12 @@ struct CounterCoverageMappingBuilder
     auto ExecCnt = Counter::getCounter(TheMap.first);
     auto SkipExpr = Builder.subtract(ParentCnt, ExecCnt);
 
-    if (!llvm::EnableSingleByteCoverage)
+    if (!llvm::EnableSingleByteCoverage || !SkipExpr.isExpression()) {
+      assert(
+          !TheMap.getIsCounterPair().second &&
+          "SkipCnt shouldn't be allocated but refer to an existing counter.");
       return {ExecCnt, SkipExpr};
+    }
 
     // Assign second if second is not assigned yet.
     if (!TheMap.getIsCounterPair().second)

>From ed700c2cb5b7ceac1bcf5ac0414a11d3148b9990 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 21 Dec 2024 17:49:06 +0900
Subject: [PATCH 14/36] s/replace/subst/

---
 llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h | 6 +++---
 llvm/lib/ProfileData/Coverage/CoverageMapping.cpp        | 7 +++----
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index a55ca997d47fd..dad5f1276f27c 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -215,10 +215,10 @@ class CounterExpressionBuilder {
   /// LHS.
   Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
 
-  using ReplaceMap = std::map<Counter, Counter>;
+  using SubstMap = std::map<Counter, Counter>;
 
-  /// Return a counter for each term in the expression replaced by ReplaceMap.
-  Counter replace(Counter C, const ReplaceMap &Map);
+  /// Return a counter for each term in the expression replaced by SubstMap.
+  Counter subst(Counter C, const SubstMap &Map);
 };
 
 using LineColPair = std::pair<unsigned, unsigned>;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 6d6f03c360639..3f89414bdbbb9 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -135,7 +135,7 @@ Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS,
   return Simplify ? simplify(Cnt) : Cnt;
 }
 
-Counter CounterExpressionBuilder::replace(Counter C, const ReplaceMap &Map) {
+Counter CounterExpressionBuilder::subst(Counter C, const SubstMap &Map) {
   // Replace C with the value found in Map even if C is Expression.
   if (auto I = Map.find(C); I != Map.end())
     return I->second;
@@ -143,10 +143,9 @@ Counter CounterExpressionBuilder::replace(Counter C, const ReplaceMap &Map) {
   if (!C.isExpression())
     return C;
 
-  // Traverse both sides of Expression.
   auto CE = Expressions[C.getExpressionID()];
-  auto NewLHS = replace(CE.LHS, Map);
-  auto NewRHS = replace(CE.RHS, Map);
+  auto NewLHS = subst(CE.LHS, Map);
+  auto NewRHS = subst(CE.RHS, Map);
 
   // Reconstruct Expression with induced subexpressions.
   switch (CE.Kind) {

>From dbcf896f38c4c950abd23bf5fe8b9dff75476fef Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 21 Dec 2024 18:06:25 +0900
Subject: [PATCH 15/36] getSwitchImplicitDefaultCounterPair

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 27 ++++++++++++------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index e63c38fcd4ba2..dff804fbeee92 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -944,12 +944,18 @@ struct CounterCoverageMappingBuilder
     return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
   }
 
-  Counter getSwitchImplicitDefaultCounter(const Stmt *Cond, Counter ParentCount,
-                                          Counter CaseCountSum) {
-    if (llvm::EnableSingleByteCoverage)
-      CaseCountSum = Counter::getZero();
+  /// Returns {TrueCnt,FalseCnt} for "implicit default".
+  /// FalseCnt is considered as the False count on SwitchStmt.
+  std::pair<Counter, Counter>
+  getSwitchImplicitDefaultCounterPair(const Stmt *Cond, Counter ParentCount,
+                                      Counter CaseCountSum) {
+    // 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(), /*Simplify=*/true);
 
-    return Builder.subtract(ParentCount, CaseCountSum);
+    return {CaseCountSum, Builder.subtract(ParentCount, CaseCountSum)};
   }
 
   bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
@@ -1910,16 +1916,9 @@ struct CounterCoverageMappingBuilder
     // the hidden branch, which will be added later by the CodeGen. This region
     // will be associated with the switch statement's condition.
     if (!HasDefaultCase) {
-      // 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(), /*Simplify=*/true);
-
-      // This is considered as the False count on SwitchStmt.
-      Counter SwitchFalse = getSwitchImplicitDefaultCounter(
+      auto Counters = getSwitchImplicitDefaultCounterPair(
           S->getCond(), ParentCount, CaseCountSum);
-      createBranchRegion(S->getCond(), CaseCountSum, SwitchFalse);
+      createBranchRegion(S->getCond(), Counters.first, Counters.second);
     }
   }
 

>From c0785e91103db81b53e000834ce748d8d448e5ef Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 21 Dec 2024 21:31:20 +0900
Subject: [PATCH 16/36] Fold either in switchcase

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 238235f72d731..c66280c98e80d 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -964,6 +964,10 @@ struct CounterCoverageMappingBuilder
   std::pair<Counter, Counter>
   getSwitchImplicitDefaultCounterPair(const Stmt *Cond, Counter ParentCount,
                                       Counter CaseCountSum) {
+    if (llvm::EnableSingleByteCoverage)
+      return {Counter::getZero(), // Folded
+              Counter::getCounter(CounterMap[Cond].second = NextCounterNum++)};
+
     // 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.
@@ -1195,12 +1199,14 @@ struct CounterCoverageMappingBuilder
   /// and add it to the function's SourceRegions.
   /// Returns Counter that corresponds to SC.
   Counter createSwitchCaseRegion(const SwitchCase *SC, Counter ParentCount) {
+    Counter TrueCnt = getRegionCounter(SC);
+    Counter FalseCnt = (llvm::EnableSingleByteCoverage
+                            ? Counter::getZero() // Folded
+                            : subtractCounters(ParentCount, 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.
-    Counter TrueCnt = getRegionCounter(SC);
-    popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(),
-                          subtractCounters(ParentCount, TrueCnt)));
+    popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
     return TrueCnt;
   }
 

>From bd1d96bb23b264f4976ce800470dd7ed7f74a709 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 23 Dec 2024 12:26:29 +0900
Subject: [PATCH 17/36] Introduce CounterMappingRegion::isBranch(). NFC.

Conflicts:
	clang/lib/CodeGen/CoverageMappingGen.cpp
	llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
---
 llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 63be03f231841..b2f4087465308 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -637,8 +637,7 @@ static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
   unsigned MaxCounterID = 0;
   for (const auto &Region : Record.MappingRegions) {
     MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count));
-    if (Region.Kind == CounterMappingRegion::BranchRegion ||
-        Region.Kind == CounterMappingRegion::MCDCBranchRegion)
+    if (Region.isBranch())
       MaxCounterID =
           std::max(MaxCounterID, Ctx.getMaxCounterID(Region.FalseCount));
   }

>From 4e41b99fdf41094a85bf473d27d57c527b91a0d8 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 24 Dec 2024 15:53:14 +0900
Subject: [PATCH 18/36] Introduce BranchCounterPair

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index dff804fbeee92..df29c2cb4ee17 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -938,8 +938,12 @@ struct CounterCoverageMappingBuilder
     return Counter::getCounter(CounterMap[S]);
   }
 
-  std::pair<Counter, Counter> getBranchCounterPair(const Stmt *S,
-                                                   Counter ParentCnt) {
+  struct BranchCounterPair {
+    Counter Executed;
+    Counter Skipped;
+  };
+
+  BranchCounterPair getBranchCounterPair(const Stmt *S, Counter ParentCnt) {
     Counter ExecCnt = getRegionCounter(S);
     return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
   }
@@ -1617,7 +1621,7 @@ struct CounterCoverageMappingBuilder
             : addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
     auto [ExecCount, ExitCount] =
         (llvm::EnableSingleByteCoverage
-             ? std::make_pair(getRegionCounter(S), Counter::getZero())
+             ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
              : getBranchCounterPair(S, CondCount));
     if (!llvm::EnableSingleByteCoverage) {
       assert(ExecCount.isZero() || ExecCount == BodyCount);
@@ -1674,7 +1678,7 @@ struct CounterCoverageMappingBuilder
                             : addCounters(BackedgeCount, BC.ContinueCount);
     auto [ExecCount, ExitCount] =
         (llvm::EnableSingleByteCoverage
-             ? std::make_pair(getRegionCounter(S), Counter::getZero())
+             ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
              : getBranchCounterPair(S, CondCount));
     if (!llvm::EnableSingleByteCoverage) {
       assert(ExecCount.isZero() || ExecCount == BodyCount);
@@ -1742,7 +1746,7 @@ struct CounterCoverageMappingBuilder
                   IncrementBC.ContinueCount);
     auto [ExecCount, ExitCount] =
         (llvm::EnableSingleByteCoverage
-             ? std::make_pair(getRegionCounter(S), Counter::getZero())
+             ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
              : getBranchCounterPair(S, CondCount));
     if (!llvm::EnableSingleByteCoverage) {
       assert(ExecCount.isZero() || ExecCount == BodyCount);
@@ -2049,9 +2053,9 @@ struct CounterCoverageMappingBuilder
     Counter ParentCount = getRegion().getCounter();
     auto [ThenCount, ElseCount] =
         (llvm::EnableSingleByteCoverage
-             ? std::make_pair(getRegionCounter(S->getThen()),
-                              (S->getElse() ? getRegionCounter(S->getElse())
-                                            : Counter::getZero()))
+             ? BranchCounterPair{getRegionCounter(S->getThen()),
+                                 (S->getElse() ? getRegionCounter(S->getElse())
+                                               : Counter::getZero())}
              : getBranchCounterPair(S, ParentCount));
 
     // Emitting a counter for the condition makes it easier to interpret the
@@ -2124,8 +2128,8 @@ struct CounterCoverageMappingBuilder
     Counter ParentCount = getRegion().getCounter();
     auto [TrueCount, FalseCount] =
         (llvm::EnableSingleByteCoverage
-             ? std::make_pair(getRegionCounter(E->getTrueExpr()),
-                              getRegionCounter(E->getFalseExpr()))
+             ? BranchCounterPair{getRegionCounter(E->getTrueExpr()),
+                                 getRegionCounter(E->getFalseExpr())}
              : getBranchCounterPair(E, ParentCount));
     Counter OutCount;
 

>From 306d77f3d9afdbb832f920e920008c719a3a3533 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 24 Dec 2024 15:58:13 +0900
Subject: [PATCH 19/36] void verifyCounterMap() const

---
 clang/lib/CodeGen/CodeGenPGO.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 83f35785e5327..9429b6b465207 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -131,7 +131,7 @@ class CodeGenPGO {
     // Do nothing.
   }
 
-  void verifyCounterMap() {
+  void verifyCounterMap() const {
     // Do nothing.
   }
 

>From a4f05c7a5ca60b8ed2eaf5337cdd04bab25e8170 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 24 Dec 2024 15:58:13 +0900
Subject: [PATCH 20/36] Introduce the dedicated class CounterPair instead of
 std::pair

---
 clang/lib/CodeGen/CodeGenFunction.h      |  4 +-
 clang/lib/CodeGen/CodeGenModule.h        | 53 +++++++++++++++++-------
 clang/lib/CodeGen/CodeGenPGO.cpp         | 11 +++--
 clang/lib/CodeGen/CodeGenPGO.h           |  2 +-
 clang/lib/CodeGen/CoverageMappingGen.cpp |  2 +-
 5 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 0396fa5bef136..87d016a0729ad 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1620,9 +1620,7 @@ class CodeGenFunction : public CodeGenTypeCache {
                                             uint64_t LoopCount) const;
 
 public:
-  std::pair<bool, bool> getIsCounterPair(const Stmt *S) const {
-    return PGO.getIsCounterPair(S);
-  }
+  auto getIsCounterPair(const Stmt *S) const { return PGO.getIsCounterPair(S); }
 
   void markStmtAsUsed(bool Skipped, const Stmt *S) {
     PGO.markStmtAsUsed(Skipped, S);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 8990ee13991e9..d5ef1a710eb40 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -102,23 +102,48 @@ enum ForDefinition_t : bool {
   ForDefinition = true
 };
 
-class CounterPair : public std::pair<uint32_t, uint32_t> {
-private:
-  static constexpr uint32_t None = (1u << 31); /// None is set
-
+/// The Counter with an optional additional Counter for
+/// branches. `Skipped` counter can be calculated with `Executed` and
+/// a common Counter (like `Parent`) as `(Parent-Executed)`.
+///
+/// In SingleByte mode, Counters are binary. Subtraction is not
+/// applicable (but addition is capable). In this case, both
+/// `Executed` and `Skipped` counters are required.  `Skipped` is
+/// `None` by default. It is allocated in the coverage mapping.
+///
+/// There might be cases that `Parent` could be induced with
+/// `(Executed+Skipped)`. This is not always applicable.
+class CounterPair {
 public:
-  static constexpr uint32_t Mask = None - 1;
+  /// Optional value.
+  class ValueOpt {
+  private:
+    static constexpr uint32_t None = (1u << 31); /// None is allocated.
+    static constexpr uint32_t Mask = None - 1;
 
-public:
-  CounterPair(unsigned Val = 0) {
-    assert(!(Val & ~Mask));
-    first = Val;
-    second = None;
-  }
+    uint32_t Val;
 
-  std::pair<bool, bool> getIsCounterPair() const {
-    return {!(first & None), !(second & None)};
-  }
+  public:
+    ValueOpt() : Val(None) {}
+
+    ValueOpt(unsigned InitVal) {
+      assert(!(InitVal & ~Mask));
+      Val = InitVal;
+    }
+
+    bool hasValue() const { return !(Val & None); }
+
+    operator uint32_t() const { return Val; }
+  };
+
+  ValueOpt Executed;
+  ValueOpt Skipped; /// May be None.
+
+  /// Initialized with Skipped=None.
+  CounterPair(unsigned Val) : Executed(Val) {}
+
+  // FIXME: Should work with {None, None}
+  CounterPair() : Executed(0) {}
 };
 
 struct OrderGlobalInitsOrStermFinalizers {
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 75191f86d231c..792373839107f 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1186,9 +1186,14 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
 }
 
 std::pair<bool, bool> CodeGenPGO::getIsCounterPair(const Stmt *S) const {
-  if (!RegionCounterMap || RegionCounterMap->count(S) == 0)
+  if (!RegionCounterMap)
     return {false, false};
-  return (*RegionCounterMap)[S].getIsCounterPair();
+
+  auto I = RegionCounterMap->find(S);
+  if (I == RegionCounterMap->end())
+    return {false, false};
+
+  return {I->second.Executed.hasValue(), I->second.Skipped.hasValue()};
 }
 
 void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
@@ -1196,7 +1201,7 @@ void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
   if (!RegionCounterMap || !Builder.GetInsertBlock())
     return;
 
-  unsigned Counter = (*RegionCounterMap)[S].first;
+  unsigned Counter = (*RegionCounterMap)[S].Executed;
 
   // Make sure that pointer to global is passed in with zero addrspace
   // This is relevant during GPU profiling
diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 9429b6b465207..1944b640951d5 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -143,7 +143,7 @@ class CodeGenPGO {
       return 0;
     // With profiles from a differing version of clang we can have mismatched
     // decl counts. Don't crash in such a case.
-    auto Index = (*RegionCounterMap)[S].first;
+    auto Index = (*RegionCounterMap)[S].Executed;
     if (Index >= RegionCounts.size())
       return 0;
     return RegionCounts[Index];
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 9c191e9394769..6433f930ae41e 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -935,7 +935,7 @@ struct CounterCoverageMappingBuilder
   ///
   /// This should only be called on statements that have a dedicated counter.
   Counter getRegionCounter(const Stmt *S) {
-    return Counter::getCounter(CounterMap[S].first);
+    return Counter::getCounter(CounterMap[S].Executed);
   }
 
   /// Push a region onto the stack.

>From f6c5f4017cc48534d2c3adc68a7c3d97ad45d156 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 24 Dec 2024 16:13:54 +0900
Subject: [PATCH 21/36] Catch up the merge

---
 clang/lib/CodeGen/CodeGenPGO.cpp         | 24 +++++++++++++++-------
 clang/lib/CodeGen/CoverageMappingGen.cpp | 26 +++++++++++++++++++++---
 2 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 03856795ca51a..ffb1df9ec2cc6 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1140,13 +1140,10 @@ void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
   // Scan max(FalseCnt) and update NumRegionCounters.
   unsigned MaxNumCounters = NumRegionCounters;
   for (const auto [_, V] : *RegionCounterMap) {
-    auto HasCounters = V.getIsCounterPair();
-    assert((!HasCounters.first ||
-            MaxNumCounters > (V.first & CounterPair::Mask)) &&
+    assert((!V.Executed.hasValue() || MaxNumCounters > V.Executed) &&
            "TrueCnt should not be reassigned");
-    if (HasCounters.second)
-      MaxNumCounters =
-          std::max(MaxNumCounters, (V.second & CounterPair::Mask) + 1);
+    if (V.Skipped.hasValue())
+      MaxNumCounters = std::max(MaxNumCounters, V.Skipped + 1);
   }
   NumRegionCounters = MaxNumCounters;
 
@@ -1215,7 +1212,20 @@ void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
   if (!RegionCounterMap)
     return;
 
-  unsigned Counter = (*RegionCounterMap)[S].Executed;
+  unsigned Counter;
+  auto &TheMap = (*RegionCounterMap)[S];
+  if (!UseSkipPath) {
+    if (!TheMap.Executed.hasValue())
+      return;
+    Counter = TheMap.Executed;
+  } else {
+    if (!TheMap.Skipped.hasValue())
+      return;
+    Counter = TheMap.Skipped;
+  }
+
+  if (!Builder.GetInsertBlock())
+    return;
 
   // Make sure that pointer to global is passed in with zero addrspace
   // This is relevant during GPU profiling
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index e0aa752bcbe9a..0764345af0b32 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -943,8 +943,27 @@ struct CounterCoverageMappingBuilder
   };
 
   BranchCounterPair getBranchCounterPair(const Stmt *S, Counter ParentCnt) {
-    Counter ExecCnt = getRegionCounter(S);
-    return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
+    auto &TheMap = CounterMap[S];
+    auto ExecCnt = Counter::getCounter(TheMap.Executed);
+    BranchCounterPair Counters = {ExecCnt,
+                                  Builder.subtract(ParentCnt, ExecCnt)};
+
+    if (!llvm::EnableSingleByteCoverage || !Counters.Skipped.isExpression()) {
+      assert(
+          !TheMap.Skipped.hasValue() &&
+          "SkipCnt shouldn't be allocated but refer to an existing counter.");
+      return Counters;
+    }
+
+    // Assign second if second is not assigned yet.
+    if (!TheMap.Skipped.hasValue())
+      TheMap.Skipped = NextCounterNum++;
+
+    // Replace an expression (ParentCnt - ExecCnt) with SkipCnt.
+    Counter SkipCnt = Counter::getCounter(TheMap.Skipped);
+    MapToExpand[SkipCnt] = Counters.Skipped;
+    Counters.Skipped = SkipCnt;
+    return Counters;
   }
 
   /// Returns {TrueCnt,FalseCnt} for "implicit default".
@@ -953,8 +972,9 @@ struct CounterCoverageMappingBuilder
   getSwitchImplicitDefaultCounterPair(const Stmt *Cond, Counter ParentCount,
                                       Counter CaseCountSum) {
     if (llvm::EnableSingleByteCoverage)
+      // Allocate the new Counter since `subtract(Parent - Sum)` is unavailable.
       return {Counter::getZero(), // Folded
-              Counter::getCounter(CounterMap[Cond].second = NextCounterNum++)};
+              Counter::getCounter(CounterMap[Cond].Skipped = NextCounterNum++)};
 
     // Simplify is skipped while building the counters above: it can get
     // really slow on top of switches with thousands of cases. Instead,

>From aca86d451ab886951a260c171c63c313522266d2 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 24 Dec 2024 16:13:54 +0900
Subject: [PATCH 22/36] Introduce {UseExecPath, UseSkipPath} instead of {false,
 true}

---
 clang/lib/CodeGen/CodeGenFunction.h | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 425fce241b983..6145c6a627fc8 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1627,20 +1627,31 @@ class CodeGenFunction : public CodeGenTypeCache {
   }
   void markStmtMaybeUsed(const Stmt *S) { PGO.markStmtMaybeUsed(S); }
 
+  enum CounterForIncrement {
+    UseExecPath = 0,
+    UseSkipPath,
+  };
+
   /// Increment the profiler's counter for the given statement by \p StepV.
   /// If \p StepV is null, the default increment is 1.
   void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) {
-    incrementProfileCounter(false, S, false, StepV);
+    incrementProfileCounter(UseExecPath, S, false, StepV);
   }
 
-  void incrementProfileCounter(bool UseSkipPath, const Stmt *S,
+  /// Emit increment of Counter.
+  /// \param ExecSkip Use `Skipped` Counter if UseSkipPath is specified.
+  /// \param S The Stmt that Counter is associated.
+  /// \param UseBoth Mark both Exec/Skip as used. (for verification)
+  /// \param StepV The offset Value for adding to Counter.
+  void incrementProfileCounter(CounterForIncrement ExecSkip, const Stmt *S,
                                bool UseBoth = false,
                                llvm::Value *StepV = nullptr) {
     if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
         !CurFn->hasFnAttribute(llvm::Attribute::NoProfile) &&
         !CurFn->hasFnAttribute(llvm::Attribute::SkipProfile)) {
       auto AL = ApplyDebugLocation::CreateArtificial(*this);
-      PGO.emitCounterSetOrIncrement(Builder, S, UseSkipPath, UseBoth, StepV);
+      PGO.emitCounterSetOrIncrement(Builder, S, (ExecSkip == UseSkipPath),
+                                    UseBoth, StepV);
     }
     PGO.setCurrentStmt(S);
   }

>From 28c568ad84edbfb4eb4bc7841c8c6b39e9722094 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 6 Jan 2025 23:37:50 +0900
Subject: [PATCH 23/36] Add a test

---
 .../ProfileData/CoverageMappingTest.cpp       | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index ef147674591c5..46f881ecddb5f 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -291,6 +291,45 @@ struct CoverageMappingTest : ::testing::TestWithParam<std::tuple<bool, bool>> {
   }
 };
 
+TEST(CoverageMappingTest, expression_subst) {
+  CounterExpressionBuilder Builder;
+  CounterExpressionBuilder::SubstMap MapToExpand;
+
+  auto C = [](unsigned ID) { return Counter::getCounter(ID); };
+  auto A = [&](Counter LHS, Counter RHS) { return Builder.add(LHS, RHS); };
+  // returns {E, N} in clangCodeGen
+  auto getBranchCounterPair = [&](Counter E, Counter P, Counter N) {
+    auto Skipped = Builder.subtract(P, E);
+    MapToExpand[N] = Builder.subst(Skipped, MapToExpand);
+  };
+
+  auto E18 = C(5);
+  auto P18 = C(2);
+  auto S18 = C(18);
+  // #18 => (#2 - #5)
+  getBranchCounterPair(E18, P18, S18);
+
+  auto E22 = S18;
+  auto P22 = C(0);
+  auto S22 = C(22);
+  // #22 => #0 - (#2 - #5)
+  getBranchCounterPair(E22, P22, S22);
+
+  auto E28 = A(A(C(9), C(11)), C(14));
+  auto P28 = S22;
+  auto S28 = C(28);
+  // #28 => (((((#0 + #5) - #2) - #9) - #11) - #14)
+  getBranchCounterPair(E28, P28, S28);
+
+  auto LHS = A(E28, A(S28, S18));
+  auto RHS = C(0);
+
+  // W/o subst, LHS cannot be reduced.
+  ASSERT_FALSE(Builder.subtract(LHS, RHS).isZero());
+  // W/ subst, C(18) and C(28) in LHS will be reduced.
+  ASSERT_TRUE(Builder.subst(Builder.subtract(LHS, RHS), MapToExpand).isZero());
+}
+
 TEST_P(CoverageMappingTest, basic_write_read) {
   startFunction("func", 0x1234);
   addCMR(Counter::getCounter(0), "foo", 1, 1, 1, 1);

>From d92a9d9c74814fc48c1ff5523d5215115021ac40 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 6 Jan 2025 23:38:11 +0900
Subject: [PATCH 24/36] Prune redundant logic

---
 llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 3f89414bdbbb9..87d305fc53636 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -157,10 +157,6 @@ Counter CounterExpressionBuilder::subst(Counter C, const SubstMap &Map) {
     break;
   }
 
-  // Reconfirm if the reconstructed expression would hit the Map.
-  if (auto I = Map.find(C); I != Map.end())
-    return I->second;
-
   return C;
 }
 

>From 82f2e92642fc00e0c07ed3c6506769319c39609a Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 7 Jan 2025 00:06:11 +0900
Subject: [PATCH 25/36] Expand RHS of MapToExpand. This will prevent recursion.

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 0764345af0b32..a00166881caaa 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -961,7 +961,7 @@ struct CounterCoverageMappingBuilder
 
     // Replace an expression (ParentCnt - ExecCnt) with SkipCnt.
     Counter SkipCnt = Counter::getCounter(TheMap.Skipped);
-    MapToExpand[SkipCnt] = Counters.Skipped;
+    MapToExpand[SkipCnt] = Builder.subst(Counters.Skipped, MapToExpand);
     Counters.Skipped = SkipCnt;
     return Counters;
   }

>From b90fdf61748ad0d585dc48987e5545878da98c59 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 7 Jan 2025 00:06:11 +0900
Subject: [PATCH 26/36] Append an explanation in the comment

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index a00166881caaa..bd495f84793f6 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -990,6 +990,14 @@ struct CounterCoverageMappingBuilder
       return true;
 
     // Try comaparison with pre-replaced expressions.
+    //
+    // For example, getBranchCounterPair(#0) returns {#1, #0 - #1}.
+    // The sum of the pair should be equivalent to the Parent, #0.
+    // OTOH when (#0 - #1) is replaced with the new counter #2,
+    // The sum is (#1 + #2). If the reverse substitution #2 => (#0 - #1)
+    // can be applied, the sum can be transformed to (#1 + (#0 - #1)).
+    // To apply substitutions to both hand expressions, transform (LHS - RHS)
+    // and check isZero.
     if (Builder.subst(Builder.subtract(OutCount, ParentCount), MapToExpand)
             .isZero())
       return true;

>From d854fb123be0449e83093f11e9f826c9baa3b766 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 8 Jan 2025 08:32:58 +0900
Subject: [PATCH 27/36] Rewind switch DefaultCase. (to #113112)

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 26 ++++++++----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index df29c2cb4ee17..d1968c5861c95 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -948,20 +948,6 @@ struct CounterCoverageMappingBuilder
     return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
   }
 
-  /// Returns {TrueCnt,FalseCnt} for "implicit default".
-  /// FalseCnt is considered as the False count on SwitchStmt.
-  std::pair<Counter, Counter>
-  getSwitchImplicitDefaultCounterPair(const Stmt *Cond, Counter ParentCount,
-                                      Counter CaseCountSum) {
-    // 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(), /*Simplify=*/true);
-
-    return {CaseCountSum, Builder.subtract(ParentCount, CaseCountSum)};
-  }
-
   bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
     if (OutCount == ParentCount)
       return true;
@@ -1920,9 +1906,15 @@ struct CounterCoverageMappingBuilder
     // the hidden branch, which will be added later by the CodeGen. This region
     // will be associated with the switch statement's condition.
     if (!HasDefaultCase) {
-      auto Counters = getSwitchImplicitDefaultCounterPair(
-          S->getCond(), ParentCount, CaseCountSum);
-      createBranchRegion(S->getCond(), Counters.first, Counters.second);
+      // 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(), /*Simplify=*/true);
+
+      // This is considered as the False count on SwitchStmt.
+      Counter SwitchFalse = subtractCounters(ParentCount, CaseCountSum);
+      createBranchRegion(S->getCond(), CaseCountSum, SwitchFalse);
     }
   }
 

>From bac29679dcc3d1e2f4b01270d8b1abb0858c549e Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 8 Jan 2025 08:42:38 +0900
Subject: [PATCH 28/36] Enable addCounters

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index d1968c5861c95..a973bcbb3f765 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -919,15 +919,11 @@ struct CounterCoverageMappingBuilder
 
   /// Return a counter for the sum of \c LHS and \c RHS.
   Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
-    assert(!llvm::EnableSingleByteCoverage &&
-           "cannot add counters when single byte coverage mode is enabled");
     return Builder.add(LHS, RHS, Simplify);
   }
 
   Counter addCounters(Counter C1, Counter C2, Counter C3,
                       bool Simplify = true) {
-    assert(!llvm::EnableSingleByteCoverage &&
-           "cannot add counters when single byte coverage mode is enabled");
     return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
   }
 

>From 6bae87d6193a88ab093ab472ff4a2d27f9e5e288 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 8 Jan 2025 09:05:46 +0900
Subject: [PATCH 29/36] Get rid of structual bindings

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 41 +++++++++++++-----------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index a973bcbb3f765..c03eb6a55af5e 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1601,12 +1601,13 @@ struct CounterCoverageMappingBuilder
         llvm::EnableSingleByteCoverage
             ? getRegionCounter(S->getCond())
             : addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-    auto [ExecCount, ExitCount] =
+    auto BranchCount =
         (llvm::EnableSingleByteCoverage
              ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
              : getBranchCounterPair(S, CondCount));
     if (!llvm::EnableSingleByteCoverage) {
-      assert(ExecCount.isZero() || ExecCount == BodyCount);
+      assert(BranchCount.Executed.isZero() ||
+             BranchCount.Executed == BodyCount);
     }
     propagateCounts(CondCount, S->getCond());
     adjustForOutOfOrderTraversal(getEnd(S));
@@ -1618,7 +1619,7 @@ struct CounterCoverageMappingBuilder
 
     Counter OutCount = llvm::EnableSingleByteCoverage
                            ? getRegionCounter(S)
-                           : addCounters(BC.BreakCount, ExitCount);
+                           : addCounters(BC.BreakCount, BranchCount.Skipped);
 
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
@@ -1629,7 +1630,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount, ExitCount);
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
   }
 
   void VisitDoStmt(const DoStmt *S) {
@@ -1658,18 +1659,19 @@ struct CounterCoverageMappingBuilder
     Counter CondCount = llvm::EnableSingleByteCoverage
                             ? getRegionCounter(S->getCond())
                             : addCounters(BackedgeCount, BC.ContinueCount);
-    auto [ExecCount, ExitCount] =
+    auto BranchCount =
         (llvm::EnableSingleByteCoverage
              ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
              : getBranchCounterPair(S, CondCount));
     if (!llvm::EnableSingleByteCoverage) {
-      assert(ExecCount.isZero() || ExecCount == BodyCount);
+      assert(BranchCount.Executed.isZero() ||
+             BranchCount.Executed == BodyCount);
     }
     propagateCounts(CondCount, S->getCond());
 
     Counter OutCount = llvm::EnableSingleByteCoverage
                            ? getRegionCounter(S)
-                           : addCounters(BC.BreakCount, ExitCount);
+                           : addCounters(BC.BreakCount, BranchCount.Skipped);
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
@@ -1677,7 +1679,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount, ExitCount);
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
 
     if (BodyHasTerminateStmt)
       HasTerminateStmt = true;
@@ -1726,12 +1728,13 @@ struct CounterCoverageMappingBuilder
             : addCounters(
                   addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
                   IncrementBC.ContinueCount);
-    auto [ExecCount, ExitCount] =
+    auto BranchCount =
         (llvm::EnableSingleByteCoverage
              ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
              : getBranchCounterPair(S, CondCount));
     if (!llvm::EnableSingleByteCoverage) {
-      assert(ExecCount.isZero() || ExecCount == BodyCount);
+      assert(BranchCount.Executed.isZero() ||
+             BranchCount.Executed == BodyCount);
     }
 
     if (const Expr *Cond = S->getCond()) {
@@ -1747,7 +1750,8 @@ struct CounterCoverageMappingBuilder
     Counter OutCount =
         llvm::EnableSingleByteCoverage
             ? getRegionCounter(S)
-            : addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, ExitCount);
+            : addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
+                          BranchCount.Skipped);
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
@@ -1757,7 +1761,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount, ExitCount);
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
   }
 
   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
@@ -1792,9 +1796,10 @@ struct CounterCoverageMappingBuilder
       OutCount = getRegionCounter(S);
     else {
       LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-      auto [ExecCount, SkipCount] = getBranchCounterPair(S, LoopCount);
-      ExitCount = SkipCount;
-      assert(ExecCount.isZero() || ExecCount == BodyCount);
+      auto BranchCount = getBranchCounterPair(S, LoopCount);
+      ExitCount = BranchCount.Skipped;
+      assert(BranchCount.Executed.isZero() ||
+             BranchCount.Executed == BodyCount);
       OutCount = addCounters(BC.BreakCount, ExitCount);
     }
     if (!IsCounterEqual(OutCount, ParentCount)) {
@@ -1828,9 +1833,9 @@ struct CounterCoverageMappingBuilder
 
     Counter LoopCount =
         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-    auto [ExecCount, ExitCount] = getBranchCounterPair(S, LoopCount);
-    assert(ExecCount.isZero() || ExecCount == BodyCount);
-    Counter OutCount = addCounters(BC.BreakCount, ExitCount);
+    auto BranchCount = getBranchCounterPair(S, LoopCount);
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount);
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;

>From c8edf58d644e80281e00577920125fa1d7618f47 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 8 Jan 2025 09:22:58 +0900
Subject: [PATCH 30/36] Flatten with getBranchCounterPair(SkipCntForOld)

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 95 +++++++++++-------------
 1 file changed, 44 insertions(+), 51 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index c03eb6a55af5e..0495a60e53c24 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -939,8 +939,17 @@ struct CounterCoverageMappingBuilder
     Counter Skipped;
   };
 
-  BranchCounterPair getBranchCounterPair(const Stmt *S, Counter ParentCnt) {
+  BranchCounterPair
+  getBranchCounterPair(const Stmt *S, Counter ParentCnt,
+                       std::optional<Counter> SkipCntForOld = std::nullopt) {
     Counter ExecCnt = getRegionCounter(S);
+
+    // The old behavior of SingleByte shouldn't emit Branches.
+    if (llvm::EnableSingleByteCoverage) {
+      assert(SkipCntForOld);
+      return {ExecCnt, *SkipCntForOld};
+    }
+
     return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
   }
 
@@ -1601,14 +1610,10 @@ struct CounterCoverageMappingBuilder
         llvm::EnableSingleByteCoverage
             ? getRegionCounter(S->getCond())
             : addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-    auto BranchCount =
-        (llvm::EnableSingleByteCoverage
-             ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
-             : getBranchCounterPair(S, CondCount));
-    if (!llvm::EnableSingleByteCoverage) {
-      assert(BranchCount.Executed.isZero() ||
-             BranchCount.Executed == BodyCount);
-    }
+    auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
+
     propagateCounts(CondCount, S->getCond());
     adjustForOutOfOrderTraversal(getEnd(S));
 
@@ -1617,10 +1622,10 @@ struct CounterCoverageMappingBuilder
     if (Gap)
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
-    Counter OutCount = llvm::EnableSingleByteCoverage
-                           ? getRegionCounter(S)
-                           : addCounters(BC.BreakCount, BranchCount.Skipped);
-
+    assert(
+        !llvm::EnableSingleByteCoverage ||
+        (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
@@ -1659,19 +1664,16 @@ struct CounterCoverageMappingBuilder
     Counter CondCount = llvm::EnableSingleByteCoverage
                             ? getRegionCounter(S->getCond())
                             : addCounters(BackedgeCount, BC.ContinueCount);
-    auto BranchCount =
-        (llvm::EnableSingleByteCoverage
-             ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
-             : getBranchCounterPair(S, CondCount));
-    if (!llvm::EnableSingleByteCoverage) {
-      assert(BranchCount.Executed.isZero() ||
-             BranchCount.Executed == BodyCount);
-    }
+    auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
+
     propagateCounts(CondCount, S->getCond());
 
-    Counter OutCount = llvm::EnableSingleByteCoverage
-                           ? getRegionCounter(S)
-                           : addCounters(BC.BreakCount, BranchCount.Skipped);
+    assert(
+        !llvm::EnableSingleByteCoverage ||
+        (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
@@ -1728,14 +1730,9 @@ struct CounterCoverageMappingBuilder
             : addCounters(
                   addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
                   IncrementBC.ContinueCount);
-    auto BranchCount =
-        (llvm::EnableSingleByteCoverage
-             ? BranchCounterPair{getRegionCounter(S), Counter::getZero()}
-             : getBranchCounterPair(S, CondCount));
-    if (!llvm::EnableSingleByteCoverage) {
-      assert(BranchCount.Executed.isZero() ||
-             BranchCount.Executed == BodyCount);
-    }
+    auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
 
     if (const Expr *Cond = S->getCond()) {
       propagateCounts(CondCount, Cond);
@@ -1747,11 +1744,10 @@ struct CounterCoverageMappingBuilder
     if (Gap)
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
-    Counter OutCount =
-        llvm::EnableSingleByteCoverage
-            ? getRegionCounter(S)
-            : addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
-                          BranchCount.Skipped);
+    assert(!llvm::EnableSingleByteCoverage ||
+           (BodyBC.BreakCount.isZero() && IncrementBC.BreakCount.isZero()));
+    Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
+                                   BranchCount.Skipped);
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
@@ -1789,19 +1785,16 @@ struct CounterCoverageMappingBuilder
     if (Gap)
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
-    Counter OutCount;
-    Counter ExitCount;
-    Counter LoopCount;
-    if (llvm::EnableSingleByteCoverage)
-      OutCount = getRegionCounter(S);
-    else {
-      LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-      auto BranchCount = getBranchCounterPair(S, LoopCount);
-      ExitCount = BranchCount.Skipped;
-      assert(BranchCount.Executed.isZero() ||
-             BranchCount.Executed == BodyCount);
-      OutCount = addCounters(BC.BreakCount, ExitCount);
-    }
+    Counter LoopCount =
+        addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+    auto BranchCount = getBranchCounterPair(S, LoopCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
+    assert(
+        !llvm::EnableSingleByteCoverage ||
+        (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
+
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
     if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
@@ -1811,7 +1804,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount, ExitCount);
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
   }
 
   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {

>From f2ba2192053cd335f8f848071b1e08fc6f071808 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 8 Jan 2025 18:10:52 +0900
Subject: [PATCH 31/36] Update comments

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 0495a60e53c24..8bc5d73bbd0ce 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -935,16 +935,32 @@ struct CounterCoverageMappingBuilder
   }
 
   struct BranchCounterPair {
-    Counter Executed;
-    Counter Skipped;
+    Counter Executed; ///< The Counter previously assigned.
+    Counter Skipped;  ///< An expression (Parent-Executed), or equivalent to it.
   };
 
+  /// Retrieve or assign the pair of Counter(s).
+  ///
+  /// This returns BranchCounterPair {Executed, Skipped}.
+  /// Executed is the Counter associated with S assigned by an earlier
+  /// CounterMapping pass.
+  /// Skipped may be an expression (Executed - ParentCnt) or newly
+  /// assigned Counter in EnableSingleByteCoverage, as subtract
+  /// expressions are not available in this mode.
+  ///
+  /// \param S Key to the CounterMap
+  /// \param ParentCnt The Counter representing how many times S is evaluated.
+  /// \param SkipCntForOld (To be removed later) Optional fake Counter
+  ///                      to override Skipped for adjustment of
+  ///                      expressions in the old behavior of
+  ///                      EnableSingleByteCoverage that is unaware of
+  ///                      Branch coverage.
   BranchCounterPair
   getBranchCounterPair(const Stmt *S, Counter ParentCnt,
                        std::optional<Counter> SkipCntForOld = std::nullopt) {
     Counter ExecCnt = getRegionCounter(S);
 
-    // The old behavior of SingleByte shouldn't emit Branches.
+    // The old behavior of SingleByte is unaware of Branches.
     if (llvm::EnableSingleByteCoverage) {
       assert(SkipCntForOld);
       return {ExecCnt, *SkipCntForOld};

>From 97015cb5e015a517d83bf67e3e8f65310f51bc55 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 8 Jan 2025 18:11:02 +0900
Subject: [PATCH 32/36] Decorate the mock

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 8bc5d73bbd0ce..72c027fa8e566 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -962,7 +962,8 @@ struct CounterCoverageMappingBuilder
 
     // The old behavior of SingleByte is unaware of Branches.
     if (llvm::EnableSingleByteCoverage) {
-      assert(SkipCntForOld);
+      assert(SkipCntForOld &&
+             "SingleByte must provide SkipCntForOld as a fake Skipped count.");
       return {ExecCnt, *SkipCntForOld};
     }
 

>From 9a40d20d0c468f7da49d156fd4c7752e9902033b Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 9 Jan 2025 14:11:45 +0900
Subject: [PATCH 33/36] Will be pruned after the migration of SingleByte.

---
 clang/lib/CodeGen/CoverageMappingGen.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 72c027fa8e566..dfffa12b639f2 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -961,6 +961,7 @@ struct CounterCoverageMappingBuilder
     Counter ExecCnt = getRegionCounter(S);
 
     // The old behavior of SingleByte is unaware of Branches.
+    // Will be pruned after the migration of SingleByte.
     if (llvm::EnableSingleByteCoverage) {
       assert(SkipCntForOld &&
              "SingleByte must provide SkipCntForOld as a fake Skipped count.");

>From b548e71a3cf55167d5b49e010cc76c8c82f29280 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 9 Jan 2025 15:19:00 +0900
Subject: [PATCH 34/36] Add comments

---
 llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index dad5f1276f27c..edae71491191e 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -215,9 +215,12 @@ class CounterExpressionBuilder {
   /// LHS.
   Counter subtract(Counter LHS, Counter RHS, bool Simplify = true);
 
+  /// K to V map. K will be Counter in most cases. V may be Counter or
+  /// Expression.
   using SubstMap = std::map<Counter, Counter>;
 
-  /// Return a counter for each term in the expression replaced by SubstMap.
+  /// \return A counter equivalent to \C, with each term in its
+  /// expression replaced with term from \p Map.
   Counter subst(Counter C, const SubstMap &Map);
 };
 

>From 5d31a507879e4518f83e0db6046811d9562b1b64 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 5 Jan 2026 19:30:44 +0900
Subject: [PATCH 35/36] Add comments

---
 clang/lib/CodeGen/CodeGenFunction.h      | 10 ++++++++--
 clang/lib/CodeGen/CoverageMappingGen.cpp |  5 +++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index b6c1017c1bec9..13c8f2002aad9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1662,9 +1662,15 @@ class CodeGenFunction : public CodeGenTypeCache {
   void markStmtAsUsed(bool Skipped, const Stmt *S);
   void markStmtMaybeUsed(const Stmt *S);
 
+  /// Used to specify which counter in a pair shall be incremented.
+  /// For non-binary counters, a skip counter is derived as (Parent - Exec).
+  /// In contrast for binary counters, a skip counter cannot be computed from
+  /// the Parent counter. In such cases, dedicated SkipPath counters must be
+  /// allocated and marked (incremented as binary counters). (Parent can be
+  /// synthesized with (Exec + Skip) in simple cases)
   enum CounterForIncrement {
-    UseExecPath = 0,
-    UseSkipPath,
+    UseExecPath = 0, ///< Exec (true)
+    UseSkipPath,     ///< Skip (false)
   };
 
   /// Increment the profiler's counter for the given statement by \p StepV.
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index a6fb7f5b3fddd..9a6d3c9abecbd 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -886,7 +886,12 @@ struct CounterCoverageMappingBuilder
   /// The map of statements to count values.
   llvm::DenseMap<const Stmt *, CounterPair> &CounterMap;
 
+  /// Used to expand an allocatd SkipCnt to Expression with known counters.
+  /// Key: SkipCnt
+  /// Val: Subtract Expression
   CounterExpressionBuilder::SubstMap MapToExpand;
+
+  /// Index and number for additional counters for SkipCnt.
   unsigned NextCounterNum;
 
   MCDC::State &MCDCState;

>From babbcf8bf87055739e25f0da5f18f807b1f62bb9 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 6 Jan 2026 11:01:03 +0900
Subject: [PATCH 36/36] emitCounterSetOrIncrement: Simplify.

- s/`TheMap`/`TheCounterPair`/
- Change the type of `Counter` to `ValueOpt`.
---
 clang/lib/CodeGen/CodeGenPGO.cpp | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 97fc328ee424e..d23f1a9aa5142 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1210,21 +1210,17 @@ void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
   if (!RegionCounterMap)
     return;
 
-  unsigned Counter;
-  auto &TheMap = (*RegionCounterMap)[S];
-  if (!UseSkipPath) {
-    if (!TheMap.Executed.hasValue())
-      return;
-    Counter = TheMap.Executed;
-  } else {
-    if (!TheMap.Skipped.hasValue())
-      return;
-    Counter = TheMap.Skipped;
-  }
+  // Allocate S in the Map regardless of emission.
+  const auto &TheCounterPair = (*RegionCounterMap)[S];
 
   if (!Builder.GetInsertBlock())
     return;
 
+  const CounterPair::ValueOpt &Counter =
+      (UseSkipPath ? TheCounterPair.Skipped : TheCounterPair.Executed);
+  if (!Counter.hasValue())
+    return;
+
   // Make sure that pointer to global is passed in with zero addrspace
   // This is relevant during GPU profiling
   auto *NormalizedFuncNameVarPtr =



More information about the cfe-commits mailing list