[llvm] [MC/DC] Introduce `class TestVector` with a pair of `BitVector` (PR #82174)
NAKAMURA Takumi via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 18 08:43:16 PST 2024
https://github.com/chapuni created https://github.com/llvm/llvm-project/pull/82174
This replaces `SmallVector<CondState>` and emulates it.
- -------- True False DontCare
- Values: True False False
- Visited: True True False
`findIndependencePairs()` can be optimized with logical ops.
FIXME: Specialize `findIndependencePairs()` for the single word.
>From 9ef9ea31b6fd1d351b019129758f7869519aa23a Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 17 Feb 2024 23:33:55 +0900
Subject: [PATCH] Introduce `class TestVector` with a pair of `BitVector`
This replaces `SmallVector<CondState>` and emulates it.
- True False DontCare (Impossible)
- Values: True False False True
- Visited: True True False False
`findIndependencePairs()` can be optimized with logical ops.
FIXME: Specialize `findIndependencePairs()` for the single word.
---
.../ProfileData/Coverage/CoverageMapping.h | 65 ++++++++++++++++++-
.../ProfileData/Coverage/CoverageMapping.cpp | 35 ++++------
2 files changed, 76 insertions(+), 24 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index c5c9740f25c2ce..0f82f091107f5b 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -380,7 +380,70 @@ struct MCDCRecord {
/// are effectively ignored.
enum CondState { MCDC_DontCare = -1, MCDC_False = 0, MCDC_True = 1 };
- using TestVector = llvm::SmallVector<CondState>;
+ /// Emulate SmallVector<CondState> with a pair of BitVector.
+ ///
+ /// True False DontCare (Impossible)
+ /// Values: True False False True
+ /// Visited: True True False False
+ class TestVector {
+ BitVector Values; /// True/False (False when DontCare)
+ BitVector Visited; /// ~DontCare
+
+ public:
+ /// Assume filling DontCare.
+ TestVector(unsigned n, CondState Cond = MCDC_DontCare) {
+ assert(Cond == MCDC_DontCare);
+ Values.resize(n);
+ Visited.resize(n);
+ }
+
+ /// Emulate RHS SmallVector::operator[]
+ MCDCRecord::CondState operator[](int I) const {
+ return (Visited[I] ? (Values[I] ? MCDC_True : MCDC_False)
+ : MCDC_DontCare);
+ }
+
+ /// Equivalent to buildTestVector's Index.
+ auto getIndex() const { return Values.getData()[0]; }
+
+ /// Emulate LHS SmallVector::operator[].
+ void set(int I, CondState Val) {
+ Visited[I] = (Val != MCDC_DontCare);
+ Values[I] = (Val == MCDC_True);
+ }
+
+ /// Emulate SmallVector::push_back.
+ void push_back(CondState Val) {
+ Visited.push_back(Val != MCDC_DontCare);
+ Values.push_back(Val == MCDC_True);
+ }
+
+ /// Return the outcome is different each other.
+ /// Assumes back() is the outcome
+ /// Dedicated to findIndependencePairs().
+ bool isDifferentOutcome(const TestVector &B) const {
+ const auto &A = *this;
+ assert(A.Visited.back() && B.Visited.back() &&
+ "Both shouldn't be DontCare");
+ return (A.Values.back() ^ B.Values.back());
+ }
+
+ /// For each element:
+ /// - False if either is DontCare
+ /// - False if both have the same value
+ /// - True if both have the opposite value
+ /// ((A.Values ^ B.Values) & A.Visited & B.Visited)
+ /// Dedicated to findIndependencePairs().
+ auto getDifferences(const TestVector &B) const {
+ const auto &A = *this;
+ BitVector AB = A.Values;
+ AB ^= B.Values;
+ AB &= A.Visited;
+ AB &= B.Visited;
+ return AB;
+ }
+ };
+
using TestVectors = llvm::SmallVector<TestVector>;
using BoolVector = llvm::SmallVector<bool>;
using TVRowPair = std::pair<unsigned, unsigned>;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index ddce7580729170..f02ac27ed891af 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -272,22 +272,18 @@ 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, mcdc::ConditionID ID,
- unsigned Index) {
- assert((Index & (1 << ID)) == 0);
-
+ void buildTestVector(MCDCRecord::TestVector &TV, mcdc::ConditionID ID) {
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;
+ TV.set(ID, MCDCCond);
auto NextID = CondsMap[ID][MCDCCond];
if (NextID >= 0) {
- buildTestVector(TV, NextID, Index);
+ buildTestVector(TV, NextID);
continue;
}
- if (!Bitmap[BitmapIdx + Index])
+ if (!Bitmap[BitmapIdx + TV.getIndex()])
continue;
// Copy the completed test vector to the vector of testvectors.
@@ -299,7 +295,7 @@ class MCDCRecordProcessor {
}
// Reset back to DontCare.
- TV[ID] = MCDCRecord::MCDC_DontCare;
+ TV.set(ID, MCDCRecord::MCDC_DontCare);
}
/// Walk the bits in the bitmap. A bit set to '1' indicates that the test
@@ -309,7 +305,7 @@ class MCDCRecordProcessor {
// We start at the root node (ID == 0) 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, 0, 0);
+ buildTestVector(TV, 0);
}
// Find an independence pair for each condition:
@@ -323,22 +319,15 @@ class MCDCRecordProcessor {
for (unsigned J = 0; J < I; ++J) {
const MCDCRecord::TestVector &B = ExecVectors[J];
// Enumerate two execution vectors whose outcomes are different.
- if (A[NumConditions] == B[NumConditions])
+ if (!A.isDifferentOutcome(B))
continue;
- unsigned Flip = NumConditions, Idx;
- for (Idx = 0; Idx < NumConditions; ++Idx) {
- MCDCRecord::CondState ACond = A[Idx], BCond = B[Idx];
- if (ACond == BCond || ACond == MCDCRecord::MCDC_DontCare ||
- BCond == MCDCRecord::MCDC_DontCare)
- continue;
- if (Flip != NumConditions)
- break;
- Flip = Idx;
- }
// If the two vectors differ in exactly one condition, ignoring DontCare
// conditions, we have found an independence pair.
- if (Idx == NumConditions && Flip != NumConditions)
- IndependencePairs.insert({Flip, std::make_pair(J + 1, I + 1)});
+ auto AB = A.getDifferences(B);
+ assert(AB[NumConditions] && "The last element should be different");
+ if (AB.count() == 2) // The single condition and the last element
+ IndependencePairs.insert(
+ {AB.find_first(), std::make_pair(J + 1, I + 1)});
}
}
}
More information about the llvm-commits
mailing list