[Lldb-commits] [lldb] [clang] [compiler-rt] [libc] [libcxx] [flang] [clang-tools-extra] [llvm] [llvm-cov] Simplify and optimize MC/DC computation (PR #79727)
Fangrui Song via lldb-commits
lldb-commits at lists.llvm.org
Mon Jan 29 10:34:58 PST 2024
================
@@ -353,71 +331,30 @@ class MCDCRecordProcessor {
}
}
- /// For a given condition and two executed Test Vectors, A and B, see if the
- /// two test vectors match forming an Independence Pair for the condition.
- /// For two test vectors to match, the following must be satisfied:
- /// - The condition's value in each test vector must be opposite.
- /// - The result's value in each test vector must be opposite.
- /// - All other conditions' values must be equal or marked as "don't care".
- bool matchTestVectors(unsigned Aidx, unsigned Bidx, unsigned ConditionIdx) {
- const MCDCRecord::TestVector &A = ExecVectors[Aidx];
- const MCDCRecord::TestVector &B = ExecVectors[Bidx];
-
- // If condition values in both A and B aren't opposites, no match.
- // Because a value can be 0 (false), 1 (true), or -1 (DontCare), a check
- // that "XOR != 1" will ensure that the values are opposites and that
- // neither of them is a DontCare.
- // 1 XOR 0 == 1 | 0 XOR 0 == 0 | -1 XOR 0 == -1
- // 1 XOR 1 == 0 | 0 XOR 1 == 1 | -1 XOR 1 == -2
- // 1 XOR -1 == -2 | 0 XOR -1 == -1 | -1 XOR -1 == 0
- if ((A[ConditionIdx] ^ B[ConditionIdx]) != 1)
- return false;
-
- // If the results of both A and B aren't opposites, no match.
- if ((A[NumConditions] ^ B[NumConditions]) != 1)
- return false;
-
- for (unsigned Idx = 0; Idx < NumConditions; ++Idx) {
- // Look for other conditions that don't match. Skip over the given
- // Condition as well as any conditions marked as "don't care".
- const auto ARecordTyForCond = A[Idx];
- const auto BRecordTyForCond = B[Idx];
- if (Idx == ConditionIdx ||
- ARecordTyForCond == MCDCRecord::MCDC_DontCare ||
- BRecordTyForCond == MCDCRecord::MCDC_DontCare)
- continue;
-
- // If there is a condition mismatch with any of the other conditions,
- // there is no match for the test vectors.
- if (ARecordTyForCond != BRecordTyForCond)
- return false;
- }
-
- // Otherwise, match.
- return true;
- }
-
- /// Find all possible Independence Pairs for a boolean expression given its
- /// executed Test Vectors. This process involves looking at each condition
- /// and attempting to find two Test Vectors that "match", giving us a pair.
+ // Find an independence pair for each condition.
void findIndependencePairs() {
unsigned NumTVs = ExecVectors.size();
-
- // For each condition.
- for (unsigned C = 0; C < NumConditions; ++C) {
- bool PairFound = false;
-
- // For each executed test vector.
- for (unsigned I = 0; !PairFound && I < NumTVs; ++I) {
- // Compared to every other executed test vector.
- for (unsigned J = 0; !PairFound && J < NumTVs; ++J) {
- if (I == J)
+ for (unsigned I = 1; I < NumTVs; ++I) {
+ const MCDCRecord::TestVector &A = ExecVectors[I];
+ 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])
+ 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 a matching pair of vectors is found, record them.
- if ((PairFound = matchTestVectors(I, J, C)))
- IndependencePairs[C] = std::make_pair(I + 1, J + 1);
+ if (Flip != NumConditions)
+ break;
+ Flip = Idx;
}
----------------
MaskRay wrote:
I left some notes on https://maskray.me/blog/2024-01-28-mc-dc-and-compiler-implementations
GCC has a pending patch implementing MC/DC as well and they apply an algorithm described by _Efficient Test Coverage Measurement for MC/DC_, which is linear in terms of the number of conditions.
https://github.com/llvm/llvm-project/pull/79727
More information about the lldb-commits
mailing list