https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/79727
>From 1d2470c2d67673f9ef9ea504e0abb3e964d43ebb Mon Sep 17 00:00:00 2001 From: Fangrui Song <i...@maskray.me> Date: Sat, 27 Jan 2024 22:24:39 -0800 Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?= =?UTF-8?q?l=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.4 --- .../ProfileData/Coverage/CoverageMapping.cpp | 133 +++++------------- 1 file changed, 35 insertions(+), 98 deletions(-) diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index da8e1d87319dded..16a45d1788236a0 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -286,17 +286,8 @@ class MCDCRecordProcessor { TestVectors((size_t)1 << NumConditions) {} private: - void recordTestVector(MCDCRecord::TestVector &TV, + void recordTestVector(MCDCRecord::TestVector &TV, unsigned Index, MCDCRecord::CondState Result) { - // Calculate an index that is used to identify the test vector in a vector - // of test vectors. This index also corresponds to the index values of an - // MCDC Region's bitmap (see findExecutedTestVectors()). - unsigned Index = 0; - for (auto Cond = std::rbegin(TV); Cond != std::rend(TV); ++Cond) { - Index <<= 1; - Index |= (*Cond == MCDCRecord::MCDC_True) ? 0x1 : 0x0; - } - // Copy the completed test vector to the vector of testvectors. TestVectors[Index] = TV; @@ -305,38 +296,25 @@ class MCDCRecordProcessor { TestVectors[Index].push_back(Result); } - void shouldCopyOffTestVectorForTruePath(MCDCRecord::TestVector &TV, - unsigned ID) { - // Branch regions are hashed based on an ID. - const CounterMappingRegion *Branch = Map[ID]; - - TV[ID - 1] = MCDCRecord::MCDC_True; - if (Branch->MCDCParams.TrueID > 0) - buildTestVector(TV, Branch->MCDCParams.TrueID); - else - recordTestVector(TV, MCDCRecord::MCDC_True); - } - - void shouldCopyOffTestVectorForFalsePath(MCDCRecord::TestVector &TV, - unsigned ID) { - // Branch regions are hashed based on an ID. + // Walk the binary decision tree 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); + buildTestVector(TV, Branch->MCDCParams.FalseID, Index); else - recordTestVector(TV, MCDCRecord::MCDC_False); - } + recordTestVector(TV, Index, MCDCRecord::MCDC_False); - /// Starting with the base test vector, build a comprehensive list of - /// possible test vectors by recursively walking the branch condition IDs - /// provided. Once an end node is reached, record the test vector in a vector - /// of test vectors that can be matched against during MC/DC analysis, and - /// then reset the positions to 'DontCare'. - void buildTestVector(MCDCRecord::TestVector &TV, unsigned ID = 1) { - shouldCopyOffTestVectorForTruePath(TV, ID); - shouldCopyOffTestVectorForFalsePath(TV, ID); + 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; @@ -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; } + // 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)}); } } } @@ -458,7 +395,7 @@ class MCDCRecordProcessor { MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare); // Use the base test vector to build the list of all possible test vectors. - buildTestVector(TV); + buildTestVector(TV, 1, 0); // Using Profile Bitmap from runtime, mark the executed test vectors. findExecutedTestVectors(ExecutedTestVectorBitmap); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits