[llvm] 512a8a7 - [MC/DC] Introduce `class TestVector` with a pair of `BitVector` (#82174)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 26 23:46:53 PST 2024
Author: NAKAMURA Takumi
Date: 2024-02-27T16:46:49+09:00
New Revision: 512a8a78a7f3bffc41cd7c00788eb099519f4625
URL: https://github.com/llvm/llvm-project/commit/512a8a78a7f3bffc41cd7c00788eb099519f4625
DIFF: https://github.com/llvm/llvm-project/commit/512a8a78a7f3bffc41cd7c00788eb099519f4625.diff
LOG: [MC/DC] Introduce `class TestVector` with a pair of `BitVector` (#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.
Added:
Modified:
llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 27b1c32b1fa547..7a8b6639f29713 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -384,7 +384,58 @@ 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:
+ /// Default values are filled with DontCare.
+ TestVector(unsigned N) : Values(N), Visited(N) {}
+
+ /// Emulate RHS SmallVector::operator[]
+ 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]; }
+
+ /// Set the condition \p Val at position \p I.
+ /// This emulates 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);
+ assert(Values.size() == Visited.size());
+ }
+
+ /// 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<std::pair<TestVector, CondState>>;
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 64545164d597a7..6c77ce017c0365 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -400,26 +400,23 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
// 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;
+ TV.set(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[DecisionParams.BitmapIdx * CHAR_BIT + Index])
+ if (!Bitmap[DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()])
continue;
// Copy the completed test vector to the vector of testvectors.
@@ -429,7 +426,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
}
// 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
@@ -439,8 +436,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
// 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);
+ MCDCRecord::TestVector TV(NumConditions);
+ buildTestVector(TV, 0, 0);
assert(TVIdxs.size() == unsigned(NumTestVectors) &&
"TVIdxs wasn't fulfilled");
@@ -465,20 +462,12 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
for (unsigned J = 0; J < NumExecVectorsF; ++J) {
const auto &[B, BCond] = ExecVectors[J];
assert(BCond == MCDCRecord::MCDC_False);
- 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
diff er 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);
+ if (AB.count() == 1)
+ IndependencePairs.insert(
+ {AB.find_first(), std::make_pair(J + 1, I + 1)});
}
}
}
More information about the llvm-commits
mailing list