[clang] [llvm] [MC/DC][Coverage] Loosen the limit of NumConds from 6 (PR #82448)

NAKAMURA Takumi via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 10 07:43:50 PDT 2024


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

>From d168e0cb85eb150caa7ab241f136c5a23f79ba38 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 5 Feb 2024 00:33:40 +0900
Subject: [PATCH 01/33] Implement MCDCTVIdxBuilder and MCDCTestVectorBuilder
 (LLVM side)

This accept current version of profdata. The output might be different.

See also
https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798
---
 .../ProfileData/Coverage/CoverageMapping.h    |  24 ++
 .../ProfileData/Coverage/CoverageMapping.cpp  | 226 +++++++++++++-----
 llvm/test/tools/llvm-cov/mcdc-const.test      |  28 +--
 llvm/test/tools/llvm-cov/mcdc-general.test    |  16 +-
 4 files changed, 214 insertions(+), 80 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 88ec60c7aa33c..62867275a8524 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -32,6 +32,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstdint>
+#include <functional>
 #include <iterator>
 #include <memory>
 #include <sstream>
@@ -557,6 +558,29 @@ struct MCDCRecord {
   }
 };
 
+class MCDCTVIdxBuilder {
+public:
+  struct MCDCNode {
+    int InCount = 0;
+    unsigned Width;
+    struct {
+      int ID;
+      int Idx;
+    } Conds[2];
+  };
+
+  SmallVector<MCDCNode> Nodes;
+  unsigned NumTestVectors;
+
+public:
+  using NodeIDs = std::tuple<unsigned, // ID1 (ends with 0)
+                             unsigned, // ID1 for False
+                             unsigned  // ID1 for True
+                             >;
+
+  MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher);
+};
+
 /// A Counter mapping context is used to connect the counters, expressions
 /// and the obtained counter values.
 class CounterMappingContext {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 39e43f86eab5e..d3a60c664b9e9 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -223,6 +223,171 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
   return LastPoppedValue;
 }
 
+MCDCTVIdxBuilder::MCDCTVIdxBuilder(
+    std::function<NodeIDs(bool TellSize)> Fetcher) {
+  // Build Nodes and set up each InCount
+  int MaxID = -1;
+  Nodes.resize(std::get<0>(Fetcher(true)));
+  while (true) {
+    auto [ID1, FalseID1, TrueID1] = Fetcher(false);
+    if (ID1 == 0)
+      break;
+    if (Nodes.size() < ID1)
+      Nodes.resize(ID1);
+    int ID = ID1 - 1;
+    MaxID = std::max(MaxID, ID);
+    auto &Node = Nodes[ID];
+    Node.Conds[0].ID = FalseID1 - 1;
+    Node.Conds[1].ID = TrueID1 - 1;
+    for (unsigned I = 0; I < 2; ++I) {
+      int NextID = Node.Conds[I].ID;
+      if (NextID >= 0)
+        ++Nodes[NextID].InCount;
+    }
+  }
+
+  if (MaxID < 0)
+    return;
+
+  // Sort key ordered by <-Width, Ord>
+  SmallVector<std::tuple<int,      /// -Width
+                         unsigned, /// Ord
+                         int,      /// ID
+                         unsigned  /// Cond (0 or 1)
+                         >>
+      Decisions;
+
+  // Traverse Nodes to assign Idx
+  SmallVector<int> Q;
+  assert(Nodes[0].InCount == 0);
+  Nodes[0].Width = 1;
+  Q.push_back(0);
+
+  unsigned Ord = 0;
+  while (!Q.empty()) {
+    int ID = *Q.begin();
+    Q.erase(Q.begin());
+    auto &Node = Nodes[ID];
+    assert(Node.Width > 0);
+
+    for (unsigned I = 0; I < 2; ++I) {
+      int NextID = Node.Conds[I].ID;
+      assert(NextID != 0);
+      if (NextID < 0) {
+        Decisions.emplace_back(-Node.Width, Ord++, ID, I);
+        assert(Ord == Decisions.size());
+        continue;
+      }
+
+      auto &NextNode = Nodes[NextID];
+      assert(NextNode.InCount > 0);
+      Node.Conds[I].Idx = NextNode.Width; // ???
+      NextNode.Width += Node.Width;
+      if (--NextNode.InCount == 0)
+        Q.push_back(NextID);
+    }
+  }
+
+  std::sort(Decisions.begin(), Decisions.end());
+
+  // Assign TestVector Index
+  unsigned CurIdx = 0;
+  for (auto [NegWidth, Ord, ID, C] : Decisions) {
+    unsigned Width = -NegWidth;
+    auto &Node = Nodes[ID];
+    assert(Node.Width == Width);
+    assert(Node.Conds[C].Idx == 0);
+    assert(Node.Conds[C].ID < 0);
+    Node.Conds[C].Idx = CurIdx;
+    CurIdx += Width;
+  }
+  NumTestVectors = CurIdx;
+}
+
+namespace {
+
+class MCDCTestVectorBuilder : public MCDCTVIdxBuilder {
+  MCDCRecord::TestVectors TestVectors;
+  const BitVector &Bitmap;
+  unsigned BitmapIdx;
+#ifndef NDEBUG
+  DenseSet<unsigned> TVIDs;
+#endif
+
+  class BranchProvider {
+    ArrayRef<const CounterMappingRegion *> Branches;
+    unsigned BranchIdx = 0;
+
+  public:
+    BranchProvider(ArrayRef<const CounterMappingRegion *> Branches)
+        : Branches(Branches) {}
+
+    std::function<NodeIDs(bool)> getFetcher() {
+      return [this](bool TellSize) {
+        if (TellSize)
+          return NodeIDs(Branches.size(), 0, 0);
+        if (BranchIdx >= Branches.size())
+          return NodeIDs(0, 0, 0);
+        const auto *B = Branches[BranchIdx++];
+        return NodeIDs(B->MCDCParams.ID, B->MCDCParams.FalseID,
+                       B->MCDCParams.TrueID);
+      };
+    }
+  };
+
+public:
+  MCDCTestVectorBuilder(ArrayRef<const CounterMappingRegion *> Branches,
+                        const BitVector &Bitmap, unsigned BitmapIdx)
+      : MCDCTVIdxBuilder(BranchProvider(Branches).getFetcher()), Bitmap(Bitmap),
+        BitmapIdx(BitmapIdx) {}
+
+protected:
+  MCDCRecord::TestVector TempTV;
+
+  void buildTestVector(int ID = 0, unsigned TVIdx = 0, unsigned Index = 0) {
+    const auto &Node = Nodes[ID];
+
+    for (unsigned I = 0; I < 2; ++I) {
+      auto MCDCCond = (I ? MCDCRecord::MCDC_True : MCDCRecord::MCDC_False);
+      const auto &Cond = Node.Conds[I];
+      auto NextID = Cond.ID;
+      Index |= I << ID;
+      TempTV[ID] = MCDCCond;
+      if (NextID >= 0) {
+        buildTestVector(NextID, TVIdx + Cond.Idx, Index);
+        continue;
+      }
+
+      auto FinalTVIdx = Cond.Idx + TVIdx;
+      assert(TVIdx < Node.Width);
+#ifndef NDEBUG
+      assert(!TVIDs.contains(FinalTVIdx));
+      TVIDs.insert(FinalTVIdx);
+#endif
+
+      assert(BitmapIdx + Index < Bitmap.size() && "Bitmap overrun");
+      if (!Bitmap[BitmapIdx + Index])
+        continue;
+
+      TestVectors.push_back(TempTV);
+      TestVectors.back().push_back(MCDCCond);
+    }
+
+    // Reset back to DontCare.
+    TempTV[ID] = MCDCRecord::MCDC_DontCare;
+  }
+
+public:
+  MCDCRecord::TestVectors findExecutedTestVectors() {
+    TempTV.resize(Nodes.size(), MCDCRecord::MCDC_DontCare);
+    buildTestVector();
+    assert(TVIDs.size() == NumTestVectors);
+    return std::move(TestVectors);
+  }
+};
+
+} // namespace
+
 class MCDCRecordProcessor {
   /// A bitmap representing the executed test vectors for a boolean expression.
   /// Each index of the bitmap corresponds to a possible test vector. An index
@@ -251,9 +416,6 @@ class MCDCRecordProcessor {
   /// Mapping of calculated MC/DC Independence Pairs for each condition.
   MCDCRecord::TVPairMap IndependencePairs;
 
-  /// Total number of possible Test Vectors for the boolean expression.
-  MCDCRecord::TestVectors TestVectors;
-
   /// Actual executed Test Vectors for the boolean expression, based on
   /// ExecutedTestVectorBitmap.
   MCDCRecord::TestVectors ExecVectors;
@@ -265,56 +427,9 @@ class MCDCRecordProcessor {
       : Bitmap(Bitmap), Region(Region), Branches(Branches),
         NumConditions(Region.MCDCParams.NumConditions),
         BitmapIdx(Region.MCDCParams.BitmapIdx * CHAR_BIT),
-        Folded(NumConditions, false), IndependencePairs(NumConditions),
-        TestVectors((size_t)1 << NumConditions) {}
+        Folded(NumConditions, false), IndependencePairs(NumConditions) {}
 
 private:
-  void recordTestVector(MCDCRecord::TestVector &TV, unsigned Index,
-                        MCDCRecord::CondState Result) {
-    // Copy the completed test vector to the vector of testvectors.
-    TestVectors[Index] = TV;
-
-    // The final value (T,F) is equal to the last non-dontcare state on the
-    // path (in a short-circuiting system).
-    TestVectors[Index].push_back(Result);
-  }
-
-  // Walk the binary decision diagram and try assigning both false and true to
-  // each node. When a terminal node (ID == 0) is reached, fill in the value in
-  // the truth table.
-  void buildTestVector(MCDCRecord::TestVector &TV, unsigned ID,
-                       unsigned Index) {
-    const CounterMappingRegion *Branch = Map[ID];
-
-    TV[ID - 1] = MCDCRecord::MCDC_False;
-    if (Branch->MCDCParams.FalseID > 0)
-      buildTestVector(TV, Branch->MCDCParams.FalseID, Index);
-    else
-      recordTestVector(TV, Index, MCDCRecord::MCDC_False);
-
-    Index |= 1 << (ID - 1);
-    TV[ID - 1] = MCDCRecord::MCDC_True;
-    if (Branch->MCDCParams.TrueID > 0)
-      buildTestVector(TV, Branch->MCDCParams.TrueID, Index);
-    else
-      recordTestVector(TV, Index, MCDCRecord::MCDC_True);
-
-    // Reset back to DontCare.
-    TV[ID - 1] = MCDCRecord::MCDC_DontCare;
-  }
-
-  /// Walk the bits in the bitmap.  A bit set to '1' indicates that the test
-  /// vector at the corresponding index was executed during a test run.
-  void findExecutedTestVectors() {
-    for (unsigned Idx = 0; Idx < (1u << NumConditions); ++Idx) {
-      assert(BitmapIdx + Idx < Bitmap.size() && "Bitmap overrun");
-      if (Bitmap[BitmapIdx + Idx] == 0)
-        continue;
-      assert(!TestVectors[Idx].empty() && "Test Vector doesn't exist.");
-      ExecVectors.push_back(TestVectors[Idx]);
-    }
-  }
-
   // Find an independence pair for each condition:
   // - The condition is true in one test and false in the other.
   // - The decision outcome is true one test and false in the other.
@@ -378,14 +493,9 @@ class MCDCRecordProcessor {
       Folded[I++] = (B->Count.isZero() && B->FalseCount.isZero());
     }
 
-    // Walk the binary decision diagram to enumerate all possible test vectors.
-    // We start at the root node (ID == 1) with all values being DontCare.
-    // `Index` encodes the bitmask of true values and is initially 0.
-    MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
-    buildTestVector(TV, 1, 0);
-
     // Using Profile Bitmap from runtime, mark the executed test vectors.
-    findExecutedTestVectors();
+    ExecVectors = MCDCTestVectorBuilder(Branches, Bitmap, BitmapIdx)
+                      .findExecutedTestVectors();
 
     // Compare executed test vectors against each other to find an independence
     // pairs for each condition.  This processing takes the most time.
diff --git a/llvm/test/tools/llvm-cov/mcdc-const.test b/llvm/test/tools/llvm-cov/mcdc-const.test
index 0b2c9c98d5355..5424625cf6a6b 100644
--- a/llvm/test/tools/llvm-cov/mcdc-const.test
+++ b/llvm/test/tools/llvm-cov/mcdc-const.test
@@ -61,8 +61,8 @@
 //      CHECKFULLCASE: |  C1-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C  = T      }
+//      CHECKFULLCASE: |  1 { F,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
@@ -106,8 +106,8 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
@@ -118,8 +118,8 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  T  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  T  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
@@ -151,26 +151,26 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: covered: (2,3)
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 100.00%
-//      CHECKFULLCASE: |  1 { T,  -,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  T,  C  = T      }
+//      CHECKFULLCASE: |  1 { F,  T,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  -,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  -,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  T,  C  = T      }
+//      CHECKFULLCASE: |  1 { F,  T,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  -,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  T  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  T  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
diff --git a/llvm/test/tools/llvm-cov/mcdc-general.test b/llvm/test/tools/llvm-cov/mcdc-general.test
index 753036bedaf17..4b59ce59d638e 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general.test
@@ -19,16 +19,16 @@
 // CHECK-NEXT:  |
 // CHECK-NEXT:  |     C1, C2, C3, C4    Result
 // CHECK-NEXT:  |  1 { F,  -,  F,  -  = F      }
-// CHECK-NEXT:  |  2 { T,  F,  F,  -  = F      }
-// CHECK-NEXT:  |  3 { F,  -,  T,  F  = F      }
+// CHECK-NEXT:  |  2 { F,  -,  T,  F  = F      }
+// CHECK-NEXT:  |  3 { T,  F,  F,  -  = F      }
 // CHECK-NEXT:  |  4 { T,  F,  T,  F  = F      }
-// CHECK-NEXT:  |  5 { T,  T,  -,  -  = T      }
-// CHECK-NEXT:  |  6 { T,  F,  T,  T  = T      }
+// CHECK-NEXT:  |  5 { T,  F,  T,  T  = T      }
+// CHECK-NEXT:  |  6 { T,  T,  -,  -  = T      }
 // CHECK-NEXT:  |
-// CHECK-NEXT:  |  C1-Pair: covered: (1,5)
-// CHECK-NEXT:  |  C2-Pair: covered: (2,5)
-// CHECK-NEXT:  |  C3-Pair: covered: (2,6)
-// CHECK-NEXT:  |  C4-Pair: covered: (4,6)
+// CHECK-NEXT:  |  C1-Pair: covered: (1,6)
+// CHECK-NEXT:  |  C2-Pair: covered: (3,6)
+// CHECK-NEXT:  |  C3-Pair: covered: (3,5)
+// CHECK-NEXT:  |  C4-Pair: covered: (4,5)
 // CHECK-NEXT:  |  MC/DC Coverage for Decision: 100.00%
 // CHECK-NEXT:  |
 // CHECK-NEXT:  ------------------

>From 35b19ea47f34bb14b30fca25572fcd55a3b6b3b5 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 6 Feb 2024 17:21:04 +0900
Subject: [PATCH 02/33] Revert "Implement MCDCTVIdxBuilder and
 MCDCTestVectorBuilder (LLVM side)"

This reverts commit d168e0cb85eb150caa7ab241f136c5a23f79ba38.
---
 .../ProfileData/Coverage/CoverageMapping.h    |  24 --
 .../ProfileData/Coverage/CoverageMapping.cpp  | 226 +++++-------------
 llvm/test/tools/llvm-cov/mcdc-const.test      |  28 +--
 llvm/test/tools/llvm-cov/mcdc-general.test    |  16 +-
 4 files changed, 80 insertions(+), 214 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 62867275a8524..88ec60c7aa33c 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -32,7 +32,6 @@
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstdint>
-#include <functional>
 #include <iterator>
 #include <memory>
 #include <sstream>
@@ -558,29 +557,6 @@ struct MCDCRecord {
   }
 };
 
-class MCDCTVIdxBuilder {
-public:
-  struct MCDCNode {
-    int InCount = 0;
-    unsigned Width;
-    struct {
-      int ID;
-      int Idx;
-    } Conds[2];
-  };
-
-  SmallVector<MCDCNode> Nodes;
-  unsigned NumTestVectors;
-
-public:
-  using NodeIDs = std::tuple<unsigned, // ID1 (ends with 0)
-                             unsigned, // ID1 for False
-                             unsigned  // ID1 for True
-                             >;
-
-  MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher);
-};
-
 /// A Counter mapping context is used to connect the counters, expressions
 /// and the obtained counter values.
 class CounterMappingContext {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index d3a60c664b9e9..39e43f86eab5e 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -223,171 +223,6 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
   return LastPoppedValue;
 }
 
-MCDCTVIdxBuilder::MCDCTVIdxBuilder(
-    std::function<NodeIDs(bool TellSize)> Fetcher) {
-  // Build Nodes and set up each InCount
-  int MaxID = -1;
-  Nodes.resize(std::get<0>(Fetcher(true)));
-  while (true) {
-    auto [ID1, FalseID1, TrueID1] = Fetcher(false);
-    if (ID1 == 0)
-      break;
-    if (Nodes.size() < ID1)
-      Nodes.resize(ID1);
-    int ID = ID1 - 1;
-    MaxID = std::max(MaxID, ID);
-    auto &Node = Nodes[ID];
-    Node.Conds[0].ID = FalseID1 - 1;
-    Node.Conds[1].ID = TrueID1 - 1;
-    for (unsigned I = 0; I < 2; ++I) {
-      int NextID = Node.Conds[I].ID;
-      if (NextID >= 0)
-        ++Nodes[NextID].InCount;
-    }
-  }
-
-  if (MaxID < 0)
-    return;
-
-  // Sort key ordered by <-Width, Ord>
-  SmallVector<std::tuple<int,      /// -Width
-                         unsigned, /// Ord
-                         int,      /// ID
-                         unsigned  /// Cond (0 or 1)
-                         >>
-      Decisions;
-
-  // Traverse Nodes to assign Idx
-  SmallVector<int> Q;
-  assert(Nodes[0].InCount == 0);
-  Nodes[0].Width = 1;
-  Q.push_back(0);
-
-  unsigned Ord = 0;
-  while (!Q.empty()) {
-    int ID = *Q.begin();
-    Q.erase(Q.begin());
-    auto &Node = Nodes[ID];
-    assert(Node.Width > 0);
-
-    for (unsigned I = 0; I < 2; ++I) {
-      int NextID = Node.Conds[I].ID;
-      assert(NextID != 0);
-      if (NextID < 0) {
-        Decisions.emplace_back(-Node.Width, Ord++, ID, I);
-        assert(Ord == Decisions.size());
-        continue;
-      }
-
-      auto &NextNode = Nodes[NextID];
-      assert(NextNode.InCount > 0);
-      Node.Conds[I].Idx = NextNode.Width; // ???
-      NextNode.Width += Node.Width;
-      if (--NextNode.InCount == 0)
-        Q.push_back(NextID);
-    }
-  }
-
-  std::sort(Decisions.begin(), Decisions.end());
-
-  // Assign TestVector Index
-  unsigned CurIdx = 0;
-  for (auto [NegWidth, Ord, ID, C] : Decisions) {
-    unsigned Width = -NegWidth;
-    auto &Node = Nodes[ID];
-    assert(Node.Width == Width);
-    assert(Node.Conds[C].Idx == 0);
-    assert(Node.Conds[C].ID < 0);
-    Node.Conds[C].Idx = CurIdx;
-    CurIdx += Width;
-  }
-  NumTestVectors = CurIdx;
-}
-
-namespace {
-
-class MCDCTestVectorBuilder : public MCDCTVIdxBuilder {
-  MCDCRecord::TestVectors TestVectors;
-  const BitVector &Bitmap;
-  unsigned BitmapIdx;
-#ifndef NDEBUG
-  DenseSet<unsigned> TVIDs;
-#endif
-
-  class BranchProvider {
-    ArrayRef<const CounterMappingRegion *> Branches;
-    unsigned BranchIdx = 0;
-
-  public:
-    BranchProvider(ArrayRef<const CounterMappingRegion *> Branches)
-        : Branches(Branches) {}
-
-    std::function<NodeIDs(bool)> getFetcher() {
-      return [this](bool TellSize) {
-        if (TellSize)
-          return NodeIDs(Branches.size(), 0, 0);
-        if (BranchIdx >= Branches.size())
-          return NodeIDs(0, 0, 0);
-        const auto *B = Branches[BranchIdx++];
-        return NodeIDs(B->MCDCParams.ID, B->MCDCParams.FalseID,
-                       B->MCDCParams.TrueID);
-      };
-    }
-  };
-
-public:
-  MCDCTestVectorBuilder(ArrayRef<const CounterMappingRegion *> Branches,
-                        const BitVector &Bitmap, unsigned BitmapIdx)
-      : MCDCTVIdxBuilder(BranchProvider(Branches).getFetcher()), Bitmap(Bitmap),
-        BitmapIdx(BitmapIdx) {}
-
-protected:
-  MCDCRecord::TestVector TempTV;
-
-  void buildTestVector(int ID = 0, unsigned TVIdx = 0, unsigned Index = 0) {
-    const auto &Node = Nodes[ID];
-
-    for (unsigned I = 0; I < 2; ++I) {
-      auto MCDCCond = (I ? MCDCRecord::MCDC_True : MCDCRecord::MCDC_False);
-      const auto &Cond = Node.Conds[I];
-      auto NextID = Cond.ID;
-      Index |= I << ID;
-      TempTV[ID] = MCDCCond;
-      if (NextID >= 0) {
-        buildTestVector(NextID, TVIdx + Cond.Idx, Index);
-        continue;
-      }
-
-      auto FinalTVIdx = Cond.Idx + TVIdx;
-      assert(TVIdx < Node.Width);
-#ifndef NDEBUG
-      assert(!TVIDs.contains(FinalTVIdx));
-      TVIDs.insert(FinalTVIdx);
-#endif
-
-      assert(BitmapIdx + Index < Bitmap.size() && "Bitmap overrun");
-      if (!Bitmap[BitmapIdx + Index])
-        continue;
-
-      TestVectors.push_back(TempTV);
-      TestVectors.back().push_back(MCDCCond);
-    }
-
-    // Reset back to DontCare.
-    TempTV[ID] = MCDCRecord::MCDC_DontCare;
-  }
-
-public:
-  MCDCRecord::TestVectors findExecutedTestVectors() {
-    TempTV.resize(Nodes.size(), MCDCRecord::MCDC_DontCare);
-    buildTestVector();
-    assert(TVIDs.size() == NumTestVectors);
-    return std::move(TestVectors);
-  }
-};
-
-} // namespace
-
 class MCDCRecordProcessor {
   /// A bitmap representing the executed test vectors for a boolean expression.
   /// Each index of the bitmap corresponds to a possible test vector. An index
@@ -416,6 +251,9 @@ class MCDCRecordProcessor {
   /// Mapping of calculated MC/DC Independence Pairs for each condition.
   MCDCRecord::TVPairMap IndependencePairs;
 
+  /// Total number of possible Test Vectors for the boolean expression.
+  MCDCRecord::TestVectors TestVectors;
+
   /// Actual executed Test Vectors for the boolean expression, based on
   /// ExecutedTestVectorBitmap.
   MCDCRecord::TestVectors ExecVectors;
@@ -427,9 +265,56 @@ class MCDCRecordProcessor {
       : Bitmap(Bitmap), Region(Region), Branches(Branches),
         NumConditions(Region.MCDCParams.NumConditions),
         BitmapIdx(Region.MCDCParams.BitmapIdx * CHAR_BIT),
-        Folded(NumConditions, false), IndependencePairs(NumConditions) {}
+        Folded(NumConditions, false), IndependencePairs(NumConditions),
+        TestVectors((size_t)1 << NumConditions) {}
 
 private:
+  void recordTestVector(MCDCRecord::TestVector &TV, unsigned Index,
+                        MCDCRecord::CondState Result) {
+    // Copy the completed test vector to the vector of testvectors.
+    TestVectors[Index] = TV;
+
+    // The final value (T,F) is equal to the last non-dontcare state on the
+    // path (in a short-circuiting system).
+    TestVectors[Index].push_back(Result);
+  }
+
+  // Walk the binary decision diagram and try assigning both false and true to
+  // each node. When a terminal node (ID == 0) is reached, fill in the value in
+  // the truth table.
+  void buildTestVector(MCDCRecord::TestVector &TV, unsigned ID,
+                       unsigned Index) {
+    const CounterMappingRegion *Branch = Map[ID];
+
+    TV[ID - 1] = MCDCRecord::MCDC_False;
+    if (Branch->MCDCParams.FalseID > 0)
+      buildTestVector(TV, Branch->MCDCParams.FalseID, Index);
+    else
+      recordTestVector(TV, Index, MCDCRecord::MCDC_False);
+
+    Index |= 1 << (ID - 1);
+    TV[ID - 1] = MCDCRecord::MCDC_True;
+    if (Branch->MCDCParams.TrueID > 0)
+      buildTestVector(TV, Branch->MCDCParams.TrueID, Index);
+    else
+      recordTestVector(TV, Index, MCDCRecord::MCDC_True);
+
+    // Reset back to DontCare.
+    TV[ID - 1] = MCDCRecord::MCDC_DontCare;
+  }
+
+  /// Walk the bits in the bitmap.  A bit set to '1' indicates that the test
+  /// vector at the corresponding index was executed during a test run.
+  void findExecutedTestVectors() {
+    for (unsigned Idx = 0; Idx < (1u << NumConditions); ++Idx) {
+      assert(BitmapIdx + Idx < Bitmap.size() && "Bitmap overrun");
+      if (Bitmap[BitmapIdx + Idx] == 0)
+        continue;
+      assert(!TestVectors[Idx].empty() && "Test Vector doesn't exist.");
+      ExecVectors.push_back(TestVectors[Idx]);
+    }
+  }
+
   // Find an independence pair for each condition:
   // - The condition is true in one test and false in the other.
   // - The decision outcome is true one test and false in the other.
@@ -493,9 +378,14 @@ class MCDCRecordProcessor {
       Folded[I++] = (B->Count.isZero() && B->FalseCount.isZero());
     }
 
+    // Walk the binary decision diagram to enumerate all possible test vectors.
+    // We start at the root node (ID == 1) with all values being DontCare.
+    // `Index` encodes the bitmask of true values and is initially 0.
+    MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
+    buildTestVector(TV, 1, 0);
+
     // Using Profile Bitmap from runtime, mark the executed test vectors.
-    ExecVectors = MCDCTestVectorBuilder(Branches, Bitmap, BitmapIdx)
-                      .findExecutedTestVectors();
+    findExecutedTestVectors();
 
     // Compare executed test vectors against each other to find an independence
     // pairs for each condition.  This processing takes the most time.
diff --git a/llvm/test/tools/llvm-cov/mcdc-const.test b/llvm/test/tools/llvm-cov/mcdc-const.test
index 5424625cf6a6b..0b2c9c98d5355 100644
--- a/llvm/test/tools/llvm-cov/mcdc-const.test
+++ b/llvm/test/tools/llvm-cov/mcdc-const.test
@@ -61,8 +61,8 @@
 //      CHECKFULLCASE: |  C1-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { F,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { T,  C  = T      }
+//      CHECKFULLCASE: |  1 { T,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { F,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
@@ -106,8 +106,8 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { F,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { F,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
@@ -118,8 +118,8 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { F,  C,  T  = T      }
-// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { F,  C,  T  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
@@ -151,26 +151,26 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: covered: (2,3)
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 100.00%
-//      CHECKFULLCASE: |  1 { F,  T,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { T,  -,  C  = T      }
+//      CHECKFULLCASE: |  1 { T,  -,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { F,  T,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { F,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { F,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { F,  T,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { T,  -,  C  = T      }
+//      CHECKFULLCASE: |  1 { T,  -,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { F,  T,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { F,  C,  T  = T      }
-// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { F,  C,  T  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
diff --git a/llvm/test/tools/llvm-cov/mcdc-general.test b/llvm/test/tools/llvm-cov/mcdc-general.test
index 4b59ce59d638e..753036bedaf17 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general.test
@@ -19,16 +19,16 @@
 // CHECK-NEXT:  |
 // CHECK-NEXT:  |     C1, C2, C3, C4    Result
 // CHECK-NEXT:  |  1 { F,  -,  F,  -  = F      }
-// CHECK-NEXT:  |  2 { F,  -,  T,  F  = F      }
-// CHECK-NEXT:  |  3 { T,  F,  F,  -  = F      }
+// CHECK-NEXT:  |  2 { T,  F,  F,  -  = F      }
+// CHECK-NEXT:  |  3 { F,  -,  T,  F  = F      }
 // CHECK-NEXT:  |  4 { T,  F,  T,  F  = F      }
-// CHECK-NEXT:  |  5 { T,  F,  T,  T  = T      }
-// CHECK-NEXT:  |  6 { T,  T,  -,  -  = T      }
+// CHECK-NEXT:  |  5 { T,  T,  -,  -  = T      }
+// CHECK-NEXT:  |  6 { T,  F,  T,  T  = T      }
 // CHECK-NEXT:  |
-// CHECK-NEXT:  |  C1-Pair: covered: (1,6)
-// CHECK-NEXT:  |  C2-Pair: covered: (3,6)
-// CHECK-NEXT:  |  C3-Pair: covered: (3,5)
-// CHECK-NEXT:  |  C4-Pair: covered: (4,5)
+// CHECK-NEXT:  |  C1-Pair: covered: (1,5)
+// CHECK-NEXT:  |  C2-Pair: covered: (2,5)
+// CHECK-NEXT:  |  C3-Pair: covered: (2,6)
+// CHECK-NEXT:  |  C4-Pair: covered: (4,6)
 // CHECK-NEXT:  |  MC/DC Coverage for Decision: 100.00%
 // CHECK-NEXT:  |
 // CHECK-NEXT:  ------------------

>From 8c777ebbea6f5d005de2112b88eceec9b5eeeadd Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 6 Feb 2024 17:06:11 +0900
Subject: [PATCH 03/33] [Coverage] MCDCRecordProcessor: Find `ExecVectors`
 directly

Deprecate `TestVectors`, since no one uses it.

This affects the output order of ExecVectors.
The current impl emits sorted by binary value of ExecVector.
This impl emits along the traversal of `buildTestVector()`.
---
 .../ProfileData/Coverage/CoverageMapping.cpp  | 31 +++++++------------
 llvm/test/tools/llvm-cov/mcdc-const.test      | 28 ++++++++---------
 llvm/test/tools/llvm-cov/mcdc-general.test    | 16 +++++-----
 3 files changed, 33 insertions(+), 42 deletions(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 6b189c3146328..eb0996e33b70d 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -253,9 +253,6 @@ class MCDCRecordProcessor {
   /// Mapping of calculated MC/DC Independence Pairs for each condition.
   MCDCRecord::TVPairMap IndependencePairs;
 
-  /// Total number of possible Test Vectors for the boolean expression.
-  MCDCRecord::TestVectors TestVectors;
-
   /// Actual executed Test Vectors for the boolean expression, based on
   /// ExecutedTestVectorBitmap.
   MCDCRecord::TestVectors ExecVectors;
@@ -267,18 +264,20 @@ class MCDCRecordProcessor {
       : Bitmap(Bitmap), Region(Region), Branches(Branches),
         NumConditions(Region.MCDCParams.NumConditions),
         BitmapIdx(Region.MCDCParams.BitmapIdx * CHAR_BIT),
-        Folded(NumConditions, false), IndependencePairs(NumConditions),
-        TestVectors((size_t)1 << NumConditions) {}
+        Folded(NumConditions, false), IndependencePairs(NumConditions) {}
 
 private:
   void recordTestVector(MCDCRecord::TestVector &TV, unsigned Index,
                         MCDCRecord::CondState Result) {
+    if (!Bitmap[BitmapIdx + Index])
+      return;
+
     // Copy the completed test vector to the vector of testvectors.
-    TestVectors[Index] = TV;
+    ExecVectors.push_back(TV);
 
     // The final value (T,F) is equal to the last non-dontcare state on the
     // path (in a short-circuiting system).
-    TestVectors[Index].push_back(Result);
+    ExecVectors.back().push_back(Result);
   }
 
   // Walk the binary decision diagram and try assigning both false and true to
@@ -308,13 +307,11 @@ class MCDCRecordProcessor {
   /// Walk the bits in the bitmap.  A bit set to '1' indicates that the test
   /// vector at the corresponding index was executed during a test run.
   void findExecutedTestVectors() {
-    for (unsigned Idx = 0; Idx < (1u << NumConditions); ++Idx) {
-      assert(BitmapIdx + Idx < Bitmap.size() && "Bitmap overrun");
-      if (Bitmap[BitmapIdx + Idx] == 0)
-        continue;
-      assert(!TestVectors[Idx].empty() && "Test Vector doesn't exist.");
-      ExecVectors.push_back(TestVectors[Idx]);
-    }
+    // Walk the binary decision diagram to enumerate all possible test vectors.
+    // We start at the root node (ID == 1) with all values being DontCare.
+    // `Index` encodes the bitmask of true values and is initially 0.
+    MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
+    buildTestVector(TV, 1, 0);
   }
 
   // Find an independence pair for each condition:
@@ -380,12 +377,6 @@ class MCDCRecordProcessor {
       Folded[I++] = (B->Count.isZero() && B->FalseCount.isZero());
     }
 
-    // Walk the binary decision diagram to enumerate all possible test vectors.
-    // We start at the root node (ID == 1) with all values being DontCare.
-    // `Index` encodes the bitmask of true values and is initially 0.
-    MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
-    buildTestVector(TV, 1, 0);
-
     // Using Profile Bitmap from runtime, mark the executed test vectors.
     findExecutedTestVectors();
 
diff --git a/llvm/test/tools/llvm-cov/mcdc-const.test b/llvm/test/tools/llvm-cov/mcdc-const.test
index 0b2c9c98d5355..5424625cf6a6b 100644
--- a/llvm/test/tools/llvm-cov/mcdc-const.test
+++ b/llvm/test/tools/llvm-cov/mcdc-const.test
@@ -61,8 +61,8 @@
 //      CHECKFULLCASE: |  C1-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C  = T      }
+//      CHECKFULLCASE: |  1 { F,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
@@ -106,8 +106,8 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
@@ -118,8 +118,8 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  T  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  T  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
@@ -151,26 +151,26 @@
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: covered: (2,3)
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 100.00%
-//      CHECKFULLCASE: |  1 { T,  -,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  T,  C  = T      }
+//      CHECKFULLCASE: |  1 { F,  T,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  -,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  -  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  -  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  -,  C  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  T,  C  = T      }
+//      CHECKFULLCASE: |  1 { F,  T,  C  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  -,  C  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C3-Pair: constant folded
 //      CHECKFULLCASE: |  MC/DC Coverage for Decision: 0.00%
-//      CHECKFULLCASE: |  1 { T,  C,  -  = T      }
-// CHECKFULLCASE-NEXT: |  2 { F,  C,  T  = T      }
+//      CHECKFULLCASE: |  1 { F,  C,  T  = T      }
+// CHECKFULLCASE-NEXT: |  2 { T,  C,  -  = T      }
 //      CHECKFULLCASE: |  C1-Pair: not covered
 // CHECKFULLCASE-NEXT: |  C2-Pair: constant folded
 // CHECKFULLCASE-NEXT: |  C3-Pair: not covered
diff --git a/llvm/test/tools/llvm-cov/mcdc-general.test b/llvm/test/tools/llvm-cov/mcdc-general.test
index 753036bedaf17..4b59ce59d638e 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general.test
@@ -19,16 +19,16 @@
 // CHECK-NEXT:  |
 // CHECK-NEXT:  |     C1, C2, C3, C4    Result
 // CHECK-NEXT:  |  1 { F,  -,  F,  -  = F      }
-// CHECK-NEXT:  |  2 { T,  F,  F,  -  = F      }
-// CHECK-NEXT:  |  3 { F,  -,  T,  F  = F      }
+// CHECK-NEXT:  |  2 { F,  -,  T,  F  = F      }
+// CHECK-NEXT:  |  3 { T,  F,  F,  -  = F      }
 // CHECK-NEXT:  |  4 { T,  F,  T,  F  = F      }
-// CHECK-NEXT:  |  5 { T,  T,  -,  -  = T      }
-// CHECK-NEXT:  |  6 { T,  F,  T,  T  = T      }
+// CHECK-NEXT:  |  5 { T,  F,  T,  T  = T      }
+// CHECK-NEXT:  |  6 { T,  T,  -,  -  = T      }
 // CHECK-NEXT:  |
-// CHECK-NEXT:  |  C1-Pair: covered: (1,5)
-// CHECK-NEXT:  |  C2-Pair: covered: (2,5)
-// CHECK-NEXT:  |  C3-Pair: covered: (2,6)
-// CHECK-NEXT:  |  C4-Pair: covered: (4,6)
+// CHECK-NEXT:  |  C1-Pair: covered: (1,6)
+// CHECK-NEXT:  |  C2-Pair: covered: (3,6)
+// CHECK-NEXT:  |  C3-Pair: covered: (3,5)
+// CHECK-NEXT:  |  C4-Pair: covered: (4,5)
 // CHECK-NEXT:  |  MC/DC Coverage for Decision: 100.00%
 // CHECK-NEXT:  |
 // CHECK-NEXT:  ------------------

>From 5432aecffd203f232842607ff581a20cbbf1ba3b Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 5 Feb 2024 00:33:40 +0900
Subject: [PATCH 04/33] Implement MCDCTVIdxBuilder (LLVM side)

This accepts current version of profdata. The output might be different.

See also
https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798
---
 .../ProfileData/Coverage/CoverageMapping.h    |  24 +++
 .../ProfileData/Coverage/CoverageMapping.cpp  | 162 +++++++++++++++---
 2 files changed, 166 insertions(+), 20 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 88ec60c7aa33c..45c28e6cfd792 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -32,6 +32,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstdint>
+#include <functional>
 #include <iterator>
 #include <memory>
 #include <sstream>
@@ -557,6 +558,29 @@ struct MCDCRecord {
   }
 };
 
+class MCDCTVIdxBuilder {
+public:
+  struct MCDCNode {
+    int InCount = 0;
+    int Width;
+    struct {
+      int ID;
+      int Idx;
+    } Conds[2];
+  };
+
+  SmallVector<MCDCNode> Nodes;
+  unsigned NumTestVectors;
+
+public:
+  using NodeIDs = std::tuple<unsigned, // ID1 (ends with 0)
+                             unsigned, // ID1 for False
+                             unsigned  // ID1 for True
+                             >;
+
+  MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher);
+};
+
 /// A Counter mapping context is used to connect the counters, expressions
 /// and the obtained counter values.
 class CounterMappingContext {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index eb0996e33b70d..5eb78f7a78571 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -223,9 +223,119 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
   return LastPoppedValue;
 }
 
+MCDCTVIdxBuilder::MCDCTVIdxBuilder(
+    std::function<NodeIDs(bool TellSize)> Fetcher) {
+  // Build Nodes and set up each InCount
+  int MaxID = -1;
+  Nodes.resize(std::get<0>(Fetcher(true)));
+  while (true) {
+    auto [ID1, FalseID1, TrueID1] = Fetcher(false);
+    if (ID1 == 0)
+      break;
+    int ID = ID1 - 1;
+    MaxID = std::max(MaxID, ID);
+    auto &Node = Nodes[ID];
+    Node.Conds[0].ID = FalseID1 - 1;
+    Node.Conds[1].ID = TrueID1 - 1;
+    for (unsigned I = 0; I < 2; ++I) {
+#ifndef NDEBUG
+      Node.Conds[I].Idx = INT_MIN;
+#endif
+      int NextID = Node.Conds[I].ID;
+      if (NextID >= 0)
+        ++Nodes[NextID].InCount;
+    }
+  }
+
+  if (MaxID < 0)
+    return;
+
+  // Sort key ordered by <-Width, Ord>
+  SmallVector<std::tuple<int,      /// -Width
+                         unsigned, /// Ord
+                         int,      /// ID
+                         unsigned  /// Cond (0 or 1)
+                         >>
+      Decisions;
+
+  // Traverse Nodes to assign Idx
+  SmallVector<int> Q;
+  assert(Nodes[0].InCount == 0);
+  Nodes[0].Width = 1;
+  Q.push_back(0);
+
+  unsigned Ord = 0;
+  while (!Q.empty()) {
+    int ID = *Q.begin();
+    Q.erase(Q.begin());
+    auto &Node = Nodes[ID];
+    assert(Node.Width > 0);
+
+    for (unsigned I = 0; I < 2; ++I) {
+      int NextID = Node.Conds[I].ID;
+      assert(NextID != 0);
+      if (NextID < 0) {
+        Decisions.emplace_back(-Node.Width, Ord++, ID, I);
+        assert(Ord == Decisions.size());
+        continue;
+      }
+
+      auto &NextNode = Nodes[NextID];
+      assert(NextNode.InCount > 0);
+      assert(Node.Conds[I].Idx == INT_MIN);
+      Node.Conds[I].Idx = NextNode.Width;
+      NextNode.Width += Node.Width;
+      if (--NextNode.InCount == 0)
+        Q.push_back(NextID);
+    }
+  }
+
+  std::sort(Decisions.begin(), Decisions.end());
+
+  // Assign TestVector Index
+  unsigned CurIdx = 0;
+  for (auto [NegWidth, Ord, ID, C] : Decisions) {
+    int Width = -NegWidth;
+    assert(Nodes[ID].Width == Width);
+    assert(Nodes[ID].Conds[C].Idx == INT_MIN);
+    assert(Nodes[ID].Conds[C].ID < 0);
+    Nodes[ID].Conds[C].Idx = CurIdx;
+    CurIdx += Width;
+  }
+  NumTestVectors = CurIdx;
+
+#ifndef NDEBUG
+  for (const auto &Node : Nodes)
+    for (const auto &Cond : Node.Conds)
+      assert(Cond.Idx != INT_MIN);
+#endif
+}
+
 namespace {
 
-class MCDCRecordProcessor {
+class BranchProvider {
+  using NodeIDs = MCDCTVIdxBuilder::NodeIDs;
+  ArrayRef<const CounterMappingRegion *> Branches;
+  unsigned BranchIdx = 0;
+
+public:
+  BranchProvider(ArrayRef<const CounterMappingRegion *> Branches)
+      : Branches(Branches) {}
+
+  std::function<NodeIDs(bool)> getFetcher() {
+    return [this](bool TellSize) {
+      if (TellSize)
+        return NodeIDs(Branches.size(), 0, 0);
+      if (BranchIdx >= Branches.size())
+        return NodeIDs(0, 0, 0);
+      const auto *B = Branches[BranchIdx++];
+      return NodeIDs(B->MCDCParams.ID, B->MCDCParams.FalseID,
+                     B->MCDCParams.TrueID);
+    };
+  }
+};
+
+class MCDCRecordProcessor : MCDCTVIdxBuilder {
   /// A bitmap representing the executed test vectors for a boolean expression.
   /// Each index of the bitmap corresponds to a possible test vector. An index
   /// with a bit value of '1' indicates that the corresponding Test Vector
@@ -257,18 +367,28 @@ class MCDCRecordProcessor {
   /// ExecutedTestVectorBitmap.
   MCDCRecord::TestVectors ExecVectors;
 
+#ifndef NDEBUG
+  DenseSet<unsigned> TVIDs;
+#endif
+
 public:
   MCDCRecordProcessor(const BitVector &Bitmap,
                       const CounterMappingRegion &Region,
                       ArrayRef<const CounterMappingRegion *> Branches)
-      : Bitmap(Bitmap), Region(Region), Branches(Branches),
+      : MCDCTVIdxBuilder(BranchProvider(Branches).getFetcher()), Bitmap(Bitmap),
+        Region(Region), Branches(Branches),
         NumConditions(Region.MCDCParams.NumConditions),
         BitmapIdx(Region.MCDCParams.BitmapIdx * CHAR_BIT),
         Folded(NumConditions, false), IndependencePairs(NumConditions) {}
 
 private:
-  void recordTestVector(MCDCRecord::TestVector &TV, unsigned Index,
+  void recordTestVector(MCDCRecord::TestVector &TV, int TVIdx, unsigned Index,
                         MCDCRecord::CondState Result) {
+#ifndef NDEBUG
+    assert(!TVIDs.contains(TVIdx));
+    TVIDs.insert(TVIdx);
+#endif
+
     if (!Bitmap[BitmapIdx + Index])
       return;
 
@@ -283,25 +403,26 @@ class MCDCRecordProcessor {
   // Walk the binary decision diagram and try assigning both false and true to
   // each node. When a terminal node (ID == 0) is reached, fill in the value in
   // the truth table.
-  void buildTestVector(MCDCRecord::TestVector &TV, unsigned ID,
+  void buildTestVector(MCDCRecord::TestVector &TV, int ID, int TVIdx,
                        unsigned Index) {
-    const CounterMappingRegion *Branch = Map[ID];
-
-    TV[ID - 1] = MCDCRecord::MCDC_False;
-    if (Branch->MCDCParams.FalseID > 0)
-      buildTestVector(TV, Branch->MCDCParams.FalseID, Index);
-    else
-      recordTestVector(TV, Index, MCDCRecord::MCDC_False);
-
-    Index |= 1 << (ID - 1);
-    TV[ID - 1] = MCDCRecord::MCDC_True;
-    if (Branch->MCDCParams.TrueID > 0)
-      buildTestVector(TV, Branch->MCDCParams.TrueID, Index);
-    else
-      recordTestVector(TV, Index, MCDCRecord::MCDC_True);
+    const auto &Node = Nodes[ID];
+
+    for (unsigned I = 0; I < 2; ++I) {
+      auto MCDCCond = (I ? MCDCRecord::MCDC_True : MCDCRecord::MCDC_False);
+      const auto &Cond = Node.Conds[I];
+      auto NextID = Cond.ID;
+      Index |= I << ID;
+      TV[ID] = MCDCCond;
+      if (NextID >= 0) {
+        buildTestVector(TV, NextID, TVIdx + Cond.Idx, Index);
+      } else {
+        assert(TVIdx < Node.Width);
+        recordTestVector(TV, Cond.Idx + TVIdx, Index, MCDCCond);
+      }
+    }
 
     // Reset back to DontCare.
-    TV[ID - 1] = MCDCRecord::MCDC_DontCare;
+    TV[ID] = MCDCRecord::MCDC_DontCare;
   }
 
   /// Walk the bits in the bitmap.  A bit set to '1' indicates that the test
@@ -311,7 +432,8 @@ class MCDCRecordProcessor {
     // We start at the root node (ID == 1) with all values being DontCare.
     // `Index` encodes the bitmask of true values and is initially 0.
     MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
-    buildTestVector(TV, 1, 0);
+    buildTestVector(TV, 0, 0, 0);
+    assert(TVIDs.size() == NumTestVectors);
   }
 
   // Find an independence pair for each condition:

>From 3ee8a6131de896869edd03f18e07e193c3229fe4 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 6 Feb 2024 21:41:43 +0900
Subject: [PATCH 05/33] Update comments and assertions

---
 .../ProfileData/Coverage/CoverageMapping.h    | 14 +++++++---
 .../ProfileData/Coverage/CoverageMapping.cpp  | 28 +++++++++++--------
 2 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 45c28e6cfd792..7341b41aed63d 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -558,14 +558,15 @@ struct MCDCRecord {
   }
 };
 
+/// Compute Conds[].Idx from Branch-like structure
 class MCDCTVIdxBuilder {
 public:
   struct MCDCNode {
-    int InCount = 0;
-    int Width;
+    int InCount = 0; /// Reference count; temporary use
+    int Width;       /// Number of paths (>= 1)
     struct {
-      int ID;
-      int Idx;
+      int Idx; /// Index in TestVectors bitmap
+      int ID;  /// Final Decision if ID<0, or NextID
     } Conds[2];
   };
 
@@ -578,6 +579,11 @@ class MCDCTVIdxBuilder {
                              unsigned  // ID1 for True
                              >;
 
+  /// Assign Idx
+  /// \param Fetcher Function to fetch NodeIDs.
+  ///        returns {size,0,0} with TellSize=ture
+  ///        returns {ID1,TrueID1,FalseID1} as the value
+  ///        returns {0,0,0} as the terminator
   MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher);
 };
 
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 5eb78f7a78571..cafb36c19c27f 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -266,25 +266,32 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
 
   unsigned Ord = 0;
   while (!Q.empty()) {
-    int ID = *Q.begin();
-    Q.erase(Q.begin());
+    auto IID = Q.begin();
+    int ID = *IID;
+    Q.erase(IID);
     auto &Node = Nodes[ID];
     assert(Node.Width > 0);
 
     for (unsigned I = 0; I < 2; ++I) {
       int NextID = Node.Conds[I].ID;
-      assert(NextID != 0);
+      assert(NextID != 0 && "NextID should not point to the top");
       if (NextID < 0) {
+        // Decision
         Decisions.emplace_back(-Node.Width, Ord++, ID, I);
         assert(Ord == Decisions.size());
         continue;
       }
 
+      // Inter Node
       auto &NextNode = Nodes[NextID];
       assert(NextNode.InCount > 0);
       assert(Node.Conds[I].Idx == INT_MIN);
+
+      // Assign Idx
       Node.Conds[I].Idx = NextNode.Width;
       NextNode.Width += Node.Width;
+
+      // Ready if all incomings are processed.
       if (--NextNode.InCount == 0)
         Q.push_back(NextID);
     }
@@ -292,7 +299,7 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
 
   std::sort(Decisions.begin(), Decisions.end());
 
-  // Assign TestVector Index
+  // Assign TestVector Indices in Decision Nodes
   unsigned CurIdx = 0;
   for (auto [NegWidth, Ord, ID, C] : Decisions) {
     int Width = -NegWidth;
@@ -313,6 +320,7 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
 
 namespace {
 
+/// Returns the fetcher to return {ID1,TrueID1,FalseID1} from Branches
 class BranchProvider {
   using NodeIDs = MCDCTVIdxBuilder::NodeIDs;
   ArrayRef<const CounterMappingRegion *> Branches;
@@ -368,7 +376,7 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
   MCDCRecord::TestVectors ExecVectors;
 
 #ifndef NDEBUG
-  DenseSet<unsigned> TVIDs;
+  DenseSet<unsigned> TVIdxs;
 #endif
 
 public:
@@ -384,10 +392,7 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
 private:
   void recordTestVector(MCDCRecord::TestVector &TV, int TVIdx, unsigned Index,
                         MCDCRecord::CondState Result) {
-#ifndef NDEBUG
-    assert(!TVIDs.contains(TVIdx));
-    TVIDs.insert(TVIdx);
-#endif
+    assert(TVIdxs.insert(TVIdx).second && "Duplicate TVIdx");
 
     if (!Bitmap[BitmapIdx + Index])
       return;
@@ -429,11 +434,12 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
   /// vector at the corresponding index was executed during a test run.
   void findExecutedTestVectors() {
     // Walk the binary decision diagram to enumerate all possible test vectors.
-    // We start at the root node (ID == 1) with all values being DontCare.
+    // We start at the root node (ID == 0) with all values being DontCare.
+    // `TVIdx` starts with 0 and is in the traversal.
     // `Index` encodes the bitmask of true values and is initially 0.
     MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
     buildTestVector(TV, 0, 0, 0);
-    assert(TVIDs.size() == NumTestVectors);
+    assert(TVIdxs.size() == NumTestVectors && "TVIdxs wasn't fulfilled");
   }
 
   // Find an independence pair for each condition:

>From 1f0f3fc963fdd8b4e637a45f362c49c8e907ae4b Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 12 Feb 2024 18:10:18 +0900
Subject: [PATCH 06/33] Reorganize TVIdxBuilder

* Split out `Indices[ID][Cond]`
* Let `Nodes` debug-only.
* Introduce `Offset`
* Introduce `HardMaxTVs`
---
 .../ProfileData/Coverage/CoverageMapping.h    | 45 ++++++++----
 .../ProfileData/Coverage/CoverageMapping.cpp  | 71 ++++++++++++-------
 2 files changed, 74 insertions(+), 42 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 7341b41aed63d..bafb1ce2ce5e0 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -558,33 +558,48 @@ struct MCDCRecord {
   }
 };
 
-/// Compute Conds[].Idx from Branch-like structure
+/// Compute Indices from Branch-like structure
 class MCDCTVIdxBuilder {
 public:
   struct MCDCNode {
     int InCount = 0; /// Reference count; temporary use
-    int Width;       /// Number of paths (>= 1)
-    struct {
-      int Idx; /// Index in TestVectors bitmap
-      int ID;  /// Final Decision if ID<0, or NextID
-    } Conds[2];
+    int Width;       /// Number of accumulated paths (>= 1)
+    std::array<int, 2> NextIDs;
   };
 
-  SmallVector<MCDCNode> Nodes;
-  unsigned NumTestVectors;
+#ifndef NDEBUG
+  /// This is no longer needed after the assignment.
+  /// It may be used in assert() for reconfirmation.
+  SmallVector<MCDCNode> SavedNodes;
+#endif
 
-public:
-  using NodeIDs = std::tuple<unsigned, // ID1 (ends with 0)
-                             unsigned, // ID1 for False
-                             unsigned  // ID1 for True
-                             >;
+  /// Output: Index for TestVectors bitmap
+  SmallVector<std::array<int, 2>> Indices;
+
+  /// Output: The number of test vectors.
+  /// Error with HardMaxTVs if the number has exploded.
+  int NumTestVectors;
 
-  /// Assign Idx
+  /// Hard limit of test vectors
+  static constexpr auto HardMaxTVs =
+      std::numeric_limits<decltype(NumTestVectors)>::max();
+
+public:
+  /// Inputs: to gather MCDCBranch-like ID to construct the BDD.
+  using NodeIDs =
+      std::tuple<CounterMappingRegion::MCDCConditionID, // ID1 (ends with 0)
+                 CounterMappingRegion::MCDCConditionID, // ID1 for False
+                 CounterMappingRegion::MCDCConditionID  // ID1 for True
+                 >;
+
+  /// Calculate and assign Indices
   /// \param Fetcher Function to fetch NodeIDs.
   ///        returns {size,0,0} with TellSize=ture
   ///        returns {ID1,TrueID1,FalseID1} as the value
   ///        returns {0,0,0} as the terminator
-  MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher);
+  /// \param Offset Offset of index to final decisions.
+  MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher,
+                   int Offset = 0);
 };
 
 /// A Counter mapping context is used to connect the counters, expressions
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index cafb36c19c27f..83932b9b6317c 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -224,10 +224,12 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
 }
 
 MCDCTVIdxBuilder::MCDCTVIdxBuilder(
-    std::function<NodeIDs(bool TellSize)> Fetcher) {
-  // Build Nodes and set up each InCount
+    std::function<NodeIDs(bool TellSize)> Fetcher, int Offset) {
+  // Construct Nodes and set up each InCount
   int MaxID = -1;
-  Nodes.resize(std::get<0>(Fetcher(true)));
+  auto N = std::get<0>(Fetcher(true));
+  SmallVector<MCDCNode> Nodes(N);
+  Indices.resize(N);
   while (true) {
     auto [ID1, FalseID1, TrueID1] = Fetcher(false);
     if (ID1 == 0)
@@ -235,13 +237,13 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
     int ID = ID1 - 1;
     MaxID = std::max(MaxID, ID);
     auto &Node = Nodes[ID];
-    Node.Conds[0].ID = FalseID1 - 1;
-    Node.Conds[1].ID = TrueID1 - 1;
+    Node.NextIDs[0] = FalseID1 - 1;
+    Node.NextIDs[1] = TrueID1 - 1;
     for (unsigned I = 0; I < 2; ++I) {
 #ifndef NDEBUG
-      Node.Conds[I].Idx = INT_MIN;
+      Indices[ID][I] = INT_MIN;
 #endif
-      int NextID = Node.Conds[I].ID;
+      auto NextID = Node.NextIDs[I];
       if (NextID >= 0)
         ++Nodes[NextID].InCount;
     }
@@ -273,7 +275,7 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
     assert(Node.Width > 0);
 
     for (unsigned I = 0; I < 2; ++I) {
-      int NextID = Node.Conds[I].ID;
+      auto NextID = Node.NextIDs[I];
       assert(NextID != 0 && "NextID should not point to the top");
       if (NextID < 0) {
         // Decision
@@ -285,13 +287,19 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
       // Inter Node
       auto &NextNode = Nodes[NextID];
       assert(NextNode.InCount > 0);
-      assert(Node.Conds[I].Idx == INT_MIN);
 
       // Assign Idx
-      Node.Conds[I].Idx = NextNode.Width;
-      NextNode.Width += Node.Width;
+      assert(Indices[ID][I] == INT_MIN);
+      Indices[ID][I] = NextNode.Width;
+      auto NextWidth = int64_t(NextNode.Width) + Node.Width;
+      if (NextWidth > HardMaxTVs) {
+        NumTestVectors = HardMaxTVs; // Overflow
+        return;
+      }
+      NextNode.Width = NextWidth;
 
       // Ready if all incomings are processed.
+      // Or NextNode.Width hasn't been confirmed yet.
       if (--NextNode.InCount == 0)
         Q.push_back(NextID);
     }
@@ -300,21 +308,28 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
   std::sort(Decisions.begin(), Decisions.end());
 
   // Assign TestVector Indices in Decision Nodes
-  unsigned CurIdx = 0;
+  int64_t CurIdx = 0;
   for (auto [NegWidth, Ord, ID, C] : Decisions) {
     int Width = -NegWidth;
     assert(Nodes[ID].Width == Width);
-    assert(Nodes[ID].Conds[C].Idx == INT_MIN);
-    assert(Nodes[ID].Conds[C].ID < 0);
-    Nodes[ID].Conds[C].Idx = CurIdx;
+    assert(Nodes[ID].NextIDs[C] < 0);
+    assert(Indices[ID][C] == INT_MIN);
+    Indices[ID][C] = Offset + CurIdx;
     CurIdx += Width;
+    if (CurIdx > HardMaxTVs) {
+      NumTestVectors = HardMaxTVs; // Overflow
+      return;
+    }
   }
+
+  assert(CurIdx < HardMaxTVs);
   NumTestVectors = CurIdx;
 
 #ifndef NDEBUG
-  for (const auto &Node : Nodes)
-    for (const auto &Cond : Node.Conds)
-      assert(Cond.Idx != INT_MIN);
+  for (const auto &Idxs : Indices)
+    for (auto Idx : Idxs)
+      assert(Idx != INT_MIN);
+  SavedNodes = std::move(Nodes);
 #endif
 }
 
@@ -363,7 +378,7 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
   unsigned BitmapIdx;
 
   /// Mapping of a condition ID to its corresponding branch region.
-  llvm::DenseMap<unsigned, const CounterMappingRegion *> Map;
+  llvm::DenseMap<int, std::array<int, 2>> NextIDsMap;
 
   /// Vector used to track whether a condition is constant folded.
   MCDCRecord::BoolVector Folded;
@@ -410,19 +425,19 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
   // the truth table.
   void buildTestVector(MCDCRecord::TestVector &TV, int ID, int TVIdx,
                        unsigned Index) {
-    const auto &Node = Nodes[ID];
+    const auto &NextIDs = NextIDsMap[ID];
 
     for (unsigned I = 0; I < 2; ++I) {
       auto MCDCCond = (I ? MCDCRecord::MCDC_True : MCDCRecord::MCDC_False);
-      const auto &Cond = Node.Conds[I];
-      auto NextID = Cond.ID;
+      auto NextID = NextIDs[I];
+      assert(NextID == SavedNodes[ID].NextIDs[I]);
       Index |= I << ID;
       TV[ID] = MCDCCond;
       if (NextID >= 0) {
-        buildTestVector(TV, NextID, TVIdx + Cond.Idx, Index);
+        buildTestVector(TV, NextID, TVIdx + Indices[ID][I], Index);
       } else {
-        assert(TVIdx < Node.Width);
-        recordTestVector(TV, Cond.Idx + TVIdx, Index, MCDCCond);
+        assert(TVIdx < SavedNodes[ID].Width);
+        recordTestVector(TV, Indices[ID][I] + TVIdx, Index, MCDCCond);
       }
     }
 
@@ -439,7 +454,8 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
     // `Index` encodes the bitmask of true values and is initially 0.
     MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
     buildTestVector(TV, 0, 0, 0);
-    assert(TVIdxs.size() == NumTestVectors && "TVIdxs wasn't fulfilled");
+    assert(TVIdxs.size() == unsigned(NumTestVectors) &&
+           "TVIdxs wasn't fulfilled");
   }
 
   // Find an independence pair for each condition:
@@ -499,7 +515,8 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
     // - Record whether the condition is constant folded so that we exclude it
     //   from being measured.
     for (const auto *B : Branches) {
-      Map[B->MCDCParams.ID] = B;
+      NextIDsMap[B->MCDCParams.ID - 1] = {int(B->MCDCParams.FalseID) - 1,
+                                          int(B->MCDCParams.TrueID) - 1};
       PosToID[I] = B->MCDCParams.ID - 1;
       CondLoc[I] = B->startLoc();
       Folded[I++] = (B->Count.isZero() && B->FalseCount.isZero());

>From e3de6478e296c7dca9244d70fd8f5063232c32ef Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 15 Feb 2024 20:19:53 +0900
Subject: [PATCH 07/33] [CoverageMapping] Refactor `mcdc::TVIdxBuilder`

* Sink `TVIdxBuilder` into `mcdc::`.
* The ctor accepts `SmallVector<ConditionIDs>` indexed by `ID`.
* `class NextIDsBuilder` provides `NextIDs` as`SmallVector<ConditionIDs>`,
  for `TVIdxBuilder` to use it before `MCDCRecordProcessor()`.
  It was `BranchParamsMap` or `Map` as `DenseMap<Branch>`.
* `NodeIDs` and `Fetcher` function are deprecated.
---
 .../ProfileData/Coverage/CoverageMapping.h    | 22 ++----
 .../ProfileData/Coverage/CoverageMapping.cpp  | 72 ++++++++-----------
 2 files changed, 36 insertions(+), 58 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index cb3b260973e9f..4ac1d88f9206d 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -551,13 +551,14 @@ struct MCDCRecord {
   }
 };
 
+namespace mcdc {
 /// Compute Indices from Branch-like structure
-class MCDCTVIdxBuilder {
+class TVIdxBuilder {
 public:
   struct MCDCNode {
     int InCount = 0; /// Reference count; temporary use
     int Width;       /// Number of accumulated paths (>= 1)
-    std::array<int, 2> NextIDs;
+    ConditionIDs NextIDs;
   };
 
 #ifndef NDEBUG
@@ -566,7 +567,7 @@ class MCDCTVIdxBuilder {
   SmallVector<MCDCNode> SavedNodes;
 #endif
 
-  /// Output: Index for TestVectors bitmap
+  /// Output: Index for TestVectors bitmap (These are not CondIDs)
   SmallVector<std::array<int, 2>> Indices;
 
   /// Output: The number of test vectors.
@@ -578,21 +579,12 @@ class MCDCTVIdxBuilder {
       std::numeric_limits<decltype(NumTestVectors)>::max();
 
 public:
-  /// Inputs: to gather MCDCBranch-like ID to construct the BDD.
-  using NodeIDs = std::tuple<mcdc::ConditionID, // ID (ends with -1)
-                             mcdc::ConditionID, // ID for False
-                             mcdc::ConditionID  // ID for True
-                             >;
-
   /// Calculate and assign Indices
-  /// \param Fetcher Function to fetch NodeIDs.
-  ///        returns {size,0,0} with TellSize=ture
-  ///        returns {ID1,TrueID1,FalseID1} as the value
-  ///        returns {0,0,0} as the terminator
+  /// \param NextIDs The list of {FalseID, TrueID} indexed by ID
   /// \param Offset Offset of index to final decisions.
-  MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher,
-                   int Offset = 0);
+  TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs, int Offset = 0);
 };
+} // namespace mcdc
 
 /// A Counter mapping context is used to connect the counters, expressions
 /// and the obtained counter values.
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 6896603debf7f..8e6205c4b6166 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -223,34 +223,24 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
   return LastPoppedValue;
 }
 
-MCDCTVIdxBuilder::MCDCTVIdxBuilder(
-    std::function<NodeIDs(bool TellSize)> Fetcher, int Offset) {
+mcdc::TVIdxBuilder::TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs,
+                                 int Offset)
+    : Indices(NextIDs.size()) {
   // Construct Nodes and set up each InCount
-  mcdc::ConditionID MaxID = -1;
-  auto N = std::get<0>(Fetcher(true));
+  auto N = NextIDs.size();
   SmallVector<MCDCNode> Nodes(N);
-  Indices.resize(N);
-  while (true) {
-    auto [ID, FalseID, TrueID] = Fetcher(false);
-    if (ID < 0)
-      break;
-    MaxID = std::max(MaxID, ID);
-    auto &Node = Nodes[ID];
-    Node.NextIDs[0] = FalseID;
-    Node.NextIDs[1] = TrueID;
-    for (unsigned I = 0; I < 2; ++I) {
+  for (unsigned ID = 0; ID < N; ++ID) {
+    for (unsigned C = 0; C < 2; ++C) {
 #ifndef NDEBUG
-      Indices[ID][I] = INT_MIN;
+      Indices[ID][C] = INT_MIN;
 #endif
-      auto NextID = Node.NextIDs[I];
+      auto NextID = NextIDs[ID][C];
+      Nodes[ID].NextIDs[C] = NextID;
       if (NextID >= 0)
         ++Nodes[NextID].InCount;
     }
   }
 
-  if (MaxID < 0)
-    return;
-
   // Sort key ordered by <-Width, Ord>
   SmallVector<std::tuple<int,      /// -Width
                          unsigned, /// Ord
@@ -334,29 +324,29 @@ MCDCTVIdxBuilder::MCDCTVIdxBuilder(
 
 namespace {
 
-/// Returns the fetcher to return {ID1,TrueID1,FalseID1} from Branches
-class BranchProvider {
-  using NodeIDs = MCDCTVIdxBuilder::NodeIDs;
-  ArrayRef<const CounterMappingRegion *> Branches;
-  unsigned BranchIdx = 0;
+/// Construct this->NextIDs with Branches for TVIdxBuilder to use it
+/// before MCDCRecordProcessor().
+class NextIDsBuilder {
+protected:
+  SmallVector<mcdc::ConditionIDs> NextIDs;
 
 public:
-  BranchProvider(ArrayRef<const CounterMappingRegion *> Branches)
-      : Branches(Branches) {}
-
-  std::function<NodeIDs(bool)> getFetcher() {
-    return [this](bool TellSize) {
-      if (TellSize)
-        return NodeIDs(Branches.size(), 0, 0);
-      if (BranchIdx >= Branches.size())
-        return NodeIDs(-1, 0, 0);
-      const auto &B = Branches[BranchIdx++]->getBranchParams();
-      return NodeIDs(B.ID, B.Conds[false], B.Conds[true]);
-    };
+  NextIDsBuilder(const ArrayRef<const CounterMappingRegion *> Branches)
+      : NextIDs(Branches.size()) {
+#ifndef NDEBUG
+    DenseSet<mcdc::ConditionID> SeenIDs;
+#endif
+    for (const auto *Branch : Branches) {
+      const auto &BranchParams = Branch->getBranchParams();
+      assert(BranchParams.ID >= 0 && "CondID isn't set");
+      assert(SeenIDs.insert(BranchParams.ID).second && "Duplicate CondID");
+      NextIDs[BranchParams.ID] = BranchParams.Conds;
+    }
+    assert(SeenIDs.size() == Branches.size());
   }
 };
 
-class MCDCRecordProcessor : MCDCTVIdxBuilder {
+class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
   /// A bitmap representing the executed test vectors for a boolean expression.
   /// Each index of the bitmap corresponds to a possible test vector. An index
   /// with a bit value of '1' indicates that the corresponding Test Vector
@@ -376,9 +366,6 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
 
   unsigned BitmapIdx;
 
-  /// Mapping of a condition ID to its corresponding branch params.
-  llvm::DenseMap<mcdc::ConditionID, mcdc::ConditionIDs> NextIDsMap;
-
   /// Vector used to track whether a condition is constant folded.
   MCDCRecord::BoolVector Folded;
 
@@ -397,7 +384,7 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
   MCDCRecordProcessor(const BitVector &Bitmap,
                       const CounterMappingRegion &Region,
                       ArrayRef<const CounterMappingRegion *> Branches)
-      : MCDCTVIdxBuilder(BranchProvider(Branches).getFetcher()), Bitmap(Bitmap),
+      : NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
         Region(Region), DecisionParams(Region.getDecisionParams()),
         Branches(Branches), NumConditions(DecisionParams.NumConditions),
         BitmapIdx(DecisionParams.BitmapIdx * CHAR_BIT),
@@ -416,7 +403,7 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
       static_assert(MCDCRecord::MCDC_True == 1);
       Index |= MCDCCond << ID;
       TV[ID] = MCDCCond;
-      auto NextID = NextIDsMap[ID][MCDCCond];
+      auto NextID = NextIDs[ID][MCDCCond];
       auto NextTVIdx = TVIdx + Indices[ID][MCDCCond];
       assert(NextID == SavedNodes[ID].NextIDs[MCDCCond]);
       if (NextID >= 0) {
@@ -513,7 +500,6 @@ class MCDCRecordProcessor : MCDCTVIdxBuilder {
     //   from being measured.
     for (const auto *B : Branches) {
       const auto &BranchParams = B->getBranchParams();
-      NextIDsMap[BranchParams.ID] = BranchParams.Conds;
       PosToID[I] = BranchParams.ID;
       CondLoc[I] = B->startLoc();
       Folded[I++] = (B->Count.isZero() && B->FalseCount.isZero());

>From 753d0ad692c56b81d471d4c8282bb41432fcd815 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 15 Feb 2024 22:18:19 +0900
Subject: [PATCH 08/33] remove <functional>

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

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 4ac1d88f9206d..c34c6f70de6b3 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -33,7 +33,6 @@
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstdint>
-#include <functional>
 #include <iterator>
 #include <memory>
 #include <sstream>

>From 17cbac7f99d2b800dc008d3413886495d03531d0 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 21 Feb 2024 09:02:02 +0900
Subject: [PATCH 09/33] Update comments.

---
 .../llvm/ProfileData/Coverage/CoverageMapping.h  | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index c34c6f70de6b3..b39f262c3d976 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -551,7 +551,20 @@ struct MCDCRecord {
 };
 
 namespace mcdc {
-/// Compute Indices from Branch-like structure
+/// Compute TestVector Indices "TVIdx" from the Conds graph.
+///
+/// Clang CodeGen handles the bitmap index based on TVIdx.
+/// llvm-cov reconstructs conditions from TVIdx.
+///
+/// For each leaf "The final decision",
+/// - TVIdx should be unique.
+/// - TVIdx has the Width.
+///   - The width represents the number of possible paths.
+///   - The minimum width is 1 "deterministic".
+/// - The order of leaves are sorted by Width DESC. It expects
+///   latter TVIdx(s) (with Width=1) could be pruned and altered to
+///   other simple branch conditions.
+///
 class TVIdxBuilder {
 public:
   struct MCDCNode {
@@ -580,6 +593,7 @@ class TVIdxBuilder {
 public:
   /// Calculate and assign Indices
   /// \param NextIDs The list of {FalseID, TrueID} indexed by ID
+  ///        The first element [0] should be the root node.
   /// \param Offset Offset of index to final decisions.
   TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs, int Offset = 0);
 };

>From 1a4ffa7f2dc2b6ed1af1ef128865c29bf9cfc752 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 21 Feb 2024 09:02:02 +0900
Subject: [PATCH 10/33] Add unittest

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

diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index 425b3d10510af..c5b7c26bef9a7 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Testing/Support/SupportHelpers.h"
 #include "gtest/gtest.h"
 
+#include <map>
 #include <ostream>
 #include <utility>
 
@@ -1074,4 +1075,59 @@ TEST(CoverageMappingTest, filename_compilation_dir) {
   }
 }
 
+TEST(CoverageMappingTest, TVIdxBuilder) {
+  // ((n0 && n3) || (n2 && n4) || (n1 && n5))
+  static const std::array<mcdc::ConditionIDs, 6> Branches = {{
+      {2, 3},
+      {-1, 5},
+      {1, 4},
+      {2, -1},
+      {1, -1},
+      {-1, -1},
+  }};
+  int Offset = 1000;
+  auto TheBuilder = mcdc::TVIdxBuilder(
+      SmallVector<mcdc::ConditionIDs>(ArrayRef(Branches)), Offset);
+  ASSERT_TRUE(TheBuilder.NumTestVectors < TheBuilder.HardMaxTVs);
+  ASSERT_EQ(TheBuilder.Indices.size(), 6u);
+  ASSERT_EQ(TheBuilder.NumTestVectors, 15);
+
+  std::map<int, int> Decisions;
+  for (unsigned I = 0; I < TheBuilder.Indices.size(); ++I) {
+    struct Rec {
+      int Width;
+      std::array<int, 2> Indices;
+    };
+    static const std::array<Rec, 6> IndicesRefs = {{
+        {1, {0, 0}},
+        {4, {1000, 0}},
+        {2, {0, 0}},
+        {1, {1, 1014}},
+        {2, {2, 1012}},
+        {4, {1004, 1008}},
+    }};
+    ASSERT_EQ(TheBuilder.Indices[I], IndicesRefs[I].Indices);
+
+#ifndef NDEBUG
+    const auto &Node = TheBuilder.SavedNodes[I];
+    ASSERT_EQ(Node.Width, IndicesRefs[I].Width);
+    for (int C = 0; C < 2; ++C) {
+      auto Index = TheBuilder.Indices[I][C];
+      if (Node.NextIDs[C] < 0)
+        ASSERT_TRUE(Decisions.insert({Index, Node.Width}).second);
+    }
+#endif
+  }
+
+#ifndef NDEBUG
+  int NextIdx = Offset;
+  for (const auto [Index, Width] : Decisions) {
+    ASSERT_EQ(Index, NextIdx);
+    NextIdx += Width;
+  }
+  // The sum of Width(s) is NumTVs.
+  ASSERT_EQ(NextIdx, Offset + TheBuilder.NumTestVectors);
+#endif
+}
+
 } // end anonymous namespace

>From b5ecfcc22cffdd560dc5b6a050889b6c6deacbdb Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 16 Feb 2024 00:09:41 +0900
Subject: [PATCH 11/33] [MC/DC][Coverage] Loosen the limit of NumConds from 6

---
 clang/lib/CodeGen/CodeGenPGO.cpp              |  61 +++++-----
 clang/lib/CodeGen/CoverageMappingGen.cpp      | 115 +++++++++++++++++-
 clang/lib/CodeGen/MCDCState.h                 |  18 ++-
 .../CoverageMapping/branch-constfolded.cpp    |  34 +++---
 clang/test/CoverageMapping/logical.cpp        |   8 +-
 clang/test/CoverageMapping/mcdc-class.cpp     |   4 +-
 .../CoverageMapping/mcdc-error-conditions.cpp |  86 ++++++++++++-
 .../mcdc-logical-scalar-ids.cpp               |  30 ++---
 .../mcdc-logical-stmt-ids-all.cpp             |  32 ++---
 .../CoverageMapping/mcdc-logical-stmt-ids.cpp |  30 ++---
 clang/test/Profile/c-mcdc-logicalop-ternary.c |   6 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  |  32 ++---
 .../llvm-cov/Inputs/mcdc-const-folding.o      | Bin 34504 -> 34528 bytes
 .../Inputs/mcdc-const-folding.proftext        |  36 +++---
 llvm/test/tools/llvm-cov/Inputs/mcdc-const.o  | Bin 5112 -> 5112 bytes
 .../tools/llvm-cov/Inputs/mcdc-const.proftext |   6 +-
 .../test/tools/llvm-cov/Inputs/mcdc-general.o | Bin 6200 -> 6232 bytes
 .../llvm-cov/Inputs/mcdc-general.proftext     |  11 +-
 llvm/test/tools/llvm-cov/Inputs/mcdc-macro.o  | Bin 6424 -> 6480 bytes
 .../tools/llvm-cov/Inputs/mcdc-macro.proftext |  15 +--
 llvm/test/tools/llvm-cov/Inputs/mcdc-maxbs.o  | Bin 4632 -> 4112 bytes
 llvm/test/tools/llvm-cov/mcdc-maxbs.test      |   2 +-
 .../ProfileData/CoverageMappingTest.cpp       |   2 +-
 23 files changed, 348 insertions(+), 180 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 48c5e68a3b7ba..b004bf45fa75d 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -163,8 +163,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
   PGOHash Hash;
   /// The map of statements to counters.
   llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
-  /// The next bitmap byte index to assign.
-  unsigned NextMCDCBitmapIdx;
+  /// The state of MC/DC Coverage in this function.
   MCDC::State &MCDCState;
   /// Maximum number of supported MC/DC conditions in a boolean expression.
   unsigned MCDCMaxCond;
@@ -178,7 +177,7 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
                     MCDC::State &MCDCState, unsigned MCDCMaxCond,
                     DiagnosticsEngine &Diag)
       : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
-        NextMCDCBitmapIdx(0), MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
+        MCDCState(MCDCState), MCDCMaxCond(MCDCMaxCond),
         ProfileVersion(ProfileVersion), Diag(Diag) {}
 
   // Blocks and lambdas are handled as separate functions, so we need not
@@ -306,11 +305,8 @@ struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
             return false;
           }
 
-          // Otherwise, allocate the number of bytes required for the bitmap
-          // based on the number of conditions. Must be at least 1-byte long.
-          MCDCState.BitmapMap[BinOp] = NextMCDCBitmapIdx;
-          unsigned SizeInBits = std::max<unsigned>(1L << NumCond, CHAR_BIT);
-          NextMCDCBitmapIdx += SizeInBits / CHAR_BIT;
+          // Otherwise, allocate the Decision.
+          MCDCState.BitmapMap[BinOp].BitmapIdx = 0;
         }
         return true;
       }
@@ -983,7 +979,7 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
   // for most embedded applications. Setting a maximum value prevents the
   // bitmap footprint from growing too large without the user's knowledge. In
   // the future, this value could be adjusted with a command-line option.
-  unsigned MCDCMaxConditions = (CGM.getCodeGenOpts().MCDCCoverage) ? 6 : 0;
+  unsigned MCDCMaxConditions = (CGM.getCodeGenOpts().MCDCCoverage) ? 32767 : 0;
 
   RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
   RegionMCDCState.reset(new MCDC::State);
@@ -999,7 +995,6 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
     Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
   assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
   NumRegionCounters = Walker.NextCounter;
-  RegionMCDCState->BitmapBytes = Walker.NextMCDCBitmapIdx;
   FunctionHash = Walker.Hash.finalize();
 }
 
@@ -1124,9 +1119,11 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) {
   // Emit intrinsic representing MCDC bitmap parameters at function entry.
   // This is used by the instrumentation pass, but it isn't actually lowered to
   // anything.
-  llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
-                          Builder.getInt64(FunctionHash),
-                          Builder.getInt32(RegionMCDCState->BitmapBytes)};
+  llvm::Value *Args[3] = {
+      llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
+      Builder.getInt64(FunctionHash),
+      Builder.getInt32(llvm::alignTo(RegionMCDCState->BitmapBits, CHAR_BIT) /
+                       CHAR_BIT)};
   Builder.CreateCall(
       CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
 }
@@ -1139,12 +1136,9 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
 
   S = S->IgnoreParens();
 
-  auto ExprMCDCBitmapMapIterator = RegionMCDCState->BitmapMap.find(S);
-  if (ExprMCDCBitmapMapIterator == RegionMCDCState->BitmapMap.end())
+  if (!RegionMCDCState->BitmapMap.contains(S))
     return;
 
-  // Extract the ID of the global bitmap associated with this expression.
-  unsigned MCDCTestVectorBitmapID = ExprMCDCBitmapMapIterator->second;
   auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
 
   // Emit intrinsic responsible for updating the global bitmap corresponding to
@@ -1154,9 +1148,8 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
   // index represents an executed test vector.
   llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
                           Builder.getInt64(FunctionHash),
-                          Builder.getInt32(RegionMCDCState->BitmapBytes),
-                          Builder.getInt32(MCDCTestVectorBitmapID),
-                          MCDCCondBitmapAddr.getPointer()};
+                          Builder.getInt32(RegionMCDCState->BitmapBits),
+                          Builder.getInt32(0), MCDCCondBitmapAddr.getPointer()};
   Builder.CreateCall(
       CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args);
 }
@@ -1195,21 +1188,23 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
     return;
 
   // Extract the ID of the condition we are setting in the bitmap.
-  auto CondID = ExprMCDCConditionIDMapIterator->second;
-  assert(CondID >= 0 && "Condition has no ID!");
+  const auto &Branch = ExprMCDCConditionIDMapIterator->second;
+  assert(Branch.ID >= 0 && "Condition has no ID!");
 
-  auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
+  // Cancel the emission if the Decision is erased after the allocation.
+  const auto DecisionIter =
+      RegionMCDCState->BitmapMap.find(Branch.DecisionStmt);
+  if (DecisionIter == RegionMCDCState->BitmapMap.end())
+    return;
 
-  // Emit intrinsic that updates a dedicated temporary value on the stack after
-  // a condition is evaluated. After the set of conditions has been updated,
-  // the resulting value is used to update the boolean expression's bitmap.
-  llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
-                          Builder.getInt64(FunctionHash),
-                          Builder.getInt32(CondID),
-                          MCDCCondBitmapAddr.getPointer(), Val};
-  Builder.CreateCall(
-      CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update),
-      Args);
+  const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID];
+
+  auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr,
+                                   "mcdc." + Twine(Branch.ID + 1) + ".cur");
+  auto *NewTV = Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[true]));
+  NewTV = Builder.CreateSelect(
+      Val, NewTV, Builder.CreateAdd(CurTV, Builder.getInt32(TVIdxs[false])));
+  Builder.CreateStore(NewTV, MCDCCondBitmapAddr);
 }
 
 void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index c10d85ea89ee6..ec51023a2d205 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -182,6 +182,16 @@ class SourceMappingRegion {
 
   bool isBranch() const { return FalseCount.has_value(); }
 
+  bool isMCDCBranch() const {
+    const auto *BranchParams = std::get_if<mcdc::BranchParameters>(&MCDCParams);
+    assert(!BranchParams || BranchParams->ID >= 0);
+    return BranchParams;
+  }
+
+  const auto &getMCDCBranchParams() const {
+    return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams);
+  }
+
   bool isMCDCDecision() const {
     const auto *DecisionParams =
         std::get_if<mcdc::DecisionParameters>(&MCDCParams);
@@ -194,6 +204,8 @@ class SourceMappingRegion {
   }
 
   const mcdc::Parameters &getMCDCParams() const { return MCDCParams; }
+
+  void resetMCDCParams() { MCDCParams = mcdc::Parameters(); }
 };
 
 /// Spelling locations for the start and end of a source region.
@@ -684,7 +696,9 @@ struct MCDCCoverageBuilder {
 
   llvm::SmallVector<mcdc::ConditionIDs> DecisionStack;
   MCDC::State &MCDCState;
-  llvm::DenseMap<const Stmt *, mcdc::ConditionID> &CondIDs;
+  llvm::DenseMap<const Stmt *, MCDC::State::Branch> &CondIDs;
+  const Stmt *DecisionStmt = nullptr;
+  llvm::DenseMap<mcdc::ConditionID, mcdc::ConditionIDs> cache;
   mcdc::ConditionID NextID = 0;
   bool NotMapped = false;
 
@@ -714,7 +728,7 @@ struct MCDCCoverageBuilder {
 
   /// Set the given condition's ID.
   void setCondID(const Expr *Cond, mcdc::ConditionID ID) {
-    CondIDs[CodeGenFunction::stripCond(Cond)] = ID;
+    CondIDs[CodeGenFunction::stripCond(Cond)] = {ID, DecisionStmt};
   }
 
   /// Return the ID of a given condition.
@@ -723,7 +737,15 @@ struct MCDCCoverageBuilder {
     if (I == CondIDs.end())
       return -1;
     else
-      return I->second;
+      return I->second.ID;
+  }
+
+  void ccc(const Expr *CondExpr, mcdc::ConditionIDs IDs) {
+    auto ID = getCondID(CondExpr);
+    if (ID < 0)
+      return;
+    if (!cache.contains(ID))
+      cache[ID] = IDs;
   }
 
   /// Return the LHS Decision ([0,0] if not set).
@@ -745,6 +767,12 @@ struct MCDCCoverageBuilder {
     if (NotMapped)
       return;
 
+    if (NextID == 0) {
+      cache.clear();
+      DecisionStmt = E;
+      assert(MCDCState.BitmapMap.contains(E));
+    }
+
     const mcdc::ConditionIDs &ParentDecision = DecisionStack.back();
 
     // If the operator itself has an assigned ID, this means it represents a
@@ -794,9 +822,33 @@ struct MCDCCoverageBuilder {
     // Set number of conditions and reset.
     unsigned TotalConds = NextID;
 
+    llvm::SmallVector<mcdc::ConditionIDs> R(cache.size());
+    for (auto [ID, Conds] : cache)
+      R[ID] = Conds;
+    mcdc::TVIdxBuilder xxx(R, MCDCState.BitmapBits);
+    auto NumTVs = xxx.NumTestVectors;
+    assert(MCDCState.BitmapMap.contains(E));
+    auto MaxTVs = mcdc::TVIdxBuilder::HardMaxTVs;
+    if (NumTVs == MaxTVs) {
+      auto &Diag = CGM.getDiags();
+      unsigned DiagID =
+          Diag.getCustomDiagID(DiagnosticsEngine::Warning,
+                               "unsupported MC/DC boolean expression; "
+                               "number of test vectors (%0) exceeds max (%1). "
+                               "Expression will not be covered");
+      Diag.Report(E->getBeginLoc(), DiagID) << NumTVs << MaxTVs;
+
+      MCDCState.BitmapMap[E].BitmapIdx = 0; // Mark to be erased
+    } else {
+      // Last pos
+      MCDCState.BitmapMap[E] = {MCDCState.BitmapBits += NumTVs,
+                                std::move(xxx.Indices)};
+    }
+
     // Reset ID back to beginning.
     NextID = 0;
 
+    // Return the number even if the Decision will be erased.
     return TotalConds;
   }
 };
@@ -853,7 +905,9 @@ struct CounterCoverageMappingBuilder
     return Counter::getCounter(CounterMap[S]);
   }
 
-  unsigned getRegionBitmap(const Stmt *S) { return MCDCState.BitmapMap[S]; }
+  auto getRegionBitmap(const Stmt *S) {
+    return MCDCState.BitmapMap[S].BitmapIdx;
+  }
 
   /// Push a region onto the stack.
   ///
@@ -1959,9 +2013,44 @@ struct CounterCoverageMappingBuilder
                        subtractCounters(ParentCount, TrueCount));
   }
 
+  void RewindDecision(unsigned Since) {
+#ifndef NDEBUG
+    llvm::DenseSet<mcdc::ConditionID> SeenIDs;
+#endif
+    unsigned NConds = 0;
+
+    assert(Since <= SourceRegions.size());
+    auto I = SourceRegions.begin() + Since;
+    while (I != SourceRegions.end()) {
+      if (I->isMCDCDecision()) {
+        assert(I->getMCDCDecisionParams().BitmapIdx == 0 &&
+               "It should be valid");
+        assert(NConds == 0 && "Duplicate MCDCDecision");
+        NConds = I->getMCDCDecisionParams().NumConditions;
+        assert(NConds > 0 && "Malformed MCDCDecision");
+        I = SourceRegions.erase(I);
+        continue;
+      }
+
+      if (I->isMCDCBranch()) {
+        assert(SeenIDs.insert(I->getMCDCBranchParams().ID).second &&
+               "Duplicate CondID");
+        I->resetMCDCParams();
+      }
+
+      ++I;
+    }
+
+    assert(NConds > 0 && "MCDCDecision wasn't found");
+    assert(SeenIDs.size() == NConds && "Unexpected number of MCDCBranch(es)");
+    (void)NConds;
+  }
+
   void VisitBinLAnd(const BinaryOperator *E) {
     bool IsRootNode = MCDCBuilder.isIdle();
 
+    unsigned SourceRegionsSince = SourceRegions.size();
+
     // Keep track of Binary Operator and assign MCDC condition IDs.
     MCDCBuilder.pushAndAssignIDs(E);
 
@@ -1979,6 +2068,9 @@ struct CounterCoverageMappingBuilder
     // Track RHS True/False Decision.
     const auto DecisionRHS = MCDCBuilder.back();
 
+    MCDCBuilder.ccc(E->getLHS(), DecisionLHS);
+    MCDCBuilder.ccc(E->getRHS(), DecisionRHS);
+
     // Create MCDC Decision Region if at top-level (root).
     unsigned NumConds = 0;
     if (IsRootNode && (NumConds = MCDCBuilder.getTotalConditionsAndReset(E)))
@@ -2000,6 +2092,11 @@ struct CounterCoverageMappingBuilder
     // Create Branch Region around RHS condition.
     createBranchRegion(E->getRHS(), RHSTrueCnt,
                        subtractCounters(RHSExecCnt, RHSTrueCnt), DecisionRHS);
+
+    if (IsRootNode && NumConds > 0 && getRegionBitmap(E) == 0) {
+      RewindDecision(SourceRegionsSince);
+      MCDCState.BitmapMap.erase(E);
+    }
   }
 
   // Determine whether the right side of OR operation need to be visited.
@@ -2015,6 +2112,8 @@ struct CounterCoverageMappingBuilder
   void VisitBinLOr(const BinaryOperator *E) {
     bool IsRootNode = MCDCBuilder.isIdle();
 
+    unsigned SourceRegionsSince = SourceRegions.size();
+
     // Keep track of Binary Operator and assign MCDC condition IDs.
     MCDCBuilder.pushAndAssignIDs(E);
 
@@ -2032,6 +2131,9 @@ struct CounterCoverageMappingBuilder
     // Track RHS True/False Decision.
     const auto DecisionRHS = MCDCBuilder.back();
 
+    MCDCBuilder.ccc(E->getLHS(), DecisionLHS);
+    MCDCBuilder.ccc(E->getRHS(), DecisionRHS);
+
     // Create MCDC Decision Region if at top-level (root).
     unsigned NumConds = 0;
     if (IsRootNode && (NumConds = MCDCBuilder.getTotalConditionsAndReset(E)))
@@ -2057,6 +2159,11 @@ struct CounterCoverageMappingBuilder
     // Create Branch Region around RHS condition.
     createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
                        RHSFalseCnt, DecisionRHS);
+
+    if (IsRootNode && NumConds > 0 && getRegionBitmap(E) == 0) {
+      RewindDecision(SourceRegionsSince);
+      MCDCState.BitmapMap.erase(E);
+    }
   }
 
   void VisitLambdaExpr(const LambdaExpr *LE) {
diff --git a/clang/lib/CodeGen/MCDCState.h b/clang/lib/CodeGen/MCDCState.h
index e6e39237a1b41..d1763ef23b282 100644
--- a/clang/lib/CodeGen/MCDCState.h
+++ b/clang/lib/CodeGen/MCDCState.h
@@ -26,9 +26,21 @@ using namespace llvm::coverage::mcdc;
 
 /// Per-Function MC/DC state
 struct State {
-  unsigned BitmapBytes = 0;
-  llvm::DenseMap<const Stmt *, unsigned> BitmapMap;
-  llvm::DenseMap<const Stmt *, ConditionID> CondIDMap;
+  unsigned BitmapBits = 0;
+
+  struct Decision {
+    unsigned BitmapIdx;
+    llvm::SmallVector<std::array<int, 2>> Indices;
+  };
+
+  llvm::DenseMap<const Stmt *, Decision> BitmapMap;
+
+  struct Branch {
+    ConditionID ID;
+    const Stmt *DecisionStmt;
+  };
+
+  llvm::DenseMap<const Stmt *, Branch> CondIDMap;
 };
 
 } // namespace clang::CodeGen::MCDC
diff --git a/clang/test/CoverageMapping/branch-constfolded.cpp b/clang/test/CoverageMapping/branch-constfolded.cpp
index c8755d5d752b6..1e7e32808e838 100644
--- a/clang/test/CoverageMapping/branch-constfolded.cpp
+++ b/clang/test/CoverageMapping/branch-constfolded.cpp
@@ -4,93 +4,93 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-constfolded.cpp %s | FileCheck %s -check-prefix=MCDC
 
 // CHECK-LABEL: _Z6fand_0b:
-bool fand_0(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
+bool fand_0(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
   return false && a;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #2, (#1 - #2)
 
 // CHECK-LABEL: _Z6fand_1b:
-bool fand_1(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
+bool fand_1(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
   return a && true;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1)
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
 
 // CHECK-LABEL: _Z6fand_2bb:
-bool fand_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:0, C:3
+bool fand_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3
   return false && a && b;  // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = #4, (#3 - #4)
                            // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = #2, (#1 - #2)
 
 // CHECK-LABEL: _Z6fand_3bb:
-bool fand_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:0, C:3
+bool fand_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3
   return a && true && b;   // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3)
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
                            // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = #2, (#1 - #2)
 
 // CHECK-LABEL: _Z6fand_4bb:
-bool fand_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:0, C:3
+bool fand_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3
   return a && b && false;  // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #3, (#0 - #3)
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = #4, (#3 - #4)
                            // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:25 = 0, 0
 
 // CHECK-LABEL: _Z6fand_5b:
-bool fand_5(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:0, C:2
+bool fand_5(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2
   return false && true;    // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:23 = 0, 0
 
 // CHECK-LABEL: _Z6fand_6b:
-bool fand_6(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
+bool fand_6(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
   return true && a;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = #2, (#1 - #2)
 
 // CHECK-LABEL: _Z6fand_7b:
-bool fand_7(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
+bool fand_7(bool a) {      // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
   return a && false;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = #1, (#0 - #1)
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
 
 // CHECK-LABEL: _Z5for_0b:
-bool for_0(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
+bool for_0(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
   return true || a;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#1 - #2), #2
 
 // CHECK-LABEL: _Z5for_1b:
-bool for_1(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
+bool for_1(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
   return a || false;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
 
 // CHECK-LABEL: _Z5for_2bb:
-bool for_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:0, C:3
+bool for_2(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3
   return true || a || b;   // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:19 = (#3 - #4), #4
                            // CHECK: Branch,File 0, [[@LINE-2]]:23 -> [[@LINE-2]]:24 = (#1 - #2), #2
 
 // CHECK-LABEL: _Z5for_3bb:
-bool for_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:0, C:3
+bool for_3(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:25 = M:4, C:3
   return a || false || b;  // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:20 = 0, 0
                            // CHECK: Branch,File 0, [[@LINE-2]]:24 -> [[@LINE-2]]:25 = (#1 - #2), #2
 
 // CHECK-LABEL: _Z5for_4bb:
-bool for_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:0, C:3
+bool for_4(bool a, bool b) {// MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:24 = M:4, C:3
   return a || b || true;   // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #3), #3
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:16 = (#3 - #4), #4
                            // CHECK: Branch,File 0, [[@LINE-2]]:20 -> [[@LINE-2]]:24 = 0, 0
 
 // CHECK-LABEL: _Z5for_5b:
-bool for_5(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:0, C:2
+bool for_5(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:23 = M:3, C:2
   return true || false;    // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:14 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:18 -> [[@LINE-1]]:23 = 0, 0
 
 // CHECK-LABEL: _Z5for_6b:
-bool for_6(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:0, C:2
+bool for_6(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:20 = M:3, C:2
   return false || a;       // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:15 = 0, 0
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:19 -> [[@LINE-1]]:20 = (#1 - #2), #2
 
 // CHECK-LABEL: _Z5for_7b:
-bool for_7(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:0, C:2
+bool for_7(bool a) {       // MCDC: Decision,File 0, [[@LINE+1]]:10 -> [[@LINE+1]]:19 = M:3, C:2
   return a || true;        // CHECK: Branch,File 0, [[@LINE]]:10 -> [[@LINE]]:11 = (#0 - #1), #1
 }                          // CHECK: Branch,File 0, [[@LINE-1]]:15 -> [[@LINE-1]]:19 = 0, 0
 
 // CHECK-LABEL: _Z5for_8b:
-bool for_8(bool a) {       // MCDC: Decision,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:20 = M:0, C:2
+bool for_8(bool a) {       // MCDC: Decision,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:20 = M:3, C:2
                            // CHECK: Branch,File 0, [[@LINE+2]]:7 -> [[@LINE+2]]:11 = 0, 0
                            // CHECK: Branch,File 0, [[@LINE+1]]:15 -> [[@LINE+1]]:20 = 0, 0
   if (true && false)
diff --git a/clang/test/CoverageMapping/logical.cpp b/clang/test/CoverageMapping/logical.cpp
index 7de59e1429808..2a22d6cca4518 100644
--- a/clang/test/CoverageMapping/logical.cpp
+++ b/clang/test/CoverageMapping/logical.cpp
@@ -3,22 +3,22 @@
 
 int main() {                        // CHECK: File 0, [[@LINE]]:12 -> [[@LINE+23]]:2 = #0
   bool bt = true;
-  bool bf = false;                  // MCDC: Decision,File 0, [[@LINE+1]]:12 -> [[@LINE+1]]:20 = M:0, C:2
+  bool bf = false;                  // MCDC: Decision,File 0, [[@LINE+1]]:12 -> [[@LINE+1]]:20 = M:3, C:2
   bool a = bt && bf;                // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE]]:14 = #0
                                     // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:12 -> [[@LINE-1]]:14 = #1, (#0 - #1)
                                     // CHECK-NEXT: File 0, [[@LINE-2]]:18 -> [[@LINE-2]]:20 = #1
                                     // CHECK-NEXT: Branch,File 0, [[@LINE-3]]:18 -> [[@LINE-3]]:20 = #2, (#1 - #2)
-                                    // MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:1, C:2
+                                    // MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:6, C:2
   a = bt &&                         // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
       bf;                           // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #3, (#0 - #3)
                                     // CHECK-NEXT: File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #3
                                     // CHECK-NEXT: Branch,File 0, [[@LINE-2]]:7 -> [[@LINE-2]]:9 = #4, (#3 - #4)
-                                    // MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:15 = M:2, C:2
+                                    // MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+1]]:15 = M:9, C:2
   a = bf || bt;                     // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
                                     // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = (#0 - #5), #5
                                     // CHECK-NEXT: File 0, [[@LINE-2]]:13 -> [[@LINE-2]]:15 = #5
                                     // CHECK-NEXT: Branch,File 0, [[@LINE-3]]:13 -> [[@LINE-3]]:15 = (#5 - #6), #6
-                                    // MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:3, C:2
+                                    // MCDC: Decision,File 0, [[@LINE+1]]:7 -> [[@LINE+2]]:9 = M:12, C:2
   a = bf ||                         // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:9 = #0
       bt;                           // CHECK-NEXT: Branch,File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = (#0 - #7), #7
                                     // CHECK-NEXT: File 0, [[@LINE-1]]:7 -> [[@LINE-1]]:9 = #7
diff --git a/clang/test/CoverageMapping/mcdc-class.cpp b/clang/test/CoverageMapping/mcdc-class.cpp
index dcf6123ee0fc7..7b2937830be76 100644
--- a/clang/test/CoverageMapping/mcdc-class.cpp
+++ b/clang/test/CoverageMapping/mcdc-class.cpp
@@ -23,9 +23,9 @@ Value::~Value(void) {
     bar();
 }
 
-// CHECK-LABEL:  Decision,File 0, 18:7 -> 18:31 = M:0, C:2
+// CHECK-LABEL:  Decision,File 0, 18:7 -> 18:31 = M:3, C:2
 // CHECK-NEXT:  Branch,File 0, 18:7 -> 18:17 = (#0 - #2), #2 [1,0,2]
 // CHECK:  Branch,File 0, 18:21 -> 18:31 = (#2 - #3), #3 [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 22:7 -> 22:31 = M:0, C:2
+// CHECK-LABEL:  Decision,File 0, 22:7 -> 22:31 = M:3, C:2
 // CHECK-NEXT:  Branch,File 0, 22:7 -> 22:17 = (#0 - #2), #2 [1,0,2]
 // CHECK:  Branch,File 0, 22:21 -> 22:31 = (#2 - #3), #3 [2,0,0]
diff --git a/clang/test/CoverageMapping/mcdc-error-conditions.cpp b/clang/test/CoverageMapping/mcdc-error-conditions.cpp
index d34ed69343479..d2042e576159b 100644
--- a/clang/test/CoverageMapping/mcdc-error-conditions.cpp
+++ b/clang/test/CoverageMapping/mcdc-error-conditions.cpp
@@ -1,7 +1,87 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s
 
-bool func_conditions(bool a, bool b, bool c, bool d, bool e, bool f, bool g) {
-  return a && b && c && d && e && f && g;
+// From clang-tidy/misc/MisleadingIdentifier.cpp
+bool func_conditions(unsigned CP) {
+  return (CP == 0x0590) || (CP == 0x05BE) || (CP == 0x05C0) || (CP == 0x05C3) ||
+         (CP == 0x05C6) || (0x05C8 <= CP && CP <= 0x05CF) ||
+         (0x05D0 <= CP && CP <= 0x05EA) || (0x05EB <= CP && CP <= 0x05EE) ||
+         (0x05EF <= CP && CP <= 0x05F2) || (0x05F3 <= CP && CP <= 0x05F4) ||
+         (0x05F5 <= CP && CP <= 0x05FF) || (0x07C0 <= CP && CP <= 0x07C9) ||
+         (0x07CA <= CP && CP <= 0x07EA) || (0x07F4 <= CP && CP <= 0x07F5) ||
+         (CP == 0x07FA) || (0x07FB <= CP && CP <= 0x07FC) ||
+         (0x07FE <= CP && CP <= 0x07FF) || (0x0800 <= CP && CP <= 0x0815) ||
+         (CP == 0x081A) || (CP == 0x0824) || (CP == 0x0828) ||
+         (0x082E <= CP && CP <= 0x082F) || (0x0830 <= CP && CP <= 0x083E) ||
+         (CP == 0x083F) || (0x0840 <= CP && CP <= 0x0858) ||
+         (0x085C <= CP && CP <= 0x085D) || (CP == 0x085E) || (CP == 0x085F) ||
+         (CP == 0x200F) || (CP == 0xFB1D) || (0xFB1F <= CP && CP <= 0xFB28) ||
+         (0xFB2A <= CP && CP <= 0xFB36) || (CP == 0xFB37) ||
+         (0xFB38 <= CP && CP <= 0xFB3C) || (CP == 0xFB3D) || (CP == 0xFB3E) ||
+         (CP == 0xFB3F) || (0xFB40 <= CP && CP <= 0xFB41) || (CP == 0xFB42) ||
+         (0xFB43 <= CP && CP <= 0xFB44) || (CP == 0xFB45) ||
+         (0xFB46 <= CP && CP <= 0xFB4F) || (0x10800 <= CP && CP <= 0x10805) ||
+         (0x10806 <= CP && CP <= 0x10807) || (CP == 0x10808) ||
+         (CP == 0x10809) || (0x1080A <= CP && CP <= 0x10835) ||
+         (CP == 0x10836) || (0x10837 <= CP && CP <= 0x10838) ||
+         (0x10839 <= CP && CP <= 0x1083B) || (CP == 0x1083C) ||
+         (0x1083D <= CP && CP <= 0x1083E) || (0x1083F <= CP && CP <= 0x10855) ||
+         (CP == 0x10856) || (CP == 0x10857) ||
+         (0x10858 <= CP && CP <= 0x1085F) || (0x10860 <= CP && CP <= 0x10876) ||
+         (0x10877 <= CP && CP <= 0x10878) || (0x10879 <= CP && CP <= 0x1087F) ||
+         (0x10880 <= CP && CP <= 0x1089E) || (0x1089F <= CP && CP <= 0x108A6) ||
+         (0x108A7 <= CP && CP <= 0x108AF) || (0x108B0 <= CP && CP <= 0x108DF) ||
+         (0x108E0 <= CP && CP <= 0x108F2) || (CP == 0x108F3) ||
+         (0x108F4 <= CP && CP <= 0x108F5) || (0x108F6 <= CP && CP <= 0x108FA) ||
+         (0x108FB <= CP && CP <= 0x108FF) || (0x10900 <= CP && CP <= 0x10915) ||
+         (0x10916 <= CP && CP <= 0x1091B) || (0x1091C <= CP && CP <= 0x1091E) ||
+         (0x10920 <= CP && CP <= 0x10939) || (0x1093A <= CP && CP <= 0x1093E) ||
+         (CP == 0x1093F) || (0x10940 <= CP && CP <= 0x1097F) ||
+         (0x10980 <= CP && CP <= 0x109B7) || (0x109B8 <= CP && CP <= 0x109BB) ||
+         (0x109BC <= CP && CP <= 0x109BD) || (0x109BE <= CP && CP <= 0x109BF) ||
+         (0x109C0 <= CP && CP <= 0x109CF) || (0x109D0 <= CP && CP <= 0x109D1) ||
+         (0x109D2 <= CP && CP <= 0x109FF) || (CP == 0x10A00) ||
+         (CP == 0x10A04) || (0x10A07 <= CP && CP <= 0x10A0B) ||
+         (0x10A10 <= CP && CP <= 0x10A13) || (CP == 0x10A14) ||
+         (0x10A15 <= CP && CP <= 0x10A17) || (CP == 0x10A18) ||
+         (0x10A19 <= CP && CP <= 0x10A35) || (0x10A36 <= CP && CP <= 0x10A37) ||
+         (0x10A3B <= CP && CP <= 0x10A3E) || (0x10A40 <= CP && CP <= 0x10A48) ||
+         (0x10A49 <= CP && CP <= 0x10A4F) || (0x10A50 <= CP && CP <= 0x10A58) ||
+         (0x10A59 <= CP && CP <= 0x10A5F) || (0x10A60 <= CP && CP <= 0x10A7C) ||
+         (0x10A7D <= CP && CP <= 0x10A7E) || (CP == 0x10A7F) ||
+         (0x10A80 <= CP && CP <= 0x10A9C) || (0x10A9D <= CP && CP <= 0x10A9F) ||
+         (0x10AA0 <= CP && CP <= 0x10ABF) || (0x10AC0 <= CP && CP <= 0x10AC7) ||
+         (CP == 0x10AC8) || (0x10AC9 <= CP && CP <= 0x10AE4) ||
+         (0x10AE7 <= CP && CP <= 0x10AEA) || (0x10AEB <= CP && CP <= 0x10AEF) ||
+         (0x10AF0 <= CP && CP <= 0x10AF6) || (0x10AF7 <= CP && CP <= 0x10AFF) ||
+         (0x10B00 <= CP && CP <= 0x10B35) || (0x10B36 <= CP && CP <= 0x10B38) ||
+         (0x10B40 <= CP && CP <= 0x10B55) || (0x10B56 <= CP && CP <= 0x10B57) ||
+         (0x10B58 <= CP && CP <= 0x10B5F) || (0x10B60 <= CP && CP <= 0x10B72) ||
+         (0x10B73 <= CP && CP <= 0x10B77) || (0x10B78 <= CP && CP <= 0x10B7F) ||
+         (0x10B80 <= CP && CP <= 0x10B91) || (0x10B92 <= CP && CP <= 0x10B98) ||
+         (0x10B99 <= CP && CP <= 0x10B9C) || (0x10B9D <= CP && CP <= 0x10BA8) ||
+         (0x10BA9 <= CP && CP <= 0x10BAF) || (0x10BB0 <= CP && CP <= 0x10BFF) ||
+         (0x10C00 <= CP && CP <= 0x10C48) || (0x10C49 <= CP && CP <= 0x10C7F) ||
+         (0x10C80 <= CP && CP <= 0x10CB2) || (0x10CB3 <= CP && CP <= 0x10CBF) ||
+         (0x10CC0 <= CP && CP <= 0x10CF2) || (0x10CF3 <= CP && CP <= 0x10CF9) ||
+         (0x10CFA <= CP && CP <= 0x10CFF) || (0x10D40 <= CP && CP <= 0x10E5F) ||
+         (CP == 0x10E7F) || (0x10E80 <= CP && CP <= 0x10EA9) ||
+         (CP == 0x10EAA) || (CP == 0x10EAD) ||
+         (0x10EAE <= CP && CP <= 0x10EAF) || (0x10EB0 <= CP && CP <= 0x10EB1) ||
+         (0x10EB2 <= CP && CP <= 0x10EFF) || (0x10F00 <= CP && CP <= 0x10F1C) ||
+         (0x10F1D <= CP && CP <= 0x10F26) || (CP == 0x10F27) ||
+         (0x10F28 <= CP && CP <= 0x10F2F) || (0x10F70 <= CP && CP <= 0x10F81) ||
+         (0x10F86 <= CP && CP <= 0x10F89) || (0x10F8A <= CP && CP <= 0x10FAF) ||
+         (0x10FB0 <= CP && CP <= 0x10FC4) || (0x10FC5 <= CP && CP <= 0x10FCB) ||
+         (0x10FCC <= CP && CP <= 0x10FDF) || (0x10FE0 <= CP && CP <= 0x10FF6) ||
+         (0x10FF7 <= CP && CP <= 0x10FFF) || (0x1E800 <= CP && CP <= 0x1E8C4) ||
+         (0x1E8C5 <= CP && CP <= 0x1E8C6) || (0x1E8C7 <= CP && CP <= 0x1E8CF) ||
+         (0x1E8D7 <= CP && CP <= 0x1E8FF) || (0x1E900 <= CP && CP <= 0x1E943) ||
+         (CP == 0x1E94B) || (0x1E94C <= CP && CP <= 0x1E94F) ||
+         (0x1E950 <= CP && CP <= 0x1E959) || (0x1E95A <= CP && CP <= 0x1E95D) ||
+         (0x1E95E <= CP && CP <= 0x1E95F) || (0x1E960 <= CP && CP <= 0x1EC6F) ||
+         (0x1ECC0 <= CP && CP <= 0x1ECFF) || (0x1ED50 <= CP && CP <= 0x1EDFF);
 }
 
-// CHECK: warning: unsupported MC/DC boolean expression; number of conditions{{.*}} exceeds max
+// CHECK: warning: unsupported MC/DC boolean expression; number of test vectors{{.*}} exceeds max
+// CHECK-NOT: Decision,
+// CHECK-NOT: Branch,{{.*}}]
diff --git a/clang/test/CoverageMapping/mcdc-logical-scalar-ids.cpp b/clang/test/CoverageMapping/mcdc-logical-scalar-ids.cpp
index c820b5df5ad3a..0694f7dbc294a 100644
--- a/clang/test/CoverageMapping/mcdc-logical-scalar-ids.cpp
+++ b/clang/test/CoverageMapping/mcdc-logical-scalar-ids.cpp
@@ -10,25 +10,25 @@ bool func_scalar_and(bool a, bool b, bool c, bool d, bool e, bool f) {
     return bar(res1, res2, res3, res4, res5);
 }
 
-// CHECK-LABEL: Decision,File 0, 5:17 -> 5:23 = M:0, C:2
+// CHECK-LABEL: Decision,File 0, 5:17 -> 5:23 = M:3, C:2
 // CHECK-NEXT: Branch,File 0, 5:17 -> 5:18 = #1, (#0 - #1) [1,2,0]
 // CHECK: Branch,File 0, 5:22 -> 5:23 = #2, (#1 - #2) [2,0,0]
-// CHECK-LABEL: Decision,File 0, 6:17 -> 6:28 = M:1, C:3
+// CHECK-LABEL: Decision,File 0, 6:17 -> 6:28 = M:7, C:3
 // CHECK-NEXT: Branch,File 0, 6:17 -> 6:18 = #5, (#0 - #5) [1,3,0]
 // CHECK: Branch,File 0, 6:22 -> 6:23 = #6, (#5 - #6) [3,2,0]
 // CHECK: Branch,File 0, 6:27 -> 6:28 = #4, (#3 - #4) [2,0,0]
-// CHECK-LABEL: Decision,File 0, 7:17 -> 7:33 = M:2, C:4
+// CHECK-LABEL: Decision,File 0, 7:17 -> 7:33 = M:12, C:4
 // CHECK-NEXT: Branch,File 0, 7:17 -> 7:18 = #11, (#0 - #11) [1,4,0]
 // CHECK: Branch,File 0, 7:22 -> 7:23 = #12, (#11 - #12) [4,3,0]
 // CHECK: Branch,File 0, 7:27 -> 7:28 = #10, (#9 - #10) [3,2,0]
 // CHECK: Branch,File 0, 7:32 -> 7:33 = #8, (#7 - #8) [2,0,0]
-// CHECK-LABEL: Decision,File 0, 8:17 -> 8:38 = M:4, C:5
+// CHECK-LABEL: Decision,File 0, 8:17 -> 8:38 = M:18, C:5
 // CHECK-NEXT: Branch,File 0, 8:17 -> 8:18 = #19, (#0 - #19) [1,5,0]
 // CHECK: Branch,File 0, 8:22 -> 8:23 = #20, (#19 - #20) [5,4,0]
 // CHECK: Branch,File 0, 8:27 -> 8:28 = #18, (#17 - #18) [4,3,0]
 // CHECK: Branch,File 0, 8:32 -> 8:33 = #16, (#15 - #16) [3,2,0]
 // CHECK: Branch,File 0, 8:37 -> 8:38 = #14, (#13 - #14) [2,0,0]
-// CHECK-LABEL: Decision,File 0, 9:17 -> 9:43 = M:8, C:6
+// CHECK-LABEL: Decision,File 0, 9:17 -> 9:43 = M:25, C:6
 // CHECK-NEXT: Branch,File 0, 9:17 -> 9:18 = #29, (#0 - #29) [1,6,0]
 // CHECK: Branch,File 0, 9:22 -> 9:23 = #30, (#29 - #30) [6,5,0]
 // CHECK: Branch,File 0, 9:27 -> 9:28 = #28, (#27 - #28) [5,4,0]
@@ -45,25 +45,25 @@ bool func_scalar_or(bool a, bool b, bool c, bool d, bool e, bool f) {
     return bar(res1, res2, res3, res4, res5);
 }
 
-// CHECK-LABEL: Decision,File 0, 40:17 -> 40:23 = M:0, C:2
+// CHECK-LABEL: Decision,File 0, 40:17 -> 40:23 = M:3, C:2
 // CHECK-NEXT: Branch,File 0, 40:17 -> 40:18 = (#0 - #1), #1 [1,0,2]
 // CHECK: Branch,File 0, 40:22 -> 40:23 = (#1 - #2), #2 [2,0,0]
-// CHECK-LABEL: Decision,File 0, 41:17 -> 41:28 = M:1, C:3
+// CHECK-LABEL: Decision,File 0, 41:17 -> 41:28 = M:7, C:3
 // CHECK-NEXT: Branch,File 0, 41:17 -> 41:18 = (#0 - #5), #5 [1,0,3]
 // CHECK: Branch,File 0, 41:22 -> 41:23 = (#5 - #6), #6 [3,0,2]
 // CHECK: Branch,File 0, 41:27 -> 41:28 = (#3 - #4), #4 [2,0,0]
-// CHECK-LABEL: Decision,File 0, 42:17 -> 42:33 = M:2, C:4
+// CHECK-LABEL: Decision,File 0, 42:17 -> 42:33 = M:12, C:4
 // CHECK-NEXT: Branch,File 0, 42:17 -> 42:18 = (#0 - #11), #11 [1,0,4]
 // CHECK: Branch,File 0, 42:22 -> 42:23 = (#11 - #12), #12 [4,0,3]
 // CHECK: Branch,File 0, 42:27 -> 42:28 = (#9 - #10), #10 [3,0,2]
 // CHECK: Branch,File 0, 42:32 -> 42:33 = (#7 - #8), #8 [2,0,0]
-// CHECK-LABEL: Decision,File 0, 43:17 -> 43:38 = M:4, C:5
+// CHECK-LABEL: Decision,File 0, 43:17 -> 43:38 = M:18, C:5
 // CHECK-NEXT: Branch,File 0, 43:17 -> 43:18 = (#0 - #19), #19 [1,0,5]
 // CHECK: Branch,File 0, 43:22 -> 43:23 = (#19 - #20), #20 [5,0,4]
 // CHECK: Branch,File 0, 43:27 -> 43:28 = (#17 - #18), #18 [4,0,3]
 // CHECK: Branch,File 0, 43:32 -> 43:33 = (#15 - #16), #16 [3,0,2]
 // CHECK: Branch,File 0, 43:37 -> 43:38 = (#13 - #14), #14 [2,0,0]
-// CHECK-LABEL: Decision,File 0, 44:17 -> 44:43 = M:8, C:6
+// CHECK-LABEL: Decision,File 0, 44:17 -> 44:43 = M:25, C:6
 // CHECK-NEXT: Branch,File 0, 44:17 -> 44:18 = (#0 - #29), #29 [1,0,6]
 // CHECK: Branch,File 0, 44:22 -> 44:23 = (#29 - #30), #30 [6,0,5]
 // CHECK: Branch,File 0, 44:27 -> 44:28 = (#27 - #28), #28 [5,0,4]
@@ -81,26 +81,26 @@ bool func_scalar_mix(bool a, bool b, bool c, bool d, bool e, bool f) {
     return bar(res1, res2, res3, res4, res5);
 }
 
-// CHECK-LABEL:  Decision,File 0, 76:17 -> 76:23 = M:0, C:2
+// CHECK-LABEL:  Decision,File 0, 76:17 -> 76:23 = M:3, C:2
 // CHECK-NEXT:  Branch,File 0, 76:17 -> 76:18 = (#0 - #1), #1 [1,0,2]
 // CHECK:  Branch,File 0, 76:22 -> 76:23 = (#1 - #2), #2 [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 77:17 -> 77:30 = M:1, C:3
+// CHECK-LABEL:  Decision,File 0, 77:17 -> 77:30 = M:7, C:3
 // CHECK-NEXT:  Branch,File 0, 77:17 -> 77:18 = #3, (#0 - #3) [1,2,0]
 // CHECK:  Branch,File 0, 77:23 -> 77:24 = (#3 - #4), #4 [2,0,3]
 // CHECK:  Branch,File 0, 77:28 -> 77:29 = (#4 - #5), #5 [3,0,0]
-// CHECK-LABEL:  Decision,File 0, 78:17 -> 78:37 = M:2, C:4
+// CHECK-LABEL:  Decision,File 0, 78:17 -> 78:37 = M:14, C:4
 // CHECK-NEXT:  File 0
 // CHECK-NEXT:  Branch,File 0, 78:18 -> 78:19 = (#0 - #7), #7 [1,2,3]
 // CHECK:  Branch,File 0, 78:23 -> 78:24 = (#7 - #8), #8 [3,2,0]
 // CHECK:  Branch,File 0, 78:30 -> 78:31 = (#6 - #9), #9 [2,0,4]
 // CHECK:  Branch,File 0, 78:35 -> 78:36 = (#9 - #10), #10 [4,0,0]
-// CHECK-LABEL:  Decision,File 0, 79:17 -> 79:42 = M:4, C:5
+// CHECK-LABEL:  Decision,File 0, 79:17 -> 79:42 = M:22, C:5
 // CHECK-NEXT:  Branch,File 0, 79:17 -> 79:18 = #12, (#0 - #12) [1,3,0]
 // CHECK:  Branch,File 0, 79:23 -> 79:24 = (#12 - #13), #13 [3,2,4]
 // CHECK:  Branch,File 0, 79:28 -> 79:29 = (#13 - #14), #14 [4,2,0]
 // CHECK:  Branch,File 0, 79:35 -> 79:36 = (#11 - #15), #15 [2,0,5]
 // CHECK:  Branch,File 0, 79:40 -> 79:41 = (#15 - #16), #16 [5,0,0]
-// CHECK-LABEL:  Decision,File 0, 80:17 -> 80:49 = M:8, C:6
+// CHECK-LABEL:  Decision,File 0, 80:17 -> 80:49 = M:37, C:6
 // CHECK-NEXT:  File 0
 // CHECK-NEXT:  Branch,File 0, 80:18 -> 80:19 = (#0 - #19), #19 [1,3,4]
 // CHECK:  Branch,File 0, 80:23 -> 80:24 = (#19 - #20), #20 [4,3,0]
diff --git a/clang/test/CoverageMapping/mcdc-logical-stmt-ids-all.cpp b/clang/test/CoverageMapping/mcdc-logical-stmt-ids-all.cpp
index 6f47a4b901a8a..d7436079d1810 100644
--- a/clang/test/CoverageMapping/mcdc-logical-stmt-ids-all.cpp
+++ b/clang/test/CoverageMapping/mcdc-logical-stmt-ids-all.cpp
@@ -6,7 +6,7 @@ bool func_if_and(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 4:7 -> 4:33 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 4:7 -> 4:33 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 4:7 -> 4:8 = #10, (#0 - #10) [1,6,0]
 // CHECK:  Branch,File 0, 4:12 -> 4:13 = #11, (#10 - #11) [6,5,0]
 // CHECK:  Branch,File 0, 4:17 -> 4:18 = #9, (#8 - #9) [5,4,0]
@@ -20,7 +20,7 @@ bool func_if_or(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 18:7 -> 18:33 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 18:7 -> 18:33 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 18:7 -> 18:8 = (#0 - #10), #10 [1,0,6]
 // CHECK:  Branch,File 0, 18:12 -> 18:13 = (#10 - #11), #11 [6,0,5]
 // CHECK:  Branch,File 0, 18:17 -> 18:18 = (#8 - #9), #9 [5,0,4]
@@ -33,7 +33,7 @@ bool func_while_and(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 32:10 -> 32:36 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 32:10 -> 32:36 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 32:10 -> 32:11 = #10, (#0 - #10) [1,6,0]
 // CHECK:  Branch,File 0, 32:15 -> 32:16 = #11, (#10 - #11) [6,5,0]
 // CHECK:  Branch,File 0, 32:20 -> 32:21 = #9, (#8 - #9) [5,4,0]
@@ -46,7 +46,7 @@ bool func_while_or(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 45:10 -> 45:36 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 45:10 -> 45:36 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 45:10 -> 45:11 = (#0 - #10), #10 [1,0,6]
 // CHECK:  Branch,File 0, 45:15 -> 45:16 = (#10 - #11), #11 [6,0,5]
 // CHECK:  Branch,File 0, 45:20 -> 45:21 = (#8 - #9), #9 [5,0,4]
@@ -59,7 +59,7 @@ bool func_for_and(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 58:9 -> 58:35 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 58:9 -> 58:35 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 58:9 -> 58:10 = #10, (#0 - #10) [1,6,0]
 // CHECK:  Branch,File 0, 58:14 -> 58:15 = #11, (#10 - #11) [6,5,0]
 // CHECK:  Branch,File 0, 58:19 -> 58:20 = #9, (#8 - #9) [5,4,0]
@@ -72,7 +72,7 @@ bool func_for_or(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 71:9 -> 71:35 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 71:9 -> 71:35 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 71:9 -> 71:10 = (#0 - #10), #10 [1,0,6]
 // CHECK:  Branch,File 0, 71:14 -> 71:15 = (#10 - #11), #11 [6,0,5]
 // CHECK:  Branch,File 0, 71:19 -> 71:20 = (#8 - #9), #9 [5,0,4]
@@ -85,7 +85,7 @@ bool func_do_and(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 84:16 -> 84:42 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 84:16 -> 84:42 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 84:16 -> 84:17 = #10, ((#0 + #1) - #10) [1,6,0]
 // CHECK:  Branch,File 0, 84:21 -> 84:22 = #11, (#10 - #11) [6,5,0]
 // CHECK:  Branch,File 0, 84:26 -> 84:27 = #9, (#8 - #9) [5,4,0]
@@ -98,7 +98,7 @@ bool func_do_or(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 97:16 -> 97:42 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 97:16 -> 97:42 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 97:16 -> 97:17 = ((#0 + #1) - #10), #10 [1,0,6]
 // CHECK:  Branch,File 0, 97:21 -> 97:22 = (#10 - #11), #11 [6,0,5]
 // CHECK:  Branch,File 0, 97:26 -> 97:27 = (#8 - #9), #9 [5,0,4]
@@ -110,7 +110,7 @@ bool func_ternary_and(bool a, bool b, bool c, bool d, bool e, bool f) {
   return (a && b && c && d && e && f) ? true : false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 110:11 -> 110:37 = M:0, C:6
+// CHECK-LABEL:  Decision,File 0, 110:11 -> 110:37 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 110:11 -> 110:12 = #10, (#0 - #10) [1,6,0]
 // CHECK:  Branch,File 0, 110:16 -> 110:17 = #11, (#10 - #11) [6,5,0]
 // CHECK:  Branch,File 0, 110:21 -> 110:22 = #9, (#8 - #9) [5,4,0]
@@ -122,7 +122,7 @@ bool func_ternary_or(bool a, bool b, bool c, bool d, bool e, bool f) {
   return (a || b || c || d || e || f) ? true : false;
 }
 
-// CHECK-LABEL: Decision,File 0, 122:11 -> 122:37 = M:0, C:6
+// CHECK-LABEL: Decision,File 0, 122:11 -> 122:37 = M:7, C:6
 // CHECK-NEXT:  Branch,File 0, 122:11 -> 122:12 = (#0 - #10), #10 [1,0,6]
 // CHECK:  Branch,File 0, 122:16 -> 122:17 = (#10 - #11), #11 [6,0,5]
 // CHECK:  Branch,File 0, 122:21 -> 122:22 = (#8 - #9), #9 [5,0,4]
@@ -137,7 +137,7 @@ bool func_if_nested_if(bool a, bool b, bool c, bool d, bool e) {
     return false;
 }
 
-// CHECK-LABEL: Decision,File 0, 134:7 -> 134:30 = M:0, C:5
+// CHECK-LABEL: Decision,File 0, 134:7 -> 134:30 = M:8, C:5
 // CHECK-NEXT:  Branch,File 0, 134:7 -> 134:8 = (#0 - #6), #6 [1,0,4]
 // CHECK:  Branch,File 0, 134:13 -> 134:14 = #7, (#6 - #7) [4,5,3]
 // CHECK:  Branch,File 0, 134:18 -> 134:19 = #8, (#7 - #8) [5,0,3]
@@ -148,7 +148,7 @@ bool func_ternary_nested_if(bool a, bool b, bool c, bool d, bool e) {
   return (a || (b && c) || d || e) ? true : false;
 }
 
-// CHECK-LABEL: Decision,File 0, 148:11 -> 148:34 = M:0, C:5
+// CHECK-LABEL: Decision,File 0, 148:11 -> 148:34 = M:8, C:5
 // CHECK-NEXT:  Branch,File 0, 148:11 -> 148:12 = (#0 - #6), #6 [1,0,4]
 // CHECK:  Branch,File 0, 148:17 -> 148:18 = #7, (#6 - #7) [4,5,3]
 // CHECK:  Branch,File 0, 148:22 -> 148:23 = #8, (#7 - #8) [5,0,3]
@@ -162,7 +162,7 @@ bool func_if_nested_if_2(bool a, bool b, bool c, bool d, bool e) {
     return false;
 }
 
-// CHECK-LABEL: Decision,File 0, 159:7 -> 159:32 = M:0, C:5
+// CHECK-LABEL: Decision,File 0, 159:7 -> 159:32 = M:9, C:5
 // CHECK-NEXT:  Branch,File 0, 159:7 -> 159:8 = (#0 - #2), #2 [1,0,2]
 // CHECK:  Branch,File 0, 159:14 -> 159:15 = #7, (#2 - #7) [2,5,4]
 // CHECK:  Branch,File 0, 159:19 -> 159:20 = #8, (#7 - #8) [5,3,4]
@@ -173,7 +173,7 @@ bool func_ternary_nested_if_2(bool a, bool b, bool c, bool d, bool e) {
   return (a || ((b && c) || d) && e) ? true : false;
 }
 
-// CHECK-LABEL: Decision,File 0, 173:11 -> 173:36 = M:0, C:5
+// CHECK-LABEL: Decision,File 0, 173:11 -> 173:36 = M:9, C:5
 // CHECK-NEXT:  Branch,File 0, 173:11 -> 173:12 = (#0 - #2), #2 [1,0,2]
 // CHECK:  Branch,File 0, 173:18 -> 173:19 = #7, (#2 - #7) [2,5,4]
 // CHECK:  Branch,File 0, 173:23 -> 173:24 = #8, (#7 - #8) [5,3,4]
@@ -187,7 +187,7 @@ bool func_if_nested_if_3(bool a, bool b, bool c, bool d, bool e, bool f) {
     return false;
 }
 
-// CHECK-LABEL: Decision,File 0, 184:7 -> 184:39 = M:0, C:6
+// CHECK-LABEL: Decision,File 0, 184:7 -> 184:39 = M:12, C:6
 // CHECK:  Branch,File 0, 184:8 -> 184:9 = #5, (#0 - #5) [1,4,3]
 // CHECK:  Branch,File 0, 184:14 -> 184:15 = (#5 - #6), #6 [4,2,5]
 // CHECK:  Branch,File 0, 184:19 -> 184:20 = (#6 - #7), #7 [5,2,3]
@@ -199,7 +199,7 @@ bool func_ternary_nested_if_3(bool a, bool b, bool c, bool d, bool e, bool f) {
   return ((a && (b || c) || (d && e)) && f) ? true : false;
 }
 
-// CHECK-LABEL: Decision,File 0, 199:11 -> 199:43 = M:0, C:6
+// CHECK-LABEL: Decision,File 0, 199:11 -> 199:43 = M:12, C:6
 // CHECK:  Branch,File 0, 199:12 -> 199:13 = #5, (#0 - #5) [1,4,3]
 // CHECK:  Branch,File 0, 199:18 -> 199:19 = (#5 - #6), #6 [4,2,5]
 // CHECK:  Branch,File 0, 199:23 -> 199:24 = (#6 - #7), #7 [5,2,3]
diff --git a/clang/test/CoverageMapping/mcdc-logical-stmt-ids.cpp b/clang/test/CoverageMapping/mcdc-logical-stmt-ids.cpp
index 99854ec27a3fb..655bbf25ee103 100644
--- a/clang/test/CoverageMapping/mcdc-logical-stmt-ids.cpp
+++ b/clang/test/CoverageMapping/mcdc-logical-stmt-ids.cpp
@@ -10,25 +10,25 @@ bool func_if_and(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 4:7 -> 4:13 = M:0, C:2
+// CHECK-LABEL:  Decision,File 0, 4:7 -> 4:13 = M:3, C:2
 // CHECK-NEXT:  Branch,File 0, 4:7 -> 4:8 = #2, (#0 - #2) [1,2,0]
 // CHECK:  Branch,File 0, 4:12 -> 4:13 = #3, (#2 - #3) [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 5:9 -> 5:20 = M:1, C:3
+// CHECK-LABEL:  Decision,File 0, 5:9 -> 5:20 = M:7, C:3
 // CHECK-NEXT:  Branch,File 0, 5:9 -> 5:10 = #7, (#1 - #7) [1,3,0]
 // CHECK:  Branch,File 0, 5:14 -> 5:15 = #8, (#7 - #8) [3,2,0]
 // CHECK:  Branch,File 0, 5:19 -> 5:20 = #6, (#5 - #6) [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 6:11 -> 6:27 = M:2, C:4
+// CHECK-LABEL:  Decision,File 0, 6:11 -> 6:27 = M:12, C:4
 // CHECK-NEXT:  Branch,File 0, 6:11 -> 6:12 = #14, (#4 - #14) [1,4,0]
 // CHECK:  Branch,File 0, 6:16 -> 6:17 = #15, (#14 - #15) [4,3,0]
 // CHECK:  Branch,File 0, 6:21 -> 6:22 = #13, (#12 - #13) [3,2,0]
 // CHECK:  Branch,File 0, 6:26 -> 6:27 = #11, (#10 - #11) [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 7:13 -> 7:34 = M:4, C:5
+// CHECK-LABEL:  Decision,File 0, 7:13 -> 7:34 = M:18, C:5
 // CHECK-NEXT:  Branch,File 0, 7:13 -> 7:14 = #23, (#9 - #23) [1,5,0]
 // CHECK:  Branch,File 0, 7:18 -> 7:19 = #24, (#23 - #24) [5,4,0]
 // CHECK:  Branch,File 0, 7:23 -> 7:24 = #22, (#21 - #22) [4,3,0]
 // CHECK:  Branch,File 0, 7:28 -> 7:29 = #20, (#19 - #20) [3,2,0]
 // CHECK:  Branch,File 0, 7:33 -> 7:34 = #18, (#17 - #18) [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 8:16 -> 8:42 = M:8, C:6
+// CHECK-LABEL:  Decision,File 0, 8:16 -> 8:42 = M:25, C:6
 // CHECK-NEXT:  Branch,File 0, 8:16 -> 8:17 = #34, (#16 - #34) [1,6,0]
 // CHECK:  Branch,File 0, 8:21 -> 8:22 = #35, (#34 - #35) [6,5,0]
 // CHECK:  Branch,File 0, 8:26 -> 8:27 = #33, (#32 - #33) [5,4,0]
@@ -46,25 +46,25 @@ bool func_if_or(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 40:7 -> 40:13 = M:0, C:2
+// CHECK-LABEL:  Decision,File 0, 40:7 -> 40:13 = M:3, C:2
 // CHECK-NEXT:  Branch,File 0, 40:7 -> 40:8 = (#0 - #2), #2 [1,0,2]
 // CHECK:  Branch,File 0, 40:12 -> 40:13 = (#2 - #3), #3 [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 41:9 -> 41:20 = M:1, C:3
+// CHECK-LABEL:  Decision,File 0, 41:9 -> 41:20 = M:7, C:3
 // CHECK-NEXT:  Branch,File 0, 41:9 -> 41:10 = (#1 - #7), #7 [1,0,3]
 // CHECK:  Branch,File 0, 41:14 -> 41:15 = (#7 - #8), #8 [3,0,2]
 // CHECK:  Branch,File 0, 41:19 -> 41:20 = (#5 - #6), #6 [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 42:11 -> 42:27 = M:2, C:4
+// CHECK-LABEL:  Decision,File 0, 42:11 -> 42:27 = M:12, C:4
 // CHECK-NEXT:  Branch,File 0, 42:11 -> 42:12 = (#4 - #14), #14 [1,0,4]
 // CHECK:  Branch,File 0, 42:16 -> 42:17 = (#14 - #15), #15 [4,0,3]
 // CHECK:  Branch,File 0, 42:21 -> 42:22 = (#12 - #13), #13 [3,0,2]
 // CHECK:  Branch,File 0, 42:26 -> 42:27 = (#10 - #11), #11 [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 43:13 -> 43:34 = M:4, C:5
+// CHECK-LABEL:  Decision,File 0, 43:13 -> 43:34 = M:18, C:5
 // CHECK-NEXT:  Branch,File 0, 43:13 -> 43:14 = (#9 - #23), #23 [1,0,5]
 // CHECK:  Branch,File 0, 43:18 -> 43:19 = (#23 - #24), #24 [5,0,4]
 // CHECK:  Branch,File 0, 43:23 -> 43:24 = (#21 - #22), #22 [4,0,3]
 // CHECK:  Branch,File 0, 43:28 -> 43:29 = (#19 - #20), #20 [3,0,2]
 // CHECK:  Branch,File 0, 43:33 -> 43:34 = (#17 - #18), #18 [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 44:16 -> 44:42 = M:8, C:6
+// CHECK-LABEL:  Decision,File 0, 44:16 -> 44:42 = M:25, C:6
 // CHECK-NEXT:  Branch,File 0, 44:16 -> 44:17 = (#16 - #34), #34 [1,0,6]
 // CHECK:  Branch,File 0, 44:21 -> 44:22 = (#34 - #35), #35 [6,0,5]
 // CHECK:  Branch,File 0, 44:26 -> 44:27 = (#32 - #33), #33 [5,0,4]
@@ -82,26 +82,26 @@ bool func_if_mix(bool a, bool b, bool c, bool d, bool e, bool f) {
   return false;
 }
 
-// CHECK-LABEL:  Decision,File 0, 76:7 -> 76:13 = M:0, C:2
+// CHECK-LABEL:  Decision,File 0, 76:7 -> 76:13 = M:3, C:2
 // CHECK-NEXT:  Branch,File 0, 76:7 -> 76:8 = (#0 - #2), #2 [1,0,2]
 // CHECK:  Branch,File 0, 76:12 -> 76:13 = (#2 - #3), #3 [2,0,0]
-// CHECK-LABEL:  Decision,File 0, 77:9 -> 77:22 = M:1, C:3
+// CHECK-LABEL:  Decision,File 0, 77:9 -> 77:22 = M:7, C:3
 // CHECK-NEXT:  Branch,File 0, 77:9 -> 77:10 = #5, (#1 - #5) [1,2,0]
 // CHECK:  Branch,File 0, 77:15 -> 77:16 = (#5 - #6), #6 [2,0,3]
 // CHECK:  Branch,File 0, 77:20 -> 77:21 = (#6 - #7), #7 [3,0,0]
-// CHECK-LABEL:  Decision,File 0, 78:11 -> 78:31 = M:2, C:4
+// CHECK-LABEL:  Decision,File 0, 78:11 -> 78:31 = M:14, C:4
 // CHECK-NEXT:  File 0
 // CHECK-NEXT:  Branch,File 0, 78:12 -> 78:13 = (#4 - #10), #10 [1,2,3]
 // CHECK:  Branch,File 0, 78:17 -> 78:18 = (#10 - #11), #11 [3,2,0]
 // CHECK:  Branch,File 0, 78:24 -> 78:25 = (#9 - #12), #12 [2,0,4]
 // CHECK:  Branch,File 0, 78:29 -> 78:30 = (#12 - #13), #13 [4,0,0]
-// CHECK-LABEL:  Decision,File 0, 79:13 -> 79:38 = M:4, C:5
+// CHECK-LABEL:  Decision,File 0, 79:13 -> 79:38 = M:22, C:5
 // CHECK-NEXT:  Branch,File 0, 79:13 -> 79:14 = #16, (#8 - #16) [1,3,0]
 // CHECK:  Branch,File 0, 79:19 -> 79:20 = (#16 - #17), #17 [3,2,4]
 // CHECK:  Branch,File 0, 79:24 -> 79:25 = (#17 - #18), #18 [4,2,0]
 // CHECK:  Branch,File 0, 79:31 -> 79:32 = (#15 - #19), #19 [2,0,5]
 // CHECK:  Branch,File 0, 79:36 -> 79:37 = (#19 - #20), #20 [5,0,0]
-// CHECK-LABEL:  Decision,File 0, 80:15 -> 80:47 = M:8, C:6
+// CHECK-LABEL:  Decision,File 0, 80:15 -> 80:47 = M:37, C:6
 // CHECK-NEXT:  File 0
 // CHECK-NEXT:  Branch,File 0, 80:16 -> 80:17 = (#14 - #24), #24 [1,3,4]
 // CHECK:  Branch,File 0, 80:21 -> 80:22 = (#24 - #25), #25 [4,3,0]
diff --git a/clang/test/Profile/c-mcdc-logicalop-ternary.c b/clang/test/Profile/c-mcdc-logicalop-ternary.c
index 558643f422021..04384d71bf272 100644
--- a/clang/test/Profile/c-mcdc-logicalop-ternary.c
+++ b/clang/test/Profile/c-mcdc-logicalop-ternary.c
@@ -9,7 +9,7 @@ int test(int a, int b, int c, int d, int e, int f) {
 // NOMCDC-NOT: __profbm_test
 
 // MCDC BOOKKEEPING.
-// MCDC: @__profbm_test = private global [3 x i8] zeroinitializer
+// MCDC: @__profbm_test = private global [2 x i8] zeroinitializer
 
 // ALLOCATE MCDC TEMP AND ZERO IT.
 // MCDC-LABEL: @test(
@@ -39,7 +39,7 @@ int test(int a, int b, int c, int d, int e, int f) {
 // MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
 // MCDC:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
 // MCDC:  %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
-// MCDC:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 1) to i64), %[[LAB2]]
+// MCDC:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
 // MCDC:  %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
 // MCDC:  %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
 // MCDC:  %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
@@ -71,7 +71,7 @@ int test(int a, int b, int c, int d, int e, int f) {
 // MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
 // MCDC:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
 // MCDC:  %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
-// MCDC:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr getelementptr inbounds ([3 x i8], ptr @__profbm_test, i32 0, i32 2) to i64), %[[LAB2]]
+// MCDC:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
 // MCDC:  %[[LAB4:[0-9]+]] = inttoptr i64 %[[LAB3]] to ptr
 // MCDC:  %[[LAB5:[0-9]+]] = and i32 %[[TEMP]], 7
 // MCDC:  %[[LAB6:[0-9]+]] = trunc i32 %[[LAB5]] to i8
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 8e6205c4b6166..51cc29fd26ce8 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -387,34 +387,31 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
       : NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
         Region(Region), DecisionParams(Region.getDecisionParams()),
         Branches(Branches), NumConditions(DecisionParams.NumConditions),
-        BitmapIdx(DecisionParams.BitmapIdx * CHAR_BIT),
-        Folded(NumConditions, false), IndependencePairs(NumConditions) {}
+        BitmapIdx(DecisionParams.BitmapIdx), Folded(NumConditions, false),
+        IndependencePairs(NumConditions) {}
 
 private:
   // Walk the binary decision diagram and try assigning both false and true to
   // each node. When a terminal node (ID == 0) is reached, fill in the value in
   // the truth table.
   void buildTestVector(MCDCRecord::TestVector &TV, mcdc::ConditionID ID,
-                       int TVIdx, unsigned Index) {
-    assert((Index & (1 << ID)) == 0);
-
+                       int TVIdx) {
     for (auto MCDCCond : {MCDCRecord::MCDC_False, MCDCRecord::MCDC_True}) {
       static_assert(MCDCRecord::MCDC_False == 0);
       static_assert(MCDCRecord::MCDC_True == 1);
-      Index |= MCDCCond << ID;
       TV[ID] = MCDCCond;
       auto NextID = NextIDs[ID][MCDCCond];
       auto NextTVIdx = TVIdx + Indices[ID][MCDCCond];
       assert(NextID == SavedNodes[ID].NextIDs[MCDCCond]);
       if (NextID >= 0) {
-        buildTestVector(TV, NextID, NextTVIdx, Index);
+        buildTestVector(TV, NextID, NextTVIdx);
         continue;
       }
 
       assert(TVIdx < SavedNodes[ID].Width);
       assert(TVIdxs.insert(NextTVIdx).second && "Duplicate TVIdx");
 
-      if (!Bitmap[BitmapIdx + Index])
+      if (!Bitmap[BitmapIdx - NumTestVectors + NextTVIdx])
         continue;
 
       // Copy the completed test vector to the vector of testvectors.
@@ -437,7 +434,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
     // `TVIdx` starts with 0 and is in the traversal.
     // `Index` encodes the bitmask of true values and is initially 0.
     MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
-    buildTestVector(TV, 0, 0, 0);
+    buildTestVector(TV, 0, 0);
     assert(TVIdxs.size() == unsigned(NumTestVectors) &&
            "TVIdxs wasn't fulfilled");
   }
@@ -615,21 +612,12 @@ static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
 static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx,
                                  const CoverageMappingRecord &Record) {
   unsigned MaxBitmapIdx = 0;
-  unsigned NumConditions = 0;
-  // Scan max(BitmapIdx).
-  // Note that `<=` is used insted of `<`, because `BitmapIdx == 0` is valid
-  // and `MaxBitmapIdx is `unsigned`. `BitmapIdx` is unique in the record.
   for (const auto &Region : reverse(Record.MappingRegions)) {
-    if (Region.Kind != CounterMappingRegion::MCDCDecisionRegion)
-      continue;
-    const auto &DecisionParams = Region.getDecisionParams();
-    if (MaxBitmapIdx <= DecisionParams.BitmapIdx) {
-      MaxBitmapIdx = DecisionParams.BitmapIdx;
-      NumConditions = DecisionParams.NumConditions;
-    }
+    if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion)
+      MaxBitmapIdx =
+          std::max(MaxBitmapIdx, Region.getDecisionParams().BitmapIdx);
   }
-  unsigned SizeInBits = llvm::alignTo(uint64_t(1) << NumConditions, CHAR_BIT);
-  return MaxBitmapIdx * CHAR_BIT + SizeInBits;
+  return MaxBitmapIdx;
 }
 
 namespace {
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-const-folding.o b/llvm/test/tools/llvm-cov/Inputs/mcdc-const-folding.o
index 4f54fa7b8a1a1492a9a455bbf6fa651844345c59..7a16162f29c00777d9a05f5fed1cc4cbf333c56c 100644
GIT binary patch
delta 5899
zcmai04Qx}_74|hDF*Lz(34QTOe!MP_Zf1!EB!NI3^V208h=$*kUq2ece}2FTA!&#M
zH4AGy)jC3}v@*q-rh(Q;F-g~IQmY_3+D at BV5TmH9T0C_t6J;YJqNS~tedqeV<i_o`
zC%xl)&i9?~o_p?n&+qN$?ZeO8UnmyC(MOAOtH-9=a7D&K52#^W+_L-LiS8;F_UM at s
zm_N=g7X9Ml1T)R|&aG({+ukp(3_GMqzlgRxOy3q+`EhYxT=}bG7E50|_1WaqZ&0ns
zwZ}#Da&Eow4QaxYOPCM_>C}BCqJF|7qV=1TLsie*3uUQLzlcw{l at _=AhRzH6yQs-f
z9_GydABzD*`|Pvl;x{susvn=yFEB^zc$IdFrR7XV>(YJi^ov{bN!Sazzsm9rjkiKo
z7r7TI9A6NxBxmwU;&$GGN$a1;9G_n9Q!0sGnc|$G$fxeJb`gcs3esgm?DUH%tGmY=
z^EGAh*5<49I95B>nw?S_nlQ27<9l~6H0e;Fe_th?7g%??Z-(sE_#AXJZH_&zTFLl$
zD<4d at a!hadKhxIdl&Rcs79TJBr4`?D+PL-EXxp4*P$YvmXa2aX<-AB9QI#6G;XFO$
zJdMmy?p<e-JiQIhFD~45cFS>c1Gqm_FxB1N3nD9u$c<2iHiP)O+#ktPAO3wBXH`GD
zkc&iD>n2s5Cgr{^UC}HRJ5;DAeYO|7 at v5l0@^O`8DJxcwT~bVhRY at w)JBwaVH|9(}
zCo6sTBDVw1)0bBI#v(T`cq^$zchXC#bgE;CzQ)OW`PJ0Gptiv)dh02evH1Va7r64#
z3P%wQWjt0Ixt(%c#;5Szj at +nnp8j3G_5$f$LEmxAllx+$I>$UQg-$xwz+RJf&NLpk
zNqb4!ho*C+LE7I;-zd^3>w(>{t<rud?aEA!{94*sSv>BN_HWXzp23k<q|I~kI3n$B
zX*XnZ<aM?KMXt(BQAB3m8rXQ=T<Xosq>u7u!xQ;4#R{60Ux{&T{#>z!j=~mEEWdKr
zV%|es*|>*<9NLO#B!A|kYm$ycZYsoztpN6=iZ#)^0*}}{u%;mDbQP(jH`8sl2W at s+
z8I63`aPL#mGWFY`&_42%81A@=TDhePy+*Y_r>kkK+&`iJtXxGsB}PrHRkG6fp+ehK
zoD1bEsN%m>@wLgYZIOy+QUY`3*^}WSh2Ba_&b5qOrG`7AP^$@N6nd2cKxa&uoV!M$
z^QooO=#D7VnpY_FeHFL1;RE=*Iu~%htV#w{yiCQd8lF?}NJ at N>ieF8}?Y5?YX}(|D
zMGnR18}5RnIOeh0GI6V9TL~rR8)6B$78qg`TlW@?=~8SC?V<qCCJlWE<1fdOS0}YV
z;aO>aN-;2ht}!3hnCIv+&_N9?)X<A078>q%H8fvC|4hDxhWJF<`(%PSRqZaX>k*CV
zq$rpLbOE-6t-DfV7HiDqGy=3nL+1hgLal2(dCCm;4h>xZGzT|dO;iiCQ$rUaYW3te
z^#J{G3OZY6+H9vO4m6g6^4{?E3MGKPuAz at 1YAL@*u5v>ROZzbe%8kI?6sDz<p-wRW
zEYTF4T6{UjDPBI4UM|mc7ivhgmQg~N%h5#*eOyCVlBh7;t2A^qP^(Yd$Op7O1+~s#
zh)kei4gG<p+)L34L%c*6U|(kI9?+QlbXhtVX$0uI8v2B$^FDbN8SalXbdy%$9jaYq
z)O?zPTFM!Cw)kRr18!>{Tv~jq7N1RV%;nY4%^F%p382*)Y67)-wUJzl4Y8d9u#If9
z!Wwf2buE6F!iyaOPZ=1$V(UJyF&dy{)%^xt26{z9>$N&QAW><!|DmD#wK_f}U!_s=
z?-bNho~{Pmk-eH`juvm$;*U at ibCqalqlPY`3qV(CXe&^wBU@>t(h&9JSz?F~TX$Gv
z9 at cbvsTQ1<s0a3Cw(bFq*#V|<Z5JuN#K?MAL)$5DsX?DC$rS%0*HS}#&bCJ2--0h*
zX9jL-=QFf853TowQ;YL6Xz at MNvea<T)zIl$)<TM5#+A~pqRU`z{4dOU$qBJ_AJ;fe
zZLU)!9y7!l^1+^C>wZ;Za#yXY-k>PZH#O9)RrLqD0Q4^!%I{)prMJoBH^hBu$EX(L
zEOJ#DBA0snhC3hs=zMYC^eivM!K{$hPYEzrYRpH#wrX1^)wWOon!DM$+cc*B1`ksU
z&{G<!zrmvv1NsvU)o1w`&*DC>p$kxhb at Hx~2;iNeP(CcrX%*fjU%=@8T+3aqq4K!E
z=MDsLTYYozF~Y at h{ry^)61QpyXz|C9WA&#t8K<`bE_YCIxWcH$X`&I--=-<(Z>f{y
zS!TG;YN-B}dW~v<zNIOj)|9VN56};_T>WVuq4+Yxm+e3TE?%krwCAfhSNkGvYen9H
z`^z$>iZT+_6CaQ)%NL9A-A6v4)(0e~^JSse$OLMAKn_W40<EGbQ0oKoW(wLy7l2xy
zi`m*ADywJG2vF;Du_6UsMxL69&&6O0dX;K{TAz!(Dd>Fa;av5i?N349r#MjS<M4V4
zioX)hRj)DG2GnYG<LZFx`%Z_5lV|Ps#B$oZwtQOu{N$?J>D=0K8s3mYqiemQmptqI
z6x^6Yp><wyU3$atM&T7xY(20|z}9<3yYz<Pjlz37iPZty;Kh^g+32TXc%$(4NH6##
zu#H~vS`vdd3eQ2YP0-v7Y?D_sOK%w7D7@=QYzweDuc)F}9W>#M!aFOy;8tKydPO#Q
zHUon<3a?#y!EL}cd+}`~F?gf!s>!nj^KA#V#Vh)yHw<qSUM|J9`l)XRu&rJZmR at 1d
zK{vNnh at 0%826LNVJVCK-ekwGPwT;)qUZ3fpJ=-g$74nBNuAOvlUAd^E#CAXTbcY`u
zGIxNtGlvFuc*Q6s;1xcVLkogl at fn#xKd)k^A6-rafz$&ry_n0aUq^!&LCf@`L(Hio
zb0 at TRL2D<k!ZeZ5fQ+ZO9_GC#dA*c)3dn9C_1q<MH?%OyC9}aVO3Aa!55BnzT6>_i
zi+3OauW&Ci8n~0pdqMJUQlbIKJ|Mfj&}UvByg_)^CGU>pL3<C7{Xq73F-KzmI$E&T
zi#NTwSN0CJni6}Vbr4$nywFc at 2E0LdFG^lN#lUMPb3c$qAp5=4cK~~_r-BNbkas|K
z?SNktlBdy+^N=_I#bzJ}y;RtU-8fi5eeeel@(D~Fl<NTVI+=~oYyr{;&88%?@DMVa
zcqPoVk*CFvvuU=>q|qkm9R}Kr-xjbBucE<bK1qpYxgTI+Z7t9YL9+##hrnt^ovp|^
zBzFW%oI@~C$syF)2IMgGLSVK*?=U}IW-Ir{6Y_HpLeM(`y%6+TvF;G`+L6^NI|SyC
zWWG&_R_GlC(gwXF&^rpfHh!|qcDct#{CvKSK(7OON1)dZy(7@;L{_`pWib2517<NL
z+M)L}kfYG+NHY824<7a6DPYZPign5}*a6KhARW-`1hWI0$B@~{r_}@p&k$@cB|4$m
z4diKPb|sm8 at CTpfHwQECNakx~c0n@?qzjtIzznaV1;^y+Ip!BZioxEb#4+d{hh8`I
z!eDh_ui+1N^P9m0=RL{HB{K}Y6F|by>p^#pqsC{D*~3pk;y6Fku^xFMd%!&Dpkij6
zkW8G+7#OG at wqNqv$vnZmioxEY1ngPzJi}uX_A|*jO9_lC$P at 7kKbf#~6q7aqd!0Nd
Nd0$LeygN?L{SRp}gY^Ia

delta 6068
zcmai2dr(x at 8Q*gSVHI6K;BrwBf|+1?Q(YBVFtTid5u!Fcd_Te?%0qmBg0dKetzsb6
z8OYb9WG0zNr)kr)X;@7<(SNc`G~&c*HBB;UO{daHGj at oRFt!X!?9ku2dk&m#)AY>T
zZ_oYxzVrLO^WAgKy>RP{Hh4zs&SZl<i!u|sf`t>2Hnfh3rYO<vsmo^5dioZ_+?Y2{
z>u2u?qM!L$$3(MT-1;?|$(BYqubyK)eF<7~GBrjfFFnV)20r|2bRrj(1KVfuJLU|$
z_igdWGc6%oXr4oWrZjOQe)3O_Hq8-zq!2Yc!x`|i;Rt`EGe9G(C^Cxo$*rZdeMhnp
zAKr?#W;!*W$(a6#em=4L{xhy0YKYxDQ^3xv&OrFg&Y>jM*kyMe2O_CCa(><aAJj2A
zIYmDrOf)5g1&$onoLBpq%$V10M7UtAd``S>)H*GGCYQKB#8X405p5MI!q4aqn at 1l_
zbGBIpat6+^@bs-GI at +8n#QhPFYK{%dMw59=RZfhXTnXP&Tv3_P=4FM6p(Vzv%=I&-
zQceAinqnjtRC;V^(9}a9d*p^TS%Z$7j^{D2sU`P*!9s@(&%#=9)sDk~YR5N&cO7lk
zeaFqFEHSzKXS4X4%y0i)bSH)s{%94yof<eb$Ukj3dCFU}yf=j0omV~m%=6)`g3!vE
ztlO2)g4blMPAgVnmlcBx at GKd!$rX;)J>Ncyp0yHfzZwzB${IMlO$dd&Bc%5NyYyys
zdisL0(59Qr;(f901kh<I7j{{aG6@@!khNUx9PPN{aXkP2YUf19O?0kAC(`Yx49bq0
zl`H2W2V&LZFt|B&7)1Q{@X&gro~ZliUX+7UqGvv6>$vkB at jP!qwxDZ-FE~Wb%R-1d
z-xk7or{iY6<N3=|d!(Rq*Fs0vR|Q?8x2ZTf$>9tXp12gd-Lu2<q^Er6d(;{I5VO&5
zqo07CZs&HBWq)qjQOiCygX1q)_KO*t&|fvP2KH6U&WhpvX3PHBva4rt<PFOv&gT7N
zmi?P$*E=}!wq at tX@_vV9?{Is5W8BIZmQFqMpI{j at H2(p%l<cVw0CA?yVQXl0>Pp}~
zAnWOu7JegjWul9(QM6cG0cLe=8I-<Y&Z7098;iLu7>N~tyC<-6+PNT|J$}AzL60LY
zT at 1Q3-DZooX||=5zF0S^1-e4~whHzoDgpb3Kr_Ve62V?4AJ_;HW~pF5#)-?7SCD_P
zUbIHAGVU{itrhqhF{(n~ZwkCr;5h<k6t_e-;<XSgGZ~Hu#mXWN*cQRcBD^fv%hU*V
zLa;KECj^^DeM|JVgVRFFGA<MBC4tMw at F(2!+1(R(hRE~0z!zW~Z!(9|0^b{k=Lq~l
z2-j at o=X0FD&{z@;Ez=E|BTqR7ml$mO9>p!!nTtHIh1?pOc`!8Y8HbB|^HxcXVCzFS
z7Mq0ry@^meLVZwp#<D-58}NKZ at tmu8zDg`hH~JMeO<~_9C)leBo2sy%P-T|RzOd|F
z>VfBk;>jx~^Rd$aJQHaI_I_>+r&tGkUYUw#4yCWq4Y$HR1oj&-uXR)ccC*4R2b+M4
zw at UJXtykC_pfZPp<Okap#?G at w+H9w22<&rVtgQCy6ql_V=M*+iQNB!`Y at K~<+0Upk
zTQ8E^mCufQN*%dnIsUMs5WxX7{_`j<nez;~fw+kZTd1%LiMe#+`wIJ*!n()_)~&F7
z&B|I8Qzh8VVXRz-HPi$4kixE2l#kMYOJ`?j1omZajh`u=e1}P$w<tYFHv$S<tmq6<
z3D`d<EMM(1!y)qJpps#%R320Cjf!Rj_8o7W-hoS2(m_LrWhm at 6h0UP2T;0f0*h;W6
z6AyWEbyh@;uv at t`_9>p_icT~2!KagM!1i)$yrOvWQ&{HzD`G2k<6VW_rRZECC)iIE
zmhW_#&*xORQZE_~W2N#x6}(Q-oKWxv1)og=h?Ojc^SbR<*!yS%>@tOI1}igpl+qv8
z*;*=r-OjC1qj(-tbPkXYK0flp_Hb+TDxR(I6t}k5Xb9|E3frRSd_ZxlboLQ>VE at 8x
z(HDwml;ZiNg5xDKd4~K$!TG+FD`YzLt<nvhyQ1+r%)lktg>(ZEms{3NEKg^TQDvTP
zY*hT!6L=@}z^Bf#O_t}0|Ka%@4M68bg;mezpVA1}*A+HR$;xjjzoW2f4j)juTW5cy
z64<|UTlAIUnW5<XOTiyh at agyx;Eh)!4VNgLEr$HiOrasz2e~zzis$|ClqX&`#pUa4
zHTmGVo;>JpwQM;x=Ht6W8MPRrWVH`aAJ`)byIf(9S(+y;&0b<2yuTDr{+%Lq0^|hy
zd%^PT&nPV3Umm^aGi9s?tbEseuHfpadoK)^dm)7e5Ni=%f at nNeH!hipi$=h%QP}4c
z_6L;yh;BS7Sb26y<#s9o+pUcKu`>1*@`3%0!oHxeZ<GHKz37Uf%=f-j{#?P;U4K_m
z>s8d)`M5`;A`M<*-uMB_8&8;D)#NPHjh8rtb~5xc$-Y6AV6O}G*I{e~^?+R=Ua=pA
zv1 at 1mto*3F7skFxBVZX%0d1kskXgl3dJztH!LAEqTd1T+FS;z)rZ851RCb2pY2q+_
zDGbL)2Grz7<)tuIepG%MhRcu2FT?P?6!*B!E}UQVxFedqNI9izSTgxav+eE6LR0Og
zfzoVNOTkh%+d?^IZq`6v*w?In3kA_1v-<7i-Qd;=?UY-VhZj^3H@%^oZt`w)YqzZ%
z8Y at kpm`$eUngPdBI*o28 at 8;218JNwc{ZoD_qE(S+!&*8GB!8wv27ttDG3~ESBA$)#
z0TL_DgDM&T60_B`w at f0QP4EG7YYHjLrm;<kx6RZFXHo8EWP)!0EV_tp%yv^to=v%1
zfTG(zn=Yaov%}PG1KkRAhiNZ%$fP`6Y%9cen%X-K%H0MBbkkz#BDyh8VurDlyB#RH
zUjs!qrrhN9EO*;``A0XJNuC{R=^F4$6fAe+8$GAOZ66dYp2|TNi=&Gbc`TNK6>b{a
znLz6*5hk9-%kx+<U8r=kObWv0(}fCdy;W{{r#ykKRbdj`t(4Y1W%7pur?Zw*0|lRQ
zldBS1yG(YAyp?5iZI@}k9UsaHaSyoI94qcw^6rLU6$E#iTK*gwuYzE;X)l~J>3m!|
zU#DO-gm*!>#zZjhE(q7)$xZn-OJ5s#YazTF!nLMmOQ7-H5Uw-r(c&0E7JFSR!OCI@
z1?wPO1K~ZUR)K$J)s)h;J*K^O%K4~tt{`tclxv|}Z?XUdYs+ZeUei7(d^3sFO5bh@
z?uGCk2=6nsC5hC!2g2yO&^_+P9~Zp%0rKvLVm%c1o7&k#8m~vL2Qab3P!Tf8_mnH-
ztbJWT;|KD{wGWyNrWTt-t^1(aVA_-UYZMI$RAp=VNtSjRc^jd<AKHz0Vo5Z<AKC{^
zd*_sQy$gTg at kEL#co69}K>Co$z9w%23Vg`a#t>w$o9UKQJ9(R+*a*cY6icV^MkqF;
zSh|ewt9A+JehM~2 at emXbo9sGy4?*#;seP(b>j5_o1|Iend5=J`35rLs2$E^M35qRP
z1j$m7Rk?(7ECpMjco>Rall7DLFciJmCCSu!P%7q=w-t&<pxBD#Y|!`-C>}NKnTAyK
z)w!5qg>RtXQ7C$$__V2Y8`SDWLDB6+x7jVc&XV^SBwHbQ3=1lS##<qI+|;7cJ?zGJ
z1)s`w3Lb~n)6i-&wT2XGeHvPAI5|>eVE%B<hP-X$ZHMMDXtwj65<G^b<in8wNw1sD
zwIr8N&<DvjNdC~&isw>m8zj-)g6>i2RYBepkZOn22~!KqrS$kDiuFBA>rR^X0RK2c
xi?&wAU`V%{f+yW9nsPea%t77`x0X5I8g;!RlW%&!0m?bWOX`K~qzk7W_&3g0Q!xMl

diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-const-folding.proftext b/llvm/test/tools/llvm-cov/Inputs/mcdc-const-folding.proftext
index 82335a8195faa..97d78a39f4356 100644
--- a/llvm/test/tools/llvm-cov/Inputs/mcdc-const-folding.proftext
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-const-folding.proftext
@@ -40,7 +40,7 @@ _Z5case2b
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0xa
+0x6
 
 
 _Z5case3b
@@ -55,7 +55,7 @@ _Z5case3b
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x9
+0x5
 
 
 _Z5case4b
@@ -70,7 +70,7 @@ _Z5case4b
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x2
+0x1
 
 
 _Z5case5b
@@ -85,7 +85,7 @@ _Z5case5b
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x6
+0x5
 
 
 _Z5case6b
@@ -100,7 +100,7 @@ _Z5case6b
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x5
+0x6
 
 
 _Z5case7b
@@ -166,7 +166,7 @@ _Z5caseabb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0xa2
+0xe
 
 
 _Z5casebbb
@@ -183,7 +183,7 @@ _Z5casebbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0xa1
+0xd
 
 
 _Z5casecbb
@@ -200,7 +200,7 @@ _Z5casecbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x2
+0x1
 
 
 _Z5casedbb
@@ -217,7 +217,7 @@ _Z5casedbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x12
+0x3
 
 
 _Z5caseebb
@@ -234,7 +234,7 @@ _Z5caseebb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x14
+0xa
 
 
 _Z5casefbb
@@ -251,7 +251,7 @@ _Z5casefbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x6
+0x9
 
 
 _Z5casegbb
@@ -268,7 +268,7 @@ _Z5casegbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x23
+0x7
 
 
 _Z5casehbb
@@ -302,7 +302,7 @@ _Z5caseibb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x83
+0xb
 
 
 _Z5casejbb
@@ -319,7 +319,7 @@ _Z5casejbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0xa1
+0xd
 
 
 _Z5casekbb
@@ -336,7 +336,7 @@ _Z5casekbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x12
+0x3
 
 
 _Z5caselbb
@@ -353,7 +353,7 @@ _Z5caselbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x12
+0x3
 
 
 _Z5casembb
@@ -370,7 +370,7 @@ _Z5casembb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x12
+0x3
 
 
 _Z5casenbb
@@ -387,7 +387,7 @@ _Z5casenbb
 # Num Bitmap Bytes:
 $1
 # Bitmap Byte Values:
-0x6
+0x9
 
 
 main
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-const.o b/llvm/test/tools/llvm-cov/Inputs/mcdc-const.o
index 1232088ee60fa0e1c96960f1ba11a0e7e7e982eb..915125370cb3d5b7a40bde18c50fd9b2f0e3ae5a 100644
GIT binary patch
delta 68
zcmeyN{zH9&4<pw^Upq#oi9H^SEEBI<GqOw;WHbSj;*(<;fr68lF=jAwZ{}xmWMpL8
U9LUVh!^kwbky(Co1%Cqz0E3|r^#A|>

delta 70
zcmeyN{zH9&4<qM9Upq#|i9H^SOcSqKGcrvUWHbSj;*(<;fr68lF=j9_Z02WjWSp$Q
WE3i3%`3E;6%j8C8`OOvl4J-h+&Jwl&

diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-const.proftext b/llvm/test/tools/llvm-cov/Inputs/mcdc-const.proftext
index 10253f26e0a68..16eba3a018080 100644
--- a/llvm/test/tools/llvm-cov/Inputs/mcdc-const.proftext
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-const.proftext
@@ -14,12 +14,10 @@ _Z4testbbbb
 0
 0
 # Num Bitmap Bytes:
-$4
+$2
 # Bitmap Byte Values:
 0x1
-0x2
-0x0
-0x0
+0x4
 
 
 main
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-general.o b/llvm/test/tools/llvm-cov/Inputs/mcdc-general.o
index afe6f95cf0b829a79efebe9718d3cbd04718d4aa..2d6934989b900ddc63bb498d2173b8a7127757ec 100644
GIT binary patch
delta 1562
zcmZ`(TWAzl7~X%zU1xTanVr34G8)?mq1jR&5>O%<GTG4JwzS3AhejK17lP?Sv07FU
z5shXj1{%ovSz5sd`_LlvC262^9|~RCf+dBxLd!xB5-HNM6e2?U5G6fl_DuI=!2|ho
zzRQ0*4EudgwP!X%)#A(j`$`lFg}miLEVmhEx6pi~mJ!!sZ?kYv+y~9?ewk^>PL&n!
z$HGh4LtSIF=p5Z&(fllL+4QDab|cgDK5gL1R$f{OS}4Qbdf`%l)Isl`!fAo(&Umq$
zy!^!c$gh3UJooEKbEEvkyzJu!-{5NF^~A{%@5BZ_yQ6loPLWU5PBn%Vtx5*7^4 at O?
zBH&HG#P0R~moLQ`!`|qXEki2!jdtax at 0R~kCs((BOZOk<X8b+1l$M+NS$j8oBKzL)
zpAK)Wo}2QQP#Rm*w?nUzHmA2VcpqcRfsPH|U*F|w at CJ3*iITE6zS(rHt8dbFyrqs)
z6bot}wW6l>Q(_^r?HZAa`S3C=VkXj&`htv1*618E+J}sI*3gEHo at 4kSvNKv?>xQyM
zTv=Lp7<oZqcGA1`MgFC*Q$epj;q=x)NMZkD?5{)Me$4B(lWS7D1U`;crcOwz&hAge
z2B%;}ZRf0{s*-vES*Cs>sdDaTIK$MhB$ZF~s=(jiXtZ13D^MAgsGVPG@{S4oyTr>K
z9!NZ|{f5AQO8ho<54QQ+pZBq(@~jU9COnSWd0o6|@QN3Ontl$yOXB%#8{*}9n)qOb
zArxaay at q_uc8*CNK1t9k&nIy{Zc;rl$yMxb>BjAtMza`cv7OH)AOA9gPG92+Q~h5P
z#`1mSw_Cz|i%oxEm3baW75E&%4v)A>>%Qk%lc$UM_)(E<wJC-(t+r$FChRo#%HT`p
zIq1hBRM`D>^cuEvMDj;iUNHHnUo-D}CM1tM{}sR54IVLTT%*MW$NZOAVaqy1w{X<z
z(?_|Vol)Gh`e+3e%cUx;gsZG6IFcA(R59VwX;fIe4J+v)o=9OlxktatKO1&btcG92
z`9vqG$^CQ>R?4LhFv8*-iYXWOk{YV1{d5Ob+9eGmEZ#wp#W~-#0;|nc*TNwbwKUek
qahz{!Ck4eemj+N_ at f}#UOQRUET_tYfx;;RHsMszJr!};<cm4;v&X1D-

delta 1631
zcmZ8fZD<r{5Z>9noV%CJ?tLYDS8a_{NLoUgrIx5@)(c5J at q@N#p`wToKMJKy+G|M*
zH4%@ZlxuSxXiNWv;*Ua=#6XCDG)HSOKl<Z>wg=~rC=`?+%^_-wmg~HGv$ENNoqgw-
zXP%jPcPl+}JrkWUSA1#Pm^u4Prl5b3pU-L8LX$+c{K~oO*}8kon6rNt^te{aFXnbK
zw!@sgR?tgS at ER9n>(aUFrMt at b?KPKR at lLkTB4pI0$`#qdb^+WKZn<qWHS2Nn)!e(x
zAI#Tt!+aiZ<T<hz2J??{M>rCb(Cn}8$luTHF8;7_jPd0yjVciI`p3`RJ41~dkZdn3
zk50kjlIrfq1($&cLgg?6{G#=LE9irQD*8GM)2Q8iTqRY!*o;*$pQkIO3tGKrV~zc4
z=o>lNf5vStKQKRV568_L?)!l`=Du0GF|o$GtO6B$Ti*KOCkwpPaq~%uX`Tj$__Mqz
zLF3Ex2osA6!xeciNZ6+gfs8*Yy`W%K*#@DRROl=~7$=*mP{z;0>yqDr(U~#Y`;An;
z5zQFtpwV*_FND`dDnch?MCCtb7Q-*dM6anGTA4dkaD#Rt{i@)QiT2I(tP=rQA5Lmk
z`mILrEW458AuMYae1^q{1$l&smHyJlROtM)-mnR at iF2Nq9XK3OcU|@IM85%!ulaC|
z&i`@!?>=1cH*s9WQp6hjJCHrZ at xMM?sIgexyIpVFJ<MCfcOvi*J>K*>;{r?i at I(WT
zKf9P5C55fU+szhq3vX}tiTZ~a at Zn-5ul4|*Znn~g0@?RmT}k=~Gr9$*@EyHl15>20
z1Kc6zev6a3l|Ike;P6+ltXuX?Uu~4?yp?bHa53EzzPrB=TCDVaUpDNkdML8+6pyx8
zw#>h>c!|9|1ucMkpE!m^QnmtF?~`?7iIg+0&ti?vZ{VATWgiUiy)MTBxYy-<QI*aG
zvR;?3T>VMmamqLg<(Vz!V}O^@j_rh>@Y7hYc2ev@)`^#6y|99{n1jQKBo4&8WJ$pf
z<9)c2P;oB48OE^|cVG(bgaiNJNW#%7;v<lSvD~yCE6H{oZPhW9?1Ck<lMamH2>A(|
zCLhHb`8l*(9qdV|#N15LbgKjNE^8j`Hb;@d5}sCDaj7Ya-?yb8j?--p?86%Q6KGow
YoWv3GE2NpgU#%`^#~Q_*Xs0^<2Ph|{3;+NC

diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-general.proftext b/llvm/test/tools/llvm-cov/Inputs/mcdc-general.proftext
index a83f036ddf2c9..2faca9da1b1e0 100644
--- a/llvm/test/tools/llvm-cov/Inputs/mcdc-general.proftext
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-general.proftext
@@ -24,14 +24,11 @@ _Z4testbbbb
 2
 1
 # Num Bitmap Bytes:
-$6
+$3
 # Bitmap Byte Values:
-0x2f
-0x8
-0xb
-0x9
-0x83
-0x80
+0xef
+0x77
+0x3
 
 
 main
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-macro.o b/llvm/test/tools/llvm-cov/Inputs/mcdc-macro.o
index 667ccd132d2fb848ae86b9bbbc72f7b3a917feab..8f458b962fe9ba316297da6b6b50ce72162c5d58 100644
GIT binary patch
delta 1280
zcmZ`&Z%7ki7{B*6*G;#(+q`)<D4qBrF)Oz(ZU$Z_h<->&k|?6Thy;mkvce$zlbbZm
zNS+`+R3t>7U4vi{;^>Rk7d5aV2>TL=7!G3z7VCL$HyaBdcz?I&{r#Tb^FHt0rhJRO
z2eqsyPS({*r%%P+Yq3o1PkXk6!H8zV9h1ST)+CEbU_E@$*f$<YlfFGD=5r47b(eR+
z$XlZsAu^78qYLKPJOqg}WH8 at xlR-M%za?DPTlEMx7kY%9)UcgW+?Ft;Zx`yL8$#q2
zlK)C}bWL6x{VYW0kxwcJ?Grk;e$jB4A<L^=$zf!eTnje35$-j}B%u|#nT-cddj;l*
z%Q|5`K5>FL2ixEasXQcc27gYwaDI)t?M}N}c;o44O32MyLuGID>-*3C-CB1xo9#IQ
zes-2v;TNkB8w5-~;!gCMx>@*G;wNTsSb`(~cPvesADcDMju<QSz#1>M at QTKJM$Pw4
zW31^m;guF%)OfCy_w?m|BhN4r%6k*`eZV^PQcM?dIT at DOB=FMOM=GJZR3>%MiP%KZ
zt)YMhefRXG)YAl`6Go6dlS_8l{YHKj;>ZpZu{I-r1YePzE at I6_{sJ6jvO7`4b{Tm}
zuYJ1*y9A*!nXFI;@(rfZ=SP8(eyG3kwrON^wv^r=Mt-_TE at jGr*kp15s_inV(eWrO
zq31EUY?IwBMOBZDst%Y$wyTJ}XRy~Gg`Ok2+c>0A`Or|($z8beXM3V|d0ym`?=q`9
zEK`m5(;k|i1^dndXAU~;ADltsM09GpHc6t1&k!;OUa^gca7%2ou3B at VIY^3)<Rqj;
zmEE?0&(TaSLCB#J2I7c!A&tm^*Qt^qgb=47jwnJJ at ilnMRiZ!$aSq~$^N>b-23|>p
z8HWTBsou)z|51i9gJ!7$#p!`<$&U_R7p)2*E<)U;La>~JZI>TAdn;7Z4k1K51tJIO
v3YBGe at X5`TkX3RP;)wl_mR0M3B{$131e8X$froyjnG8T&QDIX;PsQ^WqhlLQ

delta 1379
zcmZ`&T}WG39KYw}-ZWRuz4@~D=0!7RX(B!t5mE=s%@u8h%FwM}w60YvZu+p*5(*oo
zb=Z`~VypZs^sNYc&_2}(8+%yEwFMg}MccxJQgE=%rlAi`kd1cB{^#bzrn3FvoO6F4
z|BrKXv)pvEX);V#)v5Y$%~A8nCtc|$W_qimAPE at hzuTjQRKZlImy%smgS8i<nU=gd
zoiQicmORNl+{KS*7PVW}gm~pbC8zSCXl7e&Pi?8w7RkyMd%AR$)qjv)v|c*ub|t<i
zX)E#g_l^m>Z^G3~dEN^)2PP!HLZY96Q8(LNo9dUgcThc-9aLXio9aay+X<;x$<uEQ
zuWg}Zh-OmH>^pQWiAjTZ%%A7|V1opX7h4dlqHy|0f<5yzn&p at u{C!w!l5CA-X-htN
z_&*G{GS-?XTP^tuF_<Ma`XQH8a*f at 0oiI<Dr#{VLeV8ZJDigQadxH?BcZmS&)FdKA
z98E-8=y42CSQA~4k at gWc{3V?s`(W7lL3an%XvD>0oegX%o>oO~RYIl`HkHOP>6&=m
zahW<62*V*;^O%aOU1>b=E+Ygm{rtjjPM|)!6vAa(K7k4Xg>m_dU at bxxNC@mFc~dAx
zGk7aB(q``m!K~1Ny{NJ%Ih%`6_zXr+{hFhaTE}q;W>EdEOs&M{QkS1#1-mRlU!~Uf
zsLaDA>EZZk8P9V0fQ9E}Jo9&Q{OW)BKUkOOKReVU$4>U9G1&YLT%`#Wc&|z$?}JsT
z1slpdtRs87EIxz{RQH#u<#T>)SLg at Rt&t(<uF`^IWlmP-Tf2%NjKepm&g at WcaP<ef
z%i<1ofU7I;3(ong?Gf1}FxcV4Rl17~Y4^{*QDj&!)i%<Fv&t4BAHk64013goCnmcp
zY>Utf8=e^Hg^1Unp<OWSjgvDl=QUt95P&z{267W3K7%yE5bmQe=QHG4v6xy1^WGSK
z(h<KwABwOd?uJo+m?U7%Z;)lk;l2uyfI&WoA>6xQE?~&I{U66K5k~wmattEXh8*VH
z9oX>4=&A(ufjIWfRkPH{ZiDL1?dmvOk$CBk(~y%{=>s<mYjLU9iE}}>*AE#jOhzE5
i8Fajunb5=XB$F{FVMLG7KizO!kK?d8o!u)E-1{#TAWf?P

diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-macro.proftext b/llvm/test/tools/llvm-cov/Inputs/mcdc-macro.proftext
index 35ecc42b5802a..44057ffd7d885 100644
--- a/llvm/test/tools/llvm-cov/Inputs/mcdc-macro.proftext
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-macro.proftext
@@ -27,21 +27,12 @@ func
 0
 0
 # Num Bitmap Bytes:
-$13
+$4
 # Bitmap Byte Values:
 0x0
+0x9
 0x0
-0x0
-0x20
-0x8
-0x0
-0x20
-0x0
-0x0
-0x0
-0x0
-0x0
-0x0
+0x1
 
 
 func1
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-maxbs.o b/llvm/test/tools/llvm-cov/Inputs/mcdc-maxbs.o
index 8e592cf6563da92b98429e83244084649d49fd81..3aee8e5e4489cb55a322385b9b90c570f2d72c73 100644
GIT binary patch
delta 680
zcmZ8eL1+_E5dAZM&32RBWLMBl=%r#YMHJjnn)I?-5y?RiJrycaJ=ufMuF#?gD)FGA
zP#MJD+T$LzLFszXNDHaAs234Iy;Z#FB}ieN-TYv1;Qu#o-kbS<_pgjDk1UU&Z9G1F
zbmDA1-Xl0}Tgk2|wgF5wdo}PrM3QO!QEIHm;(mv&f_rN`s~p&fr-HU>eU-E};+bpt
z$oSXw^QDr#R-~ndOF^hgQ6??iSb7=_4RqX9awEo at rpkY?F1*&JcyQ$l{f24C(iuDt
zvbl;5P*>X2l9yqU4r<=Mt;EY=^E#GhLJT+Ov^P-dOE0**SD@(gVVcUc;S}A`UARaG
zc%P%U85b7mobHw$sv*dz^E#sVlf+*N|5L{me@)L>Z4am>=euz)KGJvHEq+pJ@@EPI
zD%Fj9u+ at BTtO9=4Daf66zA9 at UG<ugSXT$VqgjfOklbgUbNfpzF5n3>hV<>6e^l9E4
zqOMspYRUCEM(Mg)#b=TN%Qr5lB2r{kaYNEC%g0%yO5Vp1DPTCE(>lX8YYaO`p4?B{
z));npM8P+9)Cij<^HuEjn&x$?*gn?S!f=vrV*4;dUZG4yrwFsOkT27;Q^Ym?I>*Nj
MAHwjB4{;9t1w9d>oB#j-

delta 1144
zcmah{O=uHA6rP#Q-|nVOTdixPP?2CmtThW_E6BE9B&a>82M_U*OQjXTG^Gt%NMt=!
zA=37N)RTgOl9MGA8!t@|e}V^#y@<DXD(%IJcu`p2?9P^LE)MLz_rC9Y- at KXK`NK=G
z`8YeME+mc*jHWC<!BuSI?~tfgDHd-XjOvY4$=2v!7Up^iQwkLfGp)0e4bk$3x0qHs
z*Iwmf(XzcFXuYO4Oe+(Cdg-D}C!e|SZ_~On5?Op-3h(3|x=qEgv4KeMJ+wh1XFk1V
zT5NVaWsTaS2-LJrO!w{Pr)MsR{6DAZ=Eiz0WwC{lcBAD$pLYGyxqbFUhy&SO+ph(!
z*Q(BmGm|d_RF%-yv~JHla at tfre#vPoVonJ3(rc8$EWJ!g<umQ1RDveU(jmAa>D}*a
z4Iv#ElOq3Cc`U8bs7tLN+(j5!cWKD_KhR-V4rnwDm+*ZZcKjNhg1Z4N`aq}{#vnfZ
zq6V&ymRs19qF#e0vKt;YjQL;7Sxx8+YSB#(%bi{J7u5Y)f$*Eb<?g%RDM`SC^UwH4
zc(!|R?&cHvLmu3#k9lye?-6>#!3*}ryulsoyr;oybk&1%qnI$d*@C+lH{F7}8{gl9
zA0foO%jbItLe7W{U?ez4*DH<S6Ux5JFd?7oEDNbnkPfKJeM&yy)awj>%BR>ZA0!lm
z{(y01nB{#?Rt#2Su%#Gsi2r at KVvtn^S<wd*sv-9aP=aN3kj?pEOEp+hf<)M0c?l*k
zq+}>#SV9iNsstH!0BUNSJw=N)12)wT7z!uZM at OEQA<=HI5Rw?Wa0Cp;e7tKh5@$&q
UFk-NmcqR;A(Hp}n^o|_;2mF=y4gdfE

diff --git a/llvm/test/tools/llvm-cov/mcdc-maxbs.test b/llvm/test/tools/llvm-cov/mcdc-maxbs.test
index bbb5fb8b6059a..15f4e4dc481f3 100644
--- a/llvm/test/tools/llvm-cov/mcdc-maxbs.test
+++ b/llvm/test/tools/llvm-cov/mcdc-maxbs.test
@@ -31,7 +31,7 @@
 # Instructions for regenerating the test object:
 
 cd %S/Inputs # or copy %S/Inputs/mcdc-maxbs.c into the working directory
-clang -O3 -fcoverage-mcdc -fprofile-instr-generate \
+clang -Os -fcoverage-mcdc -fprofile-instr-generate \
     -fcoverage-mapping -fcoverage-compilation-dir=. \
     -mllvm -enable-name-compression=false \
     mcdc-maxbs.c -c -o mcdc-maxbs.o
diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index c5b7c26bef9a7..fcfa65f6e29e1 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -872,7 +872,7 @@ TEST_P(CoverageMappingTest, non_code_region_bitmask) {
   addCMR(Counter::getCounter(2), "file", 1, 1, 5, 5);
   addCMR(Counter::getCounter(3), "file", 1, 1, 5, 5);
 
-  addMCDCDecisionCMR(0, 2, "file", 7, 1, 7, 6);
+  addMCDCDecisionCMR(3, 2, "file", 7, 1, 7, 6);
   addMCDCBranchCMR(Counter::getCounter(0), Counter::getCounter(1), 0, {-1, 1},
                    "file", 7, 2, 7, 3);
   addMCDCBranchCMR(Counter::getCounter(2), Counter::getCounter(3), 1, {-1, -1},

>From 0ffad9c01ec8c7074534cd0205f9f8eab8d22665 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 21 Feb 2024 23:44:11 +0900
Subject: [PATCH 12/33] Update testcases

---
 clang/test/Profile/c-mcdc-class.cpp        | 36 ++++++-------
 clang/test/Profile/c-mcdc-nested-ternary.c | 34 ++++++------
 clang/test/Profile/c-mcdc-not.c            | 52 +++++++++---------
 clang/test/Profile/c-mcdc.c                | 62 ++++++++++------------
 4 files changed, 89 insertions(+), 95 deletions(-)

diff --git a/clang/test/Profile/c-mcdc-class.cpp b/clang/test/Profile/c-mcdc-class.cpp
index 2206a39ee4ffb..488e7a47a57c4 100644
--- a/clang/test/Profile/c-mcdc-class.cpp
+++ b/clang/test/Profile/c-mcdc-class.cpp
@@ -36,23 +36,23 @@ Value::~Value(void) {
 // SHIFT FIRST CONDITION WITH ID = 0.
 // MCDCCTOR:  %[[LAB1:[0-9]+]] = load i32, ptr %value, align 4
 // MCDCCTOR-DAG:  %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 2
-// MCDCCTOR-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDCCTOR-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDCCTOR-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
-// MCDCCTOR-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDCCTOR-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDCCTOR-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDCCTOR-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDCCTOR-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDCCTOR-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT SECOND CONDITION WITH ID = 1.
 // MCDCCTOR:  %[[LAB1:[0-9]+]] = load i32, ptr %value2, align 4
 // MCDCCTOR-DAG:  %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 6
-// MCDCCTOR-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDCCTOR-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDCCTOR-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
-// MCDCCTOR-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDCCTOR-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDCCTOR-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 2
+// MCDCCTOR-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
+// MCDCCTOR-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDCCTOR-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // UPDATE FINAL BITMASK WITH RESULT.
-// MCDCCTOR-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
+// MCDCCTOR-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
 // MCDCCTOR:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
 // MCDCCTOR:  %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
 // MCDCCTOR:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm__ZN5ValueC2Ev to i64), %[[LAB2]]
@@ -75,23 +75,23 @@ Value::~Value(void) {
 // SHIFT FIRST CONDITION WITH ID = 0.
 // MCDCDTOR:  %[[LAB1:[0-9]+]] = load i32, ptr %value, align 4
 // MCDCDTOR-DAG:  %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 2
-// MCDCDTOR-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDCDTOR-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDCDTOR-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
-// MCDCDTOR-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDCDTOR-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDCDTOR-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDCDTOR-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDCDTOR-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDCDTOR-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT SECOND CONDITION WITH ID = 1.
 // MCDCDTOR:  %[[LAB1:[0-9]+]] = load i32, ptr %value2, align 4
 // MCDCDTOR-DAG:  %[[BOOL:cmp[0-9]*]] = icmp ne i32 %[[LAB1]], 3
-// MCDCDTOR-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDCDTOR-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDCDTOR-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
-// MCDCDTOR-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDCDTOR-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDCDTOR-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 2
+// MCDCDTOR-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
+// MCDCDTOR-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDCDTOR-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // UPDATE FINAL BITMASK WITH RESULT.
-// MCDCDTOR-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
+// MCDCDTOR-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
 // MCDCDTOR:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
 // MCDCDTOR:  %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
 // MCDCDTOR:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm__ZN5ValueD2Ev to i64), %[[LAB2]]
diff --git a/clang/test/Profile/c-mcdc-nested-ternary.c b/clang/test/Profile/c-mcdc-nested-ternary.c
index 4b014e07f6df5..c5306d7d3ea6a 100644
--- a/clang/test/Profile/c-mcdc-nested-ternary.c
+++ b/clang/test/Profile/c-mcdc-nested-ternary.c
@@ -20,42 +20,42 @@ int test(int b, int c, int d, int e, int f) {
 // MCDC-LABEL: cond.true:
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %c.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // TERNARY FALSE SHOULD SHIFT ID = 0 FOR CONDITION 'd'.
 // MCDC-LABEL: cond.false:
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %d.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT SECOND CONDITION WITH ID = 2.
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %e.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 2
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT THIRD CONDITION WITH ID = 1.
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %f.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 3
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 2
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // UPDATE FINAL BITMASK WITH RESULT.
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
 // MCDC:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
 // MCDC:  %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
 // MCDC:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
diff --git a/clang/test/Profile/c-mcdc-not.c b/clang/test/Profile/c-mcdc-not.c
index aa638b9680b84..98da3b4581c9a 100644
--- a/clang/test/Profile/c-mcdc-not.c
+++ b/clang/test/Profile/c-mcdc-not.c
@@ -9,7 +9,7 @@ int test(int a, int b, int c, int d, int e, int f) {
 // NOMCDC-NOT: __profbm_test
 
 // MCDC BOOKKEEPING.
-// MCDC: @__profbm_test = private global [8 x i8] zeroinitializer
+// MCDC: @__profbm_test = private global [2 x i8] zeroinitializer
 // MCDC: @__profc_test = private global [9 x i64] zeroinitializer
 
 // ALLOCATE MCDC TEMP AND ZERO IT.
@@ -21,61 +21,61 @@ int test(int a, int b, int c, int d, int e, int f) {
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %a.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
 // MCDC-DAG:  %[[LNOT:lnot[0-9]*]] = xor i1 %[[BOOL]]
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[LNOT]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[LNOT]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT SECOND CONDITION WITH ID = 2.
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %b.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 2
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 14
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT THIRD CONDITION WITH ID = 1.
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %c.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
 // MCDC-DAG:  %[[LNOT:lnot[0-9]*]] = xor i1 %[[BOOL]]
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[LNOT]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[LNOT]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT FOURTH CONDITION WITH ID = 4.
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %d.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 4
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 12
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 2
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT FIFTH CONDITION WITH ID = 3.
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %e.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 3
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT SIXTH CONDITION WITH ID = 5.
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %f.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
 // MCDC-DAG:  %[[LNOT:lnot[0-9]*]] = xor i1 %[[BOOL]]
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[LNOT]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 5
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 8
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 4
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[LNOT]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // UPDATE FINAL BITMASK WITH RESULT.
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
 // MCDC:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
 // MCDC:  %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
 // MCDC:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]
diff --git a/clang/test/Profile/c-mcdc.c b/clang/test/Profile/c-mcdc.c
index ac845d204853d..7c10fb3618e36 100644
--- a/clang/test/Profile/c-mcdc.c
+++ b/clang/test/Profile/c-mcdc.c
@@ -11,85 +11,79 @@ int test(int a, int b, int c, int d, int e, int f) {
 // NOPROFPASS-NOT: __profbm_test
 
 // MCDC BOOKKEEPING.
-// MCDC: @__profbm_test = private global [8 x i8] zeroinitializer
+// MCDC: @__profbm_test = private global [2 x i8] zeroinitializer
 // MCDC: @__profc_test = private global [9 x i64] zeroinitializer
 
 // ALLOCATE MCDC TEMP AND ZERO IT.
 // NOPROFPASS-LABEL: @test(
-// NOPROFPASS: call void @llvm.instrprof.mcdc.parameters(ptr @__profn_test, i64 [[HASH:[0-9]+]], i32 8)
+// NOPROFPASS: call void @llvm.instrprof.mcdc.parameters(ptr @__profn_test, i64 [[HASH:[0-9]+]], i32 2)
 // MCDC-LABEL: @test(
 // MCDC: %mcdc.addr = alloca i32, align 4
 // MCDC: store i32 0, ptr %mcdc.addr, align 4
 
 // SHIFT FIRST CONDITION WITH ID = 0.
-// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 0, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %a.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 0
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT SECOND CONDITION WITH ID = 2.
 // NOPROFPASS-LABEL: land.lhs.true:
-// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 2, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %b.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 2
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 14
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 1
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT THIRD CONDITION WITH ID = 1.
 // NOPROFPASS-LABEL: lor.rhs:
-// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 1, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %c.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 1
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT FOURTH CONDITION WITH ID = 4.
 // NOPROFPASS-LABEL: land.lhs.true3:
-// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 4, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %d.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 4
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 12
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 2
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT FIFTH CONDITION WITH ID = 3.
 // NOPROFPASS-LABEL: lor.rhs6:
-// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 3, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %e.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 3
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 0
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // SHIFT SIXTH CONDITION WITH ID = 5.
 // NOPROFPASS-LABEL: land.rhs:
-// NOPROFPASS: call void @llvm.instrprof.mcdc.condbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 5, ptr %mcdc.addr, i1 %tobool{{[0-9]*}})
 // MCDC:  %[[LAB1:[0-9]+]] = load i32, ptr %f.addr, align 4
 // MCDC-DAG:  %[[BOOL:tobool[0-9]*]] = icmp ne i32 %[[LAB1]], 0
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
-// MCDC-DAG:  %[[LAB2:[0-9]+]] = zext i1 %[[BOOL]] to i32
-// MCDC-DAG:  %[[LAB3:[0-9]+]] = shl i32 %[[LAB2]], 5
-// MCDC-DAG:  %[[LAB4:[0-9]+]] = or i32 %[[TEMP]], %[[LAB3]]
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
+// MCDC-DAG:  %[[LAB2:[0-9]+]] = add i32 %[[TEMP]], 8
+// MCDC-DAG:  %[[LAB3:[0-9]+]] = add i32 %[[TEMP]], 4
+// MCDC-DAG:  %[[LAB4:[0-9]+]] = select i1 %[[BOOL]], i32 %[[LAB2]], i32 %[[LAB3]]
 // MCDC-DAG:  store i32 %[[LAB4]], ptr %mcdc.addr, align 4
 
 // UPDATE FINAL BITMASK WITH RESULT.
 // NOPROFPASS-LABEL: lor.end:
-// NOPROFPASS: call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 8, i32 0, ptr %mcdc.addr)
-// MCDC-DAG:  %[[TEMP:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
+// NOPROFPASS: call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 15, i32 0, ptr %mcdc.addr)
+// MCDC-DAG:  %[[TEMP:mcdc.*]] = load i32, ptr %mcdc.addr, align 4
 // MCDC:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
 // MCDC:  %[[LAB2:[0-9]+]] = zext i32 %[[LAB1]] to i64
 // MCDC:  %[[LAB3:[0-9]+]] = add i64 ptrtoint (ptr @__profbm_test to i64), %[[LAB2]]

>From c96fd2cd04cc9e688877368a8c28c87c88d68533 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 22 Feb 2024 00:20:48 +0900
Subject: [PATCH 13/33] Use llvm::sort

---
 llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 8e6205c4b6166..7a0a524fd71f8 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -294,7 +294,7 @@ mcdc::TVIdxBuilder::TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs,
     }
   }
 
-  std::sort(Decisions.begin(), Decisions.end());
+  llvm::sort(Decisions);
 
   // Assign TestVector Indices in Decision Nodes
   int64_t CurIdx = 0;

>From 357a693081628b916478d69820120025109c61b8 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 22 Feb 2024 00:28:21 +0900
Subject: [PATCH 14/33] EXPECT_

---
 .../ProfileData/CoverageMappingTest.cpp          | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index c5b7c26bef9a7..f063a33205b30 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -1088,9 +1088,9 @@ TEST(CoverageMappingTest, TVIdxBuilder) {
   int Offset = 1000;
   auto TheBuilder = mcdc::TVIdxBuilder(
       SmallVector<mcdc::ConditionIDs>(ArrayRef(Branches)), Offset);
-  ASSERT_TRUE(TheBuilder.NumTestVectors < TheBuilder.HardMaxTVs);
-  ASSERT_EQ(TheBuilder.Indices.size(), 6u);
-  ASSERT_EQ(TheBuilder.NumTestVectors, 15);
+  EXPECT_TRUE(TheBuilder.NumTestVectors < TheBuilder.HardMaxTVs);
+  EXPECT_EQ(TheBuilder.Indices.size(), 6u);
+  EXPECT_EQ(TheBuilder.NumTestVectors, 15);
 
   std::map<int, int> Decisions;
   for (unsigned I = 0; I < TheBuilder.Indices.size(); ++I) {
@@ -1106,15 +1106,15 @@ TEST(CoverageMappingTest, TVIdxBuilder) {
         {2, {2, 1012}},
         {4, {1004, 1008}},
     }};
-    ASSERT_EQ(TheBuilder.Indices[I], IndicesRefs[I].Indices);
+    EXPECT_EQ(TheBuilder.Indices[I], IndicesRefs[I].Indices);
 
 #ifndef NDEBUG
     const auto &Node = TheBuilder.SavedNodes[I];
-    ASSERT_EQ(Node.Width, IndicesRefs[I].Width);
+    EXPECT_EQ(Node.Width, IndicesRefs[I].Width);
     for (int C = 0; C < 2; ++C) {
       auto Index = TheBuilder.Indices[I][C];
       if (Node.NextIDs[C] < 0)
-        ASSERT_TRUE(Decisions.insert({Index, Node.Width}).second);
+        EXPECT_TRUE(Decisions.insert({Index, Node.Width}).second);
     }
 #endif
   }
@@ -1122,11 +1122,11 @@ TEST(CoverageMappingTest, TVIdxBuilder) {
 #ifndef NDEBUG
   int NextIdx = Offset;
   for (const auto [Index, Width] : Decisions) {
-    ASSERT_EQ(Index, NextIdx);
+    EXPECT_EQ(Index, NextIdx);
     NextIdx += Width;
   }
   // The sum of Width(s) is NumTVs.
-  ASSERT_EQ(NextIdx, Offset + TheBuilder.NumTestVectors);
+  EXPECT_EQ(NextIdx, Offset + TheBuilder.NumTestVectors);
 #endif
 }
 

>From 14c795eaa2faaf27790598886cd82659348d231b Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 22 Feb 2024 01:11:59 +0900
Subject: [PATCH 15/33] Hide NConds

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

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index ec51023a2d205..5eaf6c8f4222d 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -2016,8 +2016,8 @@ struct CounterCoverageMappingBuilder
   void RewindDecision(unsigned Since) {
 #ifndef NDEBUG
     llvm::DenseSet<mcdc::ConditionID> SeenIDs;
-#endif
     unsigned NConds = 0;
+#endif
 
     assert(Since <= SourceRegions.size());
     auto I = SourceRegions.begin() + Since;
@@ -2025,9 +2025,11 @@ struct CounterCoverageMappingBuilder
       if (I->isMCDCDecision()) {
         assert(I->getMCDCDecisionParams().BitmapIdx == 0 &&
                "It should be valid");
+#ifndef NDEBUG
         assert(NConds == 0 && "Duplicate MCDCDecision");
         NConds = I->getMCDCDecisionParams().NumConditions;
         assert(NConds > 0 && "Malformed MCDCDecision");
+#endif
         I = SourceRegions.erase(I);
         continue;
       }
@@ -2043,7 +2045,6 @@ struct CounterCoverageMappingBuilder
 
     assert(NConds > 0 && "MCDCDecision wasn't found");
     assert(SeenIDs.size() == NConds && "Unexpected number of MCDCBranch(es)");
-    (void)NConds;
   }
 
   void VisitBinLAnd(const BinaryOperator *E) {

>From 662bdd6f390092088608da7d9c9b1fc847e3458a Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 25 Feb 2024 22:03:23 +0900
Subject: [PATCH 16/33] Reformat

---
 llvm/test/tools/llvm-cov/mcdc-maxbs.test | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/test/tools/llvm-cov/mcdc-maxbs.test b/llvm/test/tools/llvm-cov/mcdc-maxbs.test
index e1f76c7eef4a5..c6bd18048fb95 100644
--- a/llvm/test/tools/llvm-cov/mcdc-maxbs.test
+++ b/llvm/test/tools/llvm-cov/mcdc-maxbs.test
@@ -31,6 +31,7 @@
 # Instructions for regenerating the test object:
 
 cd %S/Inputs # or copy %S/Inputs/mcdc-maxbs.c into the working directory
+
 clang -Os -fcoverage-mcdc -fprofile-instr-generate \
     -fcoverage-mapping -fcoverage-compilation-dir=. \
     -mllvm -enable-name-compression=false \

>From 90bf8e9ac20df7abe83de84fb75e8e5b68dd458d Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 27 Feb 2024 07:30:29 +0900
Subject: [PATCH 17/33] Clarify bool

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

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index eac04fe3b5aee..7660be39cece8 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -184,8 +184,8 @@ class SourceMappingRegion {
 
   bool isMCDCBranch() const {
     const auto *BranchParams = std::get_if<mcdc::BranchParameters>(&MCDCParams);
-    assert(!BranchParams || BranchParams->ID >= 0);
-    return BranchParams;
+    assert(BranchParams == nullptr || BranchParams->ID >= 0);
+    return (BranchParams != nullptr);
   }
 
   const auto &getMCDCBranchParams() const {
@@ -195,8 +195,8 @@ class SourceMappingRegion {
   bool isMCDCDecision() const {
     const auto *DecisionParams =
         std::get_if<mcdc::DecisionParameters>(&MCDCParams);
-    assert(!DecisionParams || DecisionParams->NumConditions > 0);
-    return DecisionParams;
+    assert(DecisionParams == nullptr || DecisionParams->NumConditions > 0);
+    return (DecisionParams != nullptr);
   }
 
   const auto &getMCDCDecisionParams() const {

>From 9eb695166a3e6d09bae4c0ce337bd3ab6560f723 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 27 Feb 2024 07:30:29 +0900
Subject: [PATCH 18/33] Update comments

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

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 7660be39cece8..41dcba3d32260 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1982,6 +1982,7 @@ struct CounterCoverageMappingBuilder
     if (NumConds == 0)
       return;
 
+    // Extract [ID, Conds] to construct the graph.
     llvm::SmallVector<mcdc::ConditionIDs> CondIDs(NumConds);
     for (const auto &SR : ArrayRef(SourceRegions).slice(Since)) {
       if (SR.isMCDCBranch()) {
@@ -1990,9 +1991,9 @@ struct CounterCoverageMappingBuilder
       }
     }
 
+    // Construct the graph and calculate `Indices`.
     mcdc::TVIdxBuilder Builder(CondIDs);
     auto NumTVs = Builder.NumTestVectors;
-    assert(MCDCState.DecisionByStmt.contains(E));
     auto MaxTVs = mcdc::TVIdxBuilder::HardMaxTVs;
 
     if (NumTVs >= MaxTVs) {
@@ -2001,7 +2002,8 @@ struct CounterCoverageMappingBuilder
       return;
     }
 
-    // The state for CodeGenPGO
+    // Update the state for CodeGenPGO
+    assert(MCDCState.DecisionByStmt.contains(E));
     MCDCState.DecisionByStmt[E] = {
         MCDCState.BitmapBits, // Top
         std::move(Builder.Indices),

>From 86d67c65e109cbf9748d264456c4d2e88ade6065 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 27 Feb 2024 07:30:29 +0900
Subject: [PATCH 19/33] Use MutableArrayRef :)

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

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 41dcba3d32260..2985660a750e4 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -2030,11 +2030,10 @@ struct CounterCoverageMappingBuilder
     Diag.Report(E->getBeginLoc(), DiagID) << NumTVs << MaxTVs;
 
     // Restore MCDCBranch to Branch.
-    for (auto I = SourceRegions.begin() + Since, E = SourceRegions.end();
-         I != E; ++I) {
-      assert(!I->isMCDCDecision() && "Decision shouldn't be seen here");
-      if (I->isMCDCBranch())
-        I->resetMCDCParams();
+    for (auto &SR : MutableArrayRef(SourceRegions).slice(Since)) {
+      assert(!SR.isMCDCDecision() && "Decision shouldn't be seen here");
+      if (SR.isMCDCBranch())
+        SR.resetMCDCParams();
     }
 
     // Tell CodeGenPGO not to instrument.

>From dd6f8bee84e5c65e8619b6863ebbfc455797953f Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 9 May 2024 16:51:02 +0900
Subject: [PATCH 20/33] Clarify 3rd arg of mcdc.tvbitmap.update is unused

---
 clang/lib/CodeGen/CodeGenPGO.cpp | 2 +-
 clang/test/Profile/c-mcdc.c      | 2 +-
 llvm/docs/LangRef.rst            | 7 +++----
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 0f1dd3c9310e6..1e499208c6c87 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1257,7 +1257,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
   // index represents an executed test vector.
   llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
                           Builder.getInt64(FunctionHash),
-                          Builder.getInt32(RegionMCDCState->BitmapBits),
+                          Builder.getInt32(0), // Unused
                           Builder.getInt32(MCDCTestVectorBitmapOffset),
                           MCDCCondBitmapAddr.emitRawPointer(CGF)};
   Builder.CreateCall(
diff --git a/clang/test/Profile/c-mcdc.c b/clang/test/Profile/c-mcdc.c
index 908dc339b4660..7277f171e610c 100644
--- a/clang/test/Profile/c-mcdc.c
+++ b/clang/test/Profile/c-mcdc.c
@@ -82,7 +82,7 @@ int test(int a, int b, int c, int d, int e, int f) {
 
 // UPDATE FINAL BITMASK WITH RESULT.
 // NOPROFPASS-LABEL: lor.end:
-// NOPROFPASS: call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 15, i32 0, ptr %mcdc.addr)
+// NOPROFPASS: call void @llvm.instrprof.mcdc.tvbitmap.update(ptr @__profn_test, i64 [[HASH]], i32 0, i32 0, ptr %mcdc.addr)
 // MCDC-DAG:  %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4
 // MCDC:  %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0
 // MCDC:  %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index f6ada292b93b1..9bfab3f5ae4b3 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14337,7 +14337,7 @@ Syntax:
 ::
 
       declare void @llvm.instrprof.mcdc.tvbitmap.update(ptr <name>, i64 <hash>,
-                                                        i32 <bitmap-bytes>)
+                                                        i32 <unused>)
                                                         i32 <bitmap-index>,
                                                         ptr <mcdc-temp-addr>)
 
@@ -14362,10 +14362,9 @@ name of the entity being instrumented. This should generally be the
 The second argument is a hash value that can be used by the consumer
 of the profile data to detect changes to the instrumented source.
 
-The third argument is the number of bitmap bytes required by the function to
-record the number of test vectors executed for each boolean expression.
+The third argument is not used.
 
-The fourth argument is the byte index into the global test vector bitmap
+The fourth argument is the bit index into the global test vector bitmap
 corresponding to the function.
 
 The fifth argument is the address of the condition bitmap, which contains a

>From cdd553197a2631217529c8379c2956418af840f7 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 8 May 2024 23:28:39 +0900
Subject: [PATCH 21/33] Modify 3rd arg of mcdc.parameters to bits

---
 clang/lib/CodeGen/CodeGenPGO.cpp                      |  8 +++-----
 clang/test/Profile/c-mcdc.c                           |  2 +-
 llvm/docs/LangRef.rst                                 |  4 ++--
 llvm/include/llvm/IR/IntrinsicInst.h                  | 11 +++++++++--
 .../lib/Transforms/Instrumentation/InstrProfiling.cpp |  4 ++--
 .../InstrProfiling/inline-data-var-create.ll          |  6 +++---
 6 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 1e499208c6c87..156f34c3c56bc 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1224,11 +1224,9 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) {
   // Emit intrinsic representing MCDC bitmap parameters at function entry.
   // This is used by the instrumentation pass, but it isn't actually lowered to
   // anything.
-  llvm::Value *Args[3] = {
-      llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
-      Builder.getInt64(FunctionHash),
-      Builder.getInt32(llvm::alignTo(RegionMCDCState->BitmapBits, CHAR_BIT) /
-                       CHAR_BIT)};
+  llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
+                          Builder.getInt64(FunctionHash),
+                          Builder.getInt32(RegionMCDCState->BitmapBits)};
   Builder.CreateCall(
       CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args);
 }
diff --git a/clang/test/Profile/c-mcdc.c b/clang/test/Profile/c-mcdc.c
index 7277f171e610c..251c18baa861d 100644
--- a/clang/test/Profile/c-mcdc.c
+++ b/clang/test/Profile/c-mcdc.c
@@ -16,7 +16,7 @@ int test(int a, int b, int c, int d, int e, int f) {
 
 // ALLOCATE MCDC TEMP AND ZERO IT.
 // NOPROFPASS-LABEL: @test(
-// NOPROFPASS: call void @llvm.instrprof.mcdc.parameters(ptr @__profn_test, i64 [[HASH:[0-9]+]], i32 2)
+// NOPROFPASS: call void @llvm.instrprof.mcdc.parameters(ptr @__profn_test, i64 [[HASH:[0-9]+]], i32 15)
 // MCDC-LABEL: @test(
 // MCDC: %mcdc.addr = alloca i32, align 4
 // MCDC: store i32 0, ptr %mcdc.addr, align 4
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 9bfab3f5ae4b3..331029080e32f 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14252,7 +14252,7 @@ Syntax:
 ::
 
       declare void @llvm.instrprof.mcdc.parameters(ptr <name>, i64 <hash>,
-                                                   i32 <bitmap-bytes>)
+                                                   i32 <bitmap-bits>)
 
 Overview:
 """""""""
@@ -14270,7 +14270,7 @@ name of the entity being instrumented. This should generally be the
 The second argument is a hash value that can be used by the consumer
 of the profile data to detect changes to the instrumented source.
 
-The third argument is the number of bitmap bytes required by the function to
+The third argument is the number of bitmap bits required by the function to
 record the number of test vectors executed for each boolean expression.
 
 Semantics:
diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h
index 4f22720f1c558..77ef5a4f6f87e 100644
--- a/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/llvm/include/llvm/IR/IntrinsicInst.h
@@ -33,6 +33,7 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/MathExtras.h"
 #include <cassert>
 #include <cstdint>
 #include <optional>
@@ -1564,11 +1565,17 @@ class InstrProfMCDCBitmapInstBase : public InstrProfInstBase {
     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
   }
 
-  /// \return The number of bytes used for the MCDC bitmaps for the instrumented
+  /// \return The number of bits used for the MCDC bitmaps for the instrumented
   /// function.
-  ConstantInt *getNumBitmapBytes() const {
+  ConstantInt *getNumBitmapBits() const {
     return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
   }
+
+  /// \return The number of bytes used for the MCDC bitmaps for the instrumented
+  /// function.
+  auto getNumBitmapBytes() const {
+    return alignTo(getNumBitmapBits()->getZExtValue(), CHAR_BIT) / CHAR_BIT;
+  }
 };
 
 /// This represents the llvm.instrprof.mcdc.parameters intrinsic.
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index 442228e4342e2..0c79eaa812b5f 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -1414,7 +1414,7 @@ GlobalVariable *
 InstrLowerer::createRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc,
                                   StringRef Name,
                                   GlobalValue::LinkageTypes Linkage) {
-  uint64_t NumBytes = Inc->getNumBitmapBytes()->getZExtValue();
+  uint64_t NumBytes = Inc->getNumBitmapBytes();
   auto *BitmapTy = ArrayType::get(Type::getInt8Ty(M.getContext()), NumBytes);
   auto GV = new GlobalVariable(M, BitmapTy, false, Linkage,
                                Constant::getNullValue(BitmapTy), Name);
@@ -1433,7 +1433,7 @@ InstrLowerer::getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc) {
   // the corresponding profile section.
   auto *BitmapPtr = setupProfileSection(Inc, IPSK_bitmap);
   PD.RegionBitmaps = BitmapPtr;
-  PD.NumBitmapBytes = Inc->getNumBitmapBytes()->getZExtValue();
+  PD.NumBitmapBytes = Inc->getNumBitmapBytes();
   return PD.RegionBitmaps;
 }
 
diff --git a/llvm/test/Instrumentation/InstrProfiling/inline-data-var-create.ll b/llvm/test/Instrumentation/InstrProfiling/inline-data-var-create.ll
index 7c064f547141f..456103164378e 100644
--- a/llvm/test/Instrumentation/InstrProfiling/inline-data-var-create.ll
+++ b/llvm/test/Instrumentation/InstrProfiling/inline-data-var-create.ll
@@ -27,21 +27,21 @@ declare void @llvm.instrprof.mcdc.parameters(ptr %0, i64 %1, i32 %2)
 
 define internal void @foobar() {
   call void @llvm.instrprof.increment(ptr @__profn_foobar, i64 123456, i32 32, i32 0)
-  call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foobar, i64 123456, i32 99)
+  call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foobar, i64 123456, i32 792)
 
   ret void
 }
 
 define void @foo() {
   call void @llvm.instrprof.increment(ptr @__profn_foo, i64 123456, i32 32, i32 0)
-  call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foo, i64 123456, i32 21)
+  call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foo, i64 123456, i32 168)
   call void @foobar()
   ret void
 }
 
 define void @bar() {
   call void @llvm.instrprof.increment(ptr @__profn_bar, i64 123456, i32 32, i32 0)
-  call void @llvm.instrprof.mcdc.parameters(ptr @__profn_bar, i64 123456, i32 23)
+  call void @llvm.instrprof.mcdc.parameters(ptr @__profn_bar, i64 123456, i32 184)
   call void @foobar()
   ret void
 }

>From 54e60444652745ce88accfcb81bac7ae0d43eb1d Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 9 May 2024 19:04:24 +0900
Subject: [PATCH 22/33] isMCDCBranch: Remove assert

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

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 9c549ba7f4ebd..12e38ab12c739 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -191,9 +191,7 @@ class SourceMappingRegion {
   bool isBranch() const { return FalseCount.has_value(); }
 
   bool isMCDCBranch() const {
-    const auto *BranchParams = std::get_if<mcdc::BranchParameters>(&MCDCParams);
-    assert(BranchParams == nullptr || BranchParams->ID >= 0);
-    return (BranchParams != nullptr);
+    return std::holds_alternative<mcdc::BranchParameters>(MCDCParams);
   }
 
   const auto &getMCDCBranchParams() const {

>From b1a7100e742c5a6f8efd06699214e33bcf6bde87 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 9 May 2024 19:34:43 +0900
Subject: [PATCH 23/33] isMCDCDecision: Remove assert

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

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 12e38ab12c739..27f157b2d9951 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -199,10 +199,7 @@ class SourceMappingRegion {
   }
 
   bool isMCDCDecision() const {
-    const auto *DecisionParams =
-        std::get_if<mcdc::DecisionParameters>(&MCDCParams);
-    assert(DecisionParams == nullptr || DecisionParams->NumConditions > 0);
-    return (DecisionParams != nullptr);
+    return std::holds_alternative<mcdc::DecisionParameters>(MCDCParams);
   }
 
   const auto &getMCDCDecisionParams() const {

>From 39802c5daa26921886b449e2359daf26c8f7bc82 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 14 May 2024 23:12:57 +0900
Subject: [PATCH 24/33] Make llvm-cov capable of clang-18's profdata

---
 .../ProfileData/Coverage/CoverageMapping.h    |  3 +-
 llvm/include/llvm/ProfileData/InstrProf.h     |  2 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  | 45 ++++++++++++++-----
 3 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 7a8b6639f2971..7118e3c5813c9 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -680,7 +680,8 @@ class CounterMappingContext {
   /// pairs.
   Expected<MCDCRecord>
   evaluateMCDCRegion(const CounterMappingRegion &Region,
-                     ArrayRef<const CounterMappingRegion *> Branches);
+                     ArrayRef<const CounterMappingRegion *> Branches,
+                     bool IsVersion11);
 
   unsigned getMaxCounterID(const Counter &C) const;
 };
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index eb3c10bcba1ca..e990d4de5fb2f 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -1144,7 +1144,7 @@ enum ProfVersion {
   Version10 = 10,
   // An additional field is used for bitmap bytes.
   Version11 = 11,
-  // VTable profiling,
+  // VTable profiling, decision record and bitmap are modified for mcdc.
   Version12 = 12,
   // The current version is 12.
   CurrentVersion = INSTR_PROF_INDEX_VERSION
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 69f75494cbe80..6c8ebb63f1737 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -385,15 +385,18 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
   DenseSet<unsigned> TVIdxs;
 #endif
 
+  bool IsVersion11;
+
 public:
   MCDCRecordProcessor(const BitVector &Bitmap,
                       const CounterMappingRegion &Region,
-                      ArrayRef<const CounterMappingRegion *> Branches)
+                      ArrayRef<const CounterMappingRegion *> Branches,
+                      bool IsVersion11)
       : NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
         Region(Region), DecisionParams(Region.getDecisionParams()),
         Branches(Branches), NumConditions(DecisionParams.NumConditions),
         Folded(NumConditions, false), IndependencePairs(NumConditions),
-        ExecVectors(ExecVectorsByCond[false]) {}
+        ExecVectors(ExecVectorsByCond[false]), IsVersion11(IsVersion11) {}
 
 private:
   // Walk the binary decision diagram and try assigning both false and true to
@@ -416,7 +419,9 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
       assert(TVIdx < SavedNodes[ID].Width);
       assert(TVIdxs.insert(NextTVIdx).second && "Duplicate TVIdx");
 
-      if (!Bitmap[DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
+      if (!Bitmap[IsVersion11
+                      ? DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()
+                      : DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
         continue;
 
       // Copy the completed test vector to the vector of testvectors.
@@ -522,9 +527,9 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
 
 Expected<MCDCRecord> CounterMappingContext::evaluateMCDCRegion(
     const CounterMappingRegion &Region,
-    ArrayRef<const CounterMappingRegion *> Branches) {
+    ArrayRef<const CounterMappingRegion *> Branches, bool IsVersion11) {
 
-  MCDCRecordProcessor MCDCProcessor(Bitmap, Region, Branches);
+  MCDCRecordProcessor MCDCProcessor(Bitmap, Region, Branches, IsVersion11);
   return MCDCProcessor.processMCDCRecord();
 }
 
@@ -611,14 +616,27 @@ static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
 }
 
 /// Returns the bit count
-static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx,
-                                 const CoverageMappingRecord &Record) {
+static unsigned getMaxBitmapSize(const CoverageMappingRecord &Record,
+                                 bool IsVersion11) {
   unsigned MaxBitmapIdx = 0;
+  unsigned NumConditions = 0;
+  // Scan max(BitmapIdx).
+  // Note that `<=` is used insted of `<`, because `BitmapIdx == 0` is valid
+  // and `MaxBitmapIdx is `unsigned`. `BitmapIdx` is unique in the record.
   for (const auto &Region : reverse(Record.MappingRegions)) {
-    if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion)
-      MaxBitmapIdx =
-          std::max(MaxBitmapIdx, Region.getDecisionParams().BitmapIdx);
+    if (Region.Kind != CounterMappingRegion::MCDCDecisionRegion)
+      continue;
+    const auto &DecisionParams = Region.getDecisionParams();
+    if (MaxBitmapIdx <= DecisionParams.BitmapIdx) {
+      MaxBitmapIdx = DecisionParams.BitmapIdx;
+      NumConditions = DecisionParams.NumConditions;
+    }
   }
+
+  if (IsVersion11)
+    MaxBitmapIdx = MaxBitmapIdx * CHAR_BIT +
+                   llvm::alignTo(uint64_t(1) << NumConditions, CHAR_BIT);
+
   return MaxBitmapIdx;
 }
 
@@ -808,6 +826,9 @@ Error CoverageMapping::loadFunctionRecord(
   }
   Ctx.setCounts(Counts);
 
+  bool IsVersion11 =
+      ProfileReader.getVersion() < IndexedInstrProf::ProfVersion::Version12;
+
   BitVector Bitmap;
   if (Error E = ProfileReader.getFunctionBitmap(Record.FunctionName,
                                                 Record.FunctionHash, Bitmap)) {
@@ -819,7 +840,7 @@ Error CoverageMapping::loadFunctionRecord(
     }
     if (IPE != instrprof_error::unknown_function)
       return make_error<InstrProfError>(IPE);
-    Bitmap = BitVector(getMaxBitmapSize(Ctx, Record));
+    Bitmap = BitVector(getMaxBitmapSize(Record, IsVersion11));
   }
   Ctx.setBitmap(std::move(Bitmap));
 
@@ -877,7 +898,7 @@ Error CoverageMapping::loadFunctionRecord(
     // DecisionRegion, all of the information is now available to process.
     // This is where the bulk of the MC/DC progressing takes place.
     Expected<MCDCRecord> Record =
-        Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches);
+        Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
     if (auto E = Record.takeError()) {
       consumeError(std::move(E));
       return Error::success();

>From f54c64dbd1900a78f68c0ac37c9c633cf82a0321 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 15 May 2024 14:39:11 +0900
Subject: [PATCH 25/33] Fix unittest

---
 llvm/unittests/ProfileData/CoverageMappingTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
index 13d4fc4718c59..ef147674591c5 100644
--- a/llvm/unittests/ProfileData/CoverageMappingTest.cpp
+++ b/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -895,7 +895,7 @@ TEST_P(CoverageMappingTest, decision_before_expansion) {
   addCMR(Counter::getCounter(0), "foo", 3, 23, 5, 2);
 
   // This(4:11) was put after Expansion(4:11) before the fix
-  addMCDCDecisionCMR(0, 2, "foo", 4, 11, 4, 20);
+  addMCDCDecisionCMR(3, 2, "foo", 4, 11, 4, 20);
 
   addExpansionCMR("foo", "A", 4, 11, 4, 12);
   addExpansionCMR("foo", "B", 4, 19, 4, 20);

>From a6f7eefe6f6d873bbcd76a19a2219ac24d894c41 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 16 May 2024 19:40:42 +0900
Subject: [PATCH 26/33] Introduce `-fmcdc-max-conditions` and
 `-fmcdc-max-test-vectors`

---
 clang/include/clang/Basic/CodeGenOptions.def | 2 ++
 clang/include/clang/Driver/Options.td        | 8 ++++++++
 clang/lib/CodeGen/CodeGenPGO.cpp             | 4 +++-
 clang/lib/CodeGen/CoverageMappingGen.cpp     | 7 ++++---
 4 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 340b08dd7e2a3..c8fab3e442f2f 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -222,6 +222,8 @@ CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
 CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping
                                        ///< regions.
 CODEGENOPT(MCDCCoverage , 1, 0) ///< Enable MC/DC code coverage criteria.
+VALUE_CODEGENOPT(MCDCMaxConds, 16, 32767) ///< MC/DC Maximum conditions.
+VALUE_CODEGENOPT(MCDCMaxTVs, 32, 0x7FFFFFFE) ///< MC/DC Maximum test vectors.
 
   /// If -fpcc-struct-return or -freg-struct-return is specified.
 ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index f745e573eb268..4f8253f7ee219 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1758,6 +1758,14 @@ defm mcdc_coverage : BoolFOption<"coverage-mcdc",
           "Enable MC/DC criteria when generating code coverage">,
   NegFlag<SetFalse, [], [ClangOption], "Disable MC/DC coverage criteria">,
           BothFlags<[], [ClangOption, CLOption]>>;
+def fmcdc_max_conditions_EQ : Joined<["-"], "fmcdc-max-conditions=">,
+  Group<f_Group>, Visibility<[CC1Option]>,
+  HelpText<"Maximum number of conditions in MC/DC coverage">,
+  MarshallingInfoInt<CodeGenOpts<"MCDCMaxConds">, "32767">;
+def fmcdc_max_test_vectors_EQ : Joined<["-"], "fmcdc-max-test-vectors=">,
+  Group<f_Group>, Visibility<[CC1Option]>,
+  HelpText<"Maximum number of test vectors in MC/DC coverage">,
+  MarshallingInfoInt<CodeGenOpts<"MCDCMaxTVs">, "0x7FFFFFFE">;
 def fprofile_generate : Flag<["-"], "fprofile-generate">,
     Group<f_Group>, Visibility<[ClangOption, CLOption]>,
     HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 156f34c3c56bc..65f9da2bada67 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1078,7 +1078,9 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
   // for most embedded applications. Setting a maximum value prevents the
   // bitmap footprint from growing too large without the user's knowledge. In
   // the future, this value could be adjusted with a command-line option.
-  unsigned MCDCMaxConditions = (CGM.getCodeGenOpts().MCDCCoverage) ? 32767 : 0;
+  unsigned MCDCMaxConditions =
+      (CGM.getCodeGenOpts().MCDCCoverage ? CGM.getCodeGenOpts().MCDCMaxConds
+                                         : 0);
 
   RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
   RegionMCDCState.reset(new MCDC::State);
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 27f157b2d9951..6122b9942dae0 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -2080,10 +2080,11 @@ struct CounterCoverageMappingBuilder
 
     // Construct the graph and calculate `Indices`.
     mcdc::TVIdxBuilder Builder(CondIDs);
-    auto NumTVs = Builder.NumTestVectors;
-    auto MaxTVs = mcdc::TVIdxBuilder::HardMaxTVs;
+    unsigned NumTVs = Builder.NumTestVectors;
+    unsigned MaxTVs = CVM.getCodeGenModule().getCodeGenOpts().MCDCMaxTVs;
+    assert(MaxTVs < mcdc::TVIdxBuilder::HardMaxTVs);
 
-    if (NumTVs >= MaxTVs) {
+    if (NumTVs > MaxTVs) {
       // NumTVs exceeds MaxTVs -- warn and cancel the Decision.
       cancelDecision(E, Since, NumTVs, MaxTVs);
       return;

>From cf837aee69b4a98ff77a1b503c9c9cb1d157f1c6 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 20 May 2024 20:57:42 +0900
Subject: [PATCH 27/33] mcdc-system-headers.cpp: Update

---
 clang/test/CoverageMapping/mcdc-system-headers.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/CoverageMapping/mcdc-system-headers.cpp b/clang/test/CoverageMapping/mcdc-system-headers.cpp
index a8a3ddbb506fb..a9df667ace854 100644
--- a/clang/test/CoverageMapping/mcdc-system-headers.cpp
+++ b/clang/test/CoverageMapping/mcdc-system-headers.cpp
@@ -15,7 +15,7 @@
 
 // CHECK: _Z5func0i:
 int func0(int a) {
-  // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:21 = M:3, C:2
   // W_SYS: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = #0 (Expanded file = 1)
   // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = 0, 0 [1,2,0]
   return (CONST && a);
@@ -25,7 +25,7 @@ int func0(int a) {
 
 // CHECK: _Z5func1ii:
 int func1(int a, int b) {
-  // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:21 = M:3, C:2
   // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:12 = (#0 - #1), #1 [1,0,2]
   return (a || EXPR1(b));
   // W_SYS: Expansion,File 0, [[@LINE-1]]:16 -> [[@LINE-1]]:21 = #1 (Expanded file = 1)
@@ -35,8 +35,8 @@ int func1(int a, int b) {
 
 // CHECK: _Z5func2ii:
 int func2(int a, int b) {
-  // W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:0, C:3
-  // X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:0, C:2
+  // W_SYS: Decision,File 0, [[@LINE+5]]:11 -> [[@LINE+5]]:28 = M:4, C:3
+  // X_SYS: Decision,File 0, [[@LINE+4]]:11 -> [[@LINE+4]]:28 = M:3, C:2
   // W_SYS: Expansion,File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:16 = #0 (Expanded file = 1)
   // W_SYS: Expansion,File 0, [[@LINE+2]]:23 -> [[@LINE+2]]:28 = #1 (Expanded file = 2)
   // X_SYS: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:11 = #1, (#0 - #1) [1,2,0]

>From 9e14c2a844ae90c37ff552dd05dff8690ae213a3 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 20 May 2024 23:03:46 +0900
Subject: [PATCH 28/33] llvm-cov tests for old (Version11) files

---
 .../tools/llvm-cov/Inputs/mcdc-general-18.o   | Bin 0 -> 6456 bytes
 .../llvm-cov/Inputs/mcdc-general-18.profdata  | Bin 0 -> 888 bytes
 llvm/test/tools/llvm-cov/mcdc-general-18.test |  20 ++++++++++++++++++
 3 files changed, 20 insertions(+)
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/mcdc-general-18.o
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/mcdc-general-18.profdata
 create mode 100644 llvm/test/tools/llvm-cov/mcdc-general-18.test

diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-general-18.o b/llvm/test/tools/llvm-cov/Inputs/mcdc-general-18.o
new file mode 100644
index 0000000000000000000000000000000000000000..e802f51132c068f0f4e2921c952710cb5c5665e5
GIT binary patch
literal 6456
zcmd5=eQaA-6~FJjWU*VvcC)5U(xq}rH?p!k>?X~c(jYsHvs7eLwzAQ|z;zubjTV2%
zd5H!L7F4%e5a~8hCH_Df|1qH<O`6nwfJVE*v<UIB!ZxHz2nkdgBG9IyG8ojHbKg0B
z*Ecr%gMT=ZeeU_)^Zm}dzR6?Bi80eKEJ0+5PYQztg}=1L6XJ3i7dt`o{={bz4;-0X
z{&`~go$*RD?krzREZ>N&o~k&z2nn6Lm{<v%E}wV8gp9AWqw4y><u?dPgwDOQ5 at _>Z
zC|`2!B`h8~_tr|&n}B?okPBBWG95Qwd)~P8d!JeLIE)^z;#c{y(@$`+Tyb`+r=+UP
zu6#LEehzeKf2kD>%(d^rx4SlCt6&s5^&LRgc0w<_nDKK){L+=UZy=0b{s0Ob+^yVo
z;H!qd?i`^tRPs}3!C1Wfmr(fy&(O<@J*{|U5VU?<HL<lbUYfM~GCnPE>nySdHy7yV
z>nnjI)|@O~caG97wB~MFHi|ud at +ZE}CBBeIeSQs$xhw0NHt5UH3R<<hILW!3lsz}E
zg$i;p9r}&r*Fuj;PHJv_ek!vDw0?~B#jd}COa_!sSfa1WtxK_036Yr>YH`(dXikSd
zxIn%+Fo~WU&3~*SolBJb$Id@^5hev&0)(NFzP|diT;<gp-#iAu-(NrQ^q;SdKC!;v
z{%B at b?puZtFj`x;_}kk%jh>!cyZicL#_(`rD49GQH8y>0vl%uFVHie>2pOV9?C2Fu
z$PD2V{%EUdSSGGoMXLx#x7=hwY*_il&0>dNY!&U%_DyD!z*W2G6kXBIAV|1s7PlCu
zmX?-$%|^4>T at B*HAg#Toi7eXFW<V`1!q+1LAl|wSD}z<H2#P1sxEr$C-3`&U;#X%c
zWCJYP*M)X~_K6M<V>{6fR=0~TH|Xs(L9sF;)Y}A=8L-C6hIip{1FK<KS>iVEjH at AR
z#E?`;?!n4HB`H-7+gKT>>=R)($UY1LnE2;gD}NfCI(zwMnFS(ns#N<gETh8+nBivV
zbGQk<<i0$5V09CG%r+syxy)3iZzh}1meO-}rdX6(|KDFccRX_+mM!)N32Rn~``4j@
z|7Fc{&njV&`s{#{op+7{8M*Xq9)(zBDw~;|pDpAgPH7=45ZhY^>(?-mnM>zqB8%CQ
zw2ckfQ9C*_>)@2TWPIs9VLTExb_7~{PeC%{0N+A;a)cAX at JO&@Bp68qdlSLv$>uXn
zPg<u<>sJQK5xEym1bxY1G*^qj6bo^JeEk+V_%h!P`f!PLWABhl0QhG3AmL9)5I!Lk
zfcU2pdyaYYyy2csc%V0l_bNJ$GQROTeGLFZY_G!Hml;S5ah92<2=65e#=nY%K;(L4
z3I7JzlKPuA;0RdNPI%iLQa|7U%F2=*Qvh08vWvC&52YBc1*`hpX>WT~F5#uFLlzuc
z^~kDrt#;QE+iC%jB2ZVG@?7N10sblY)XVZsz)_#|<Xi!UGuvZ&Z{wq~U+#SMm^@)Z
zd>r(Uc(!mNaPIz9aj6G4ff(oK+wa0voZpcH3XV^i{Uj9}{qvK1P{ZY+3)sUNeh0}5
z3a<J;rQqnFC+`~yj+ao*=V`)G4{Kr^Z)Hea??G1-KOl~{8uv#Ej&WK4H3dige^Wny
z(Ewl5aL&i1=cec5*YHuYhu=U+oF~WKuHcyG0O@~3!#_><Cp7#a!jlS)bx~QB2?a<0
z6QqAc!Lip|*HOat{^NOq#PvF^DDeD2((78#@EerSR}>ucVLxXy{88yuh_f0#NBDCZ
zUMBoS4d*$#py1da62%(|j`>WHpI<6CURk+6zaw1l&mR?ib*|piaDFcDE4bQ+7HlLC
z_tTYx=u&VzZ#bVG1xG(0P=Gxe9w0}16&z0?_H#hN(GTk<G<-Mtxl6&ZUXFW at hVz_1
zpx|n~4=K1hxATN!pYinOJWn^kR}??!pY_jbIM?-zf~)y|U&A^77ZhCW&&vv~=KpKL
z_580i!1*@>?;_}5l|htu6!ee#Na{YWRT=kD5AP<dAAvOzhNl#yJSV?BoPV#jZEx{!
z4g|wn+C(aqDJ+(<nbhdW(7wTe{=wv(`$tFjjU^Vmt)abR$&uvP*x=})kwZiKVaqOM
z=hC*5eZ&!VrjW~J^NuJkIP+jLH at BEe6-(2pOukk=K3gm2)4A-tuqWo7lCWn=g at vNn
zaAhZVkYX-fWal7FFXTZgmI~9yb1A%^l9X`;J6~|J_Febf-#721GY<<}CY7F=f*a at z
zC7(T!nl3>Ko*(7TTXm;mHe~9gj|+SLi#f@$2};3JX(tWN3&`yZ+?NO4>g)mH{ncIY
z6tiOhADTQIOGW81{m<+UICt>(R;N8QK#$Y8#QT~ke at 7AXZZNK9oDBY|4i{iJ|0>-H
z0%CC$g!QvH+(1|5{|AKVhBdn48xha(y$~GZ>o>h96~*rXs7PX&`Qw0Yygdrh+v4hT
zJdBUGK+c~z-Zx}V%m}PJic@^P&+!iXW4TfMXr1_Y+vm8<8^u3Q3Vd(mczXP2U_<6F
zBCI0$yJX*6gL?gExKaN5>*SBIIdA620K at qBx4%jq^xXBia&z at G8^w=Pe16XO{P3?9
zj>~)!uzK+$6#v^^D7n)6mjL5>_Ailr{6p*yg0aj+tN$sw=ts#O^T+d><MaGCs(-Rh
z|MBlruABKW!0P4yKIISFHH5k<HHv?<PXDnaj?27J|2aO_%Q1DiQUCcsinAec-M&%(
z&)4byR`9|0-2WnA*b`Gk;M=1(4X%DJ>HRAJfY at HoRIctLd;U9xx7nWg2yEb*=Y;jn
zkbNfu#MzGd+ko?0RsEj+;%WA*`w!Q?sEx09mh6{UkvR8{;lIHGXCcl2 at ptR=zYF%*
vp8J0VFl(Yx0Ja35Dn-KXlK)eI?+=n*>i__H?x=Ty<~L58XovSsJ^p_HjJhJT

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-general-18.profdata b/llvm/test/tools/llvm-cov/Inputs/mcdc-general-18.profdata
new file mode 100644
index 0000000000000000000000000000000000000000..d351096967dbf315b7bedf94441be0f19a936ba3
GIT binary patch
literal 888
zcmeyLQ&5zjmf6V7fE`3Iqly=x@!6o#0#KR>N{c{gb~Kt5$~T140_so(8nvK}5iA1J
z58*K|IPgLo05b>XoClLx!0OS(8>ApEgvc^5z-Wbq5R+m0VfGwQ=LDOBE}pQC3oH)v
zA1{~(Busg*iZ9p=Q2}!|EIdBc at qyK&iyKJuV-=6E!!CZu5xcmV6LxWX9O6t2zpnN^
zH%pm%8x}GeV0SPu<R)h3NkG{!*TQJ1Farma(RK24?*D!NCc#qC3#fQ}lu1cyaY+&o
zd_QJ2 at zrOS4q>PiEWlv_4U0G!4GU<PJj`lzaTp&akBf$>gLxCihtV*7umr6SbtlY=
cFt0(92LnShRK5XC9h3_*4rV+9oB>e)05F*>P5=M^

literal 0
HcmV?d00001

diff --git a/llvm/test/tools/llvm-cov/mcdc-general-18.test b/llvm/test/tools/llvm-cov/mcdc-general-18.test
new file mode 100644
index 0000000000000..8707238c4cdcb
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/mcdc-general-18.test
@@ -0,0 +1,20 @@
+// Test Version11 (clang-18) files.
+// mcdc-general.test is used as test patterns.
+
+// RUN: llvm-cov show --show-mcdc %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/mcdc-general.test
+// RUN: llvm-cov report --show-mcdc-summary %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %S/mcdc-general.test -check-prefix=REPORT
+
+// Turn off MC/DC visualization.
+// RUN: llvm-cov show %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/mcdc-general.test -check-prefix=NOMCDC
+
+// Turn off MC/DC summary.
+// RUN: llvm-cov report %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %S/mcdc-general.test -check-prefix=REPORT_NOMCDC
+
+// Test file-level report.
+// RUN: llvm-cov report --show-mcdc-summary %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %S/mcdc-general.test -check-prefix=FILEREPORT
+
+// Test html output.
+// RUN: rm -rf %t.html.dir
+// RUN: llvm-cov show --show-mcdc-summary --show-mcdc %S/Inputs/mcdc-general-18.o -instr-profile %S/Inputs/mcdc-general-18.profdata -path-equivalence=.,%S/Inputs -format html -o %t.html.dir
+// RUN: FileCheck -check-prefix=HTML -input-file=%t.html.dir/coverage/mcdc-general.cpp.html %S/mcdc-general.test
+// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %S/mcdc-general.test

>From 3ff3eb77c537566fd5d7925bc0ed06929f4a12b9 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 27 May 2024 14:24:57 +0900
Subject: [PATCH 29/33] Update CoverageMapping/mcdc-scratch-space.c

---
 clang/test/CoverageMapping/mcdc-scratch-space.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/test/CoverageMapping/mcdc-scratch-space.c b/clang/test/CoverageMapping/mcdc-scratch-space.c
index 2b5b12d9dcad6..a263e9b688fae 100644
--- a/clang/test/CoverageMapping/mcdc-scratch-space.c
+++ b/clang/test/CoverageMapping/mcdc-scratch-space.c
@@ -2,14 +2,14 @@
 
 // CHECK: builtin_macro0:
 int builtin_macro0(int a) {
-  // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:15 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:15 = M:3, C:2
   return (__LINE__ // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:11 = 0, 0 [1,2,0]
           && a); //   CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:15 = #2, (#1 - #2) [2,0,0]
 }
 
 // CHECK: builtin_macro1:
 int builtin_macro1(int a) {
-  // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:22 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+1]]:11 -> [[@LINE+2]]:22 = M:3, C:2
   return (a // CHECK: Branch,File 0, [[@LINE]]:11 -> [[@LINE]]:12 = (#0 - #1), #1 [1,0,2]
           || __LINE__); // CHECK: Branch,File 0, [[@LINE]]:14 -> [[@LINE]]:14 = 0, 0 [2,0,0]
 }
@@ -18,7 +18,7 @@ int builtin_macro1(int a) {
 
 // CHECK: pre0:
 int pre0(int pre_a, int b_post) {
-  // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:20 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:20 = M:3, C:2
   // CHECK: Expansion,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:14 = #0 (Expanded file = 1)
   return (PRE(a)
           && b_post);
@@ -30,7 +30,7 @@ int pre0(int pre_a, int b_post) {
 
 // CHECK: pre1:
 int pre1(int pre_a, int b_post) {
-  // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:20 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:20 = M:3, C:2
   // CHECK: Expansion,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:14 = #0 (Expanded file = 1)
   // CHECK: Branch,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:20 = #2, (#1 - #2) [2,0,0]
   return (PRE(foo)
@@ -43,7 +43,7 @@ int pre1(int pre_a, int b_post) {
 
 // CHECK: post0:
 int post0(int pre_a, int b_post) {
-  // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:18 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+2]]:11 -> [[@LINE+3]]:18 = M:3, C:2
   // CHECK: Branch,File 0, [[@LINE+1]]:11 -> [[@LINE+1]]:16 = (#0 - #1), #1 [1,0,2]
   return (pre_a
           || POST(b));
@@ -55,7 +55,7 @@ int post0(int pre_a, int b_post) {
 
 // CHECK: post1:
 int post1(int pre_a, int b_post) {
-  // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:18 = M:0, C:2
+  // CHECK: Decision,File 0, [[@LINE+3]]:11 -> [[@LINE+4]]:18 = M:3, C:2
   // CHECK: Branch,File 0, [[@LINE+2]]:11 -> [[@LINE+2]]:16 = (#0 - #1), #1 [1,0,2]
   // CHECK: Expansion,File 0, [[@LINE+2]]:14 -> [[@LINE+2]]:18 = 0 (Expanded file = 1)
   return (pre_a

>From 296f5c5b3012424013ad329b5fa6433d6e0ccd4f Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 27 May 2024 14:32:01 +0900
Subject: [PATCH 30/33] Don't create tvbitmap_update if the record is allocated
 but excluded.

Or `bitmap |= (1 << 0)` would be wrongly executed to the next bitmap.
---
 clang/lib/CodeGen/CodeGenPGO.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 65f9da2bada67..d92752a0e8fd4 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1246,6 +1246,11 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder,
   if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end())
     return;
 
+  // Don't create tvbitmap_update if the record is allocated but excluded.
+  // Or `bitmap |= (1 << 0)` would be wrongly executed to the next bitmap.
+  if (DecisionStateIter->second.Indices.size() == 0)
+    return;
+
   // Extract the offset of the global bitmap associated with this expression.
   unsigned MCDCTestVectorBitmapOffset = DecisionStateIter->second.BitmapIdx;
   auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());

>From 722424b640a9f1e8bafe6586cae1bf187782053d Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 10 Jun 2024 14:19:57 +0900
Subject: [PATCH 31/33] Update mcdc-error-conditions.cpp

---
 .../CoverageMapping/mcdc-error-conditions.cpp | 27 ++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/clang/test/CoverageMapping/mcdc-error-conditions.cpp b/clang/test/CoverageMapping/mcdc-error-conditions.cpp
index d2042e576159b..8f5d6bd66897c 100644
--- a/clang/test/CoverageMapping/mcdc-error-conditions.cpp
+++ b/clang/test/CoverageMapping/mcdc-error-conditions.cpp
@@ -1,7 +1,23 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,TV
+
+// RUN: %clang_cc1 -fmcdc-max-test-vectors=8 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,TV
+// RUN: %clang_cc1 -fmcdc-max-test-vectors=7 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,TV7,TV
+
+// RUN: %clang_cc1 -fmcdc-max-conditions=287 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,TV
+// RUN: %clang_cc1 -fmcdc-max-conditions=286 -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,COND
+// RUN: %clang_cc1 -fmcdc-max-conditions=7   -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND7,COND
+// RUN: %clang_cc1 -fmcdc-max-conditions=6   -triple %itanium_abi_triple -std=c++11 -fcoverage-mcdc -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s 2>&1| FileCheck %s --check-prefixes=CHECK,COND6,COND
+
+bool func_conditions(bool a, bool b, bool c, bool d, bool e, bool f, bool g) {
+  //   TV7: :[[@LINE+2]]:10: warning: unsupported MC/DC boolean expression; number of test vectors (8) exceeds max
+  // COND6: :[[@LINE+1]]:10: warning: unsupported MC/DC boolean expression; number of conditions (7) exceeds max
+  return a && b && c && d && e && f && g;
+}
 
 // From clang-tidy/misc/MisleadingIdentifier.cpp
-bool func_conditions(unsigned CP) {
+bool func_isR(unsigned CP) {
+  //   TV: :[[@LINE+2]]:10: warning: unsupported MC/DC boolean expression; number of test vectors (2147483647) exceeds max
+  // COND: :[[@LINE+1]]:10: warning: unsupported MC/DC boolean expression; number of conditions (287) exceeds max
   return (CP == 0x0590) || (CP == 0x05BE) || (CP == 0x05C0) || (CP == 0x05C3) ||
          (CP == 0x05C6) || (0x05C8 <= CP && CP <= 0x05CF) ||
          (0x05D0 <= CP && CP <= 0x05EA) || (0x05EB <= CP && CP <= 0x05EE) ||
@@ -82,6 +98,11 @@ bool func_conditions(unsigned CP) {
          (0x1ECC0 <= CP && CP <= 0x1ECFF) || (0x1ED50 <= CP && CP <= 0x1EDFF);
 }
 
-// CHECK: warning: unsupported MC/DC boolean expression; number of test vectors{{.*}} exceeds max
+// CHECK: _Z15func_conditionsbbbbbbb:
+//   TV8-NOT: Decision,
+// COND6-NOT: Decision,
+//     COND7: Decision,File 0, {{[0-9]+}}:10 -> {{[0-9]+}}:41 = M:8, C:7
+// CHECK: _Z8func_isRj:
 // CHECK-NOT: Decision,
 // CHECK-NOT: Branch,{{.*}}]
+//     CHECK: Branch,File 0, [[@LINE-10]]:64 -> [[@LINE-10]]:77 =

>From 183bc52df4ba8f46a435ffc3620accd84dd77afa Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 10 Jun 2024 20:40:08 +0900
Subject: [PATCH 32/33] Update documents

---
 clang/docs/SourceBasedCodeCoverage.rst | 29 ++++++++++++++++++++++----
 llvm/docs/CoverageMappingFormat.rst    |  2 +-
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/clang/docs/SourceBasedCodeCoverage.rst b/clang/docs/SourceBasedCodeCoverage.rst
index cee706289284d..375f7e9e0e7ec 100644
--- a/clang/docs/SourceBasedCodeCoverage.rst
+++ b/clang/docs/SourceBasedCodeCoverage.rst
@@ -484,10 +484,31 @@ MC/DC Instrumentation
 ---------------------
 
 When instrumenting for Modified Condition/Decision Coverage (MC/DC) using the
-clang option ``-fcoverage-mcdc``, users are limited to at most **six** leaf-level
-conditions in a boolean expression.  A warning will be generated for boolean
-expressions that contain more than six, and they will not be instrumented for
-MC/DC.
+clang option ``-fcoverage-mcdc``, there are two hard limits.
+
+The maximum number of terms is limited to 32767. It would be practical for
+handwritten expressions. To be more retrictive in order to enfoce conding rules,
+use ``-Xclang -fmcdc-max-conditions=n``. Expressions with exceeded condition
+counts ``n`` will generate warnings.
+
+The number of test vectors (the maximum number of possible combinations of
+expressions) is limited to 2,147,483,646. In this case, approximately
+256MiB (==2GiB/8) is used to record test vectors.
+
+To reduce memory usage, you can limit the maximum number of test vectors per
+expression with ``-Xclang -fmcdc-max-test-vectors=m``.
+If the number of test vectors that result from analyzing an expression exceeds
+m, a warning will be issued and the expression will be excluded in the MC/DC
+coverage.
+
+The number of test vectors ``m``, for ``n`` terms in an expression, can be
+``m <= 2^n`` in the theoretical worst case, but is usually much smaller.
+In simple cases, such as expressions consisting of a sequence of single
+operators, ``m == n+1``. For example, ``(a && b && c && d && e && f && g)``
+requires 8 test vectors.
+
+Expressions like ``((a0 && b0) || (a1 && b1) || ...)`` can cause the number
+of test vectors to grow exponentially.
 
 Also, if a boolean expression is embedded in the nest of another boolean
 expression but separated by a non-logical operator, this is also not supported.
diff --git a/llvm/docs/CoverageMappingFormat.rst b/llvm/docs/CoverageMappingFormat.rst
index f2ae8df5ad7f8..96bdf8fa71be7 100644
--- a/llvm/docs/CoverageMappingFormat.rst
+++ b/llvm/docs/CoverageMappingFormat.rst
@@ -148,7 +148,7 @@ There are several kinds of mapping regions:
 
 * Decision regions associate multiple branch regions with a boolean
   expression in the source code.  This information also includes the number of
-  bitmap bytes needed to represent the expression's executed test vectors as
+  bitmap bits needed to represent the expression's executed test vectors as
   well as the total number of instrumentable branch conditions that comprise
   the expression.  Decision regions are used to visualize Modified
   Condition/Decision Coverage (MC/DC) in *llvm-cov* for each boolean

>From 83088f1e9147d5e62b2d068a119621cf27dcc02e Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 10 Jun 2024 23:42:53 +0900
Subject: [PATCH 33/33] mcdc.tvupdate doesn't depend on condupdate

---
 llvm/docs/LangRef.rst | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 1c89c730a0ef7..fd5d550115b36 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -14426,10 +14426,9 @@ Overview:
 The '``llvm.instrprof.mcdc.tvbitmap.update``' intrinsic is used to track MC/DC
 test vector execution after each boolean expression has been fully executed.
 The overall value of the condition bitmap, after it has been successively
-updated using the '``llvm.instrprof.mcdc.condbitmap.update``' intrinsic with
-the true or false evaluation of each condition, uniquely identifies an executed
-MC/DC test vector and is used as a bit index into the global test vector
-bitmap.
+updated with the true or false evaluation of each condition, uniquely identifies
+an executed MC/DC test vector and is used as a bit index into the global test
+vector bitmap.
 
 Arguments:
 """"""""""



More information about the cfe-commits mailing list