[clang] [Coverage] Introduce `getBranchCounterPair()`. NFC. (PR #112702)

NAKAMURA Takumi via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 8 21:12:27 PST 2025


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

>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 01/12] [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 07015834bc84f3..0bfad9cbcbe12b 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 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 02/12] 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 0bfad9cbcbe12b..8bd9ab402f4e59 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 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 03/12] 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 1782434bdb9aa6..532f6e8ba18201 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 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 04/12] 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 e63c38fcd4ba25..dff804fbeee923 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 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 05/12] 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 dff804fbeee923..df29c2cb4ee178 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 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 06/12] 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 df29c2cb4ee178..d1968c5861c95a 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 07/12] 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 d1968c5861c95a..a973bcbb3f7658 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 08/12] 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 a973bcbb3f7658..c03eb6a55af5e0 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 09/12] 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 c03eb6a55af5e0..0495a60e53c24a 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 10/12] 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 0495a60e53c24a..8bc5d73bbd0ce4 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 11/12] 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 8bc5d73bbd0ce4..72c027fa8e5664 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 12/12] 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 72c027fa8e5664..dfffa12b639f24 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.");



More information about the cfe-commits mailing list