diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index 42da188fef34e..4f28f5da6cf81 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -451,19 +452,22 @@ struct MCDCRecord { private: CounterMappingRegion Region; TestVectors TV; - TVPairMap IndependencePairs; + std::optional IndependencePairs; BoolVector Folded; CondIDMap PosToID; LineColPairMap CondLoc; public: MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV, - TVPairMap &&IndependencePairs, BoolVector &&Folded, - CondIDMap &&PosToID, LineColPairMap &&CondLoc) - : Region(Region), TV(std::move(TV)), - IndependencePairs(std::move(IndependencePairs)), - Folded(std::move(Folded)), PosToID(std::move(PosToID)), - CondLoc(std::move(CondLoc)){}; + BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc) + : Region(Region), TV(std::move(TV)), Folded(std::move(Folded)), + PosToID(std::move(PosToID)), CondLoc(std::move(CondLoc)) { + findIndependencePairs(); + } + + // Compare executed test vectors against each other to find an independence + // pairs for each condition. This processing takes the most time. + void findIndependencePairs(); const CounterMappingRegion &getDecisionRegion() const { return Region; } unsigned getNumConditions() const { @@ -494,10 +498,10 @@ struct MCDCRecord { /// TestVectors requires a translation from a ordinal position to actual /// condition ID. This is done via PosToID[]. bool isConditionIndependencePairCovered(unsigned Condition) const { + assert(IndependencePairs); auto It = PosToID.find(Condition); - if (It != PosToID.end()) - return IndependencePairs.contains(It->second); - llvm_unreachable("Condition ID without an Ordinal mapping"); + assert(It != PosToID.end() && "Condition ID without an Ordinal mapping"); + return IndependencePairs->contains(It->second); } /// Return the Independence Pair that covers the given condition. Because @@ -507,7 +511,8 @@ struct MCDCRecord { /// via PosToID[]. TVRowPair getConditionIndependencePair(unsigned Condition) { assert(isConditionIndependencePairCovered(Condition)); - return IndependencePairs[PosToID[Condition]]; + assert(IndependencePairs); + return (*IndependencePairs)[PosToID[Condition]]; } float getPercentCovered() const { diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 87d8bb1bbb79c..2c7a77bac0932 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -221,6 +221,40 @@ Expected CounterMappingContext::evaluate(const Counter &C) const { return LastPoppedValue; } +// 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. +// - All other conditions' values must be equal or marked as "don't care". +void MCDCRecord::findIndependencePairs() { + if (IndependencePairs) + return; + + IndependencePairs.emplace(); + + unsigned NumTVs = TV.size(); + // Will be replaced to shorter expr. + unsigned TVTrueIdx = std::distance( + TV.begin(), + std::find_if(TV.begin(), TV.end(), + [&](auto I) { return (I.second == MCDCRecord::MCDC_True); }) + + ); + for (unsigned I = TVTrueIdx; I < NumTVs; ++I) { + const auto &[A, ACond] = TV[I]; + assert(ACond == MCDCRecord::MCDC_True); + for (unsigned J = 0; J < TVTrueIdx; ++J) { + const auto &[B, BCond] = TV[J]; + assert(BCond == MCDCRecord::MCDC_False); + // If the two vectors differ in exactly one condition, ignoring DontCare + // conditions, we have found an independence pair. + auto AB = A.getDifferences(B); + if (AB.count() == 1) + IndependencePairs->insert( + {AB.find_first(), std::make_pair(J + 1, I + 1)}); + } + } +} + mcdc::TVIdxBuilder::TVIdxBuilder(const SmallVectorImpl &NextIDs, int Offset) : Indices(NextIDs.size()) { @@ -375,9 +409,6 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder { /// ExecutedTestVectorBitmap. MCDCRecord::TestVectors &ExecVectors; - /// Number of False items in ExecVectors - unsigned NumExecVectorsF; - #ifndef NDEBUG DenseSet TVIdxs; #endif @@ -446,34 +477,11 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder { // Fill ExecVectors order by False items and True items. // ExecVectors is the alias of ExecVectorsByCond[false], so // Append ExecVectorsByCond[true] on it. - NumExecVectorsF = ExecVectors.size(); auto &ExecVectorsT = ExecVectorsByCond[true]; ExecVectors.append(std::make_move_iterator(ExecVectorsT.begin()), std::make_move_iterator(ExecVectorsT.end())); } - // 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. - // - All other conditions' values must be equal or marked as "don't care". - void findIndependencePairs() { - unsigned NumTVs = ExecVectors.size(); - for (unsigned I = NumExecVectorsF; I < NumTVs; ++I) { - const auto &[A, ACond] = ExecVectors[I]; - assert(ACond == MCDCRecord::MCDC_True); - for (unsigned J = 0; J < NumExecVectorsF; ++J) { - const auto &[B, BCond] = ExecVectors[J]; - assert(BCond == MCDCRecord::MCDC_False); - // If the two vectors differ in exactly one condition, ignoring DontCare - // conditions, we have found an independence pair. - auto AB = A.getDifferences(B); - if (AB.count() == 1) - IndependencePairs.insert( - {AB.find_first(), std::make_pair(J + 1, I + 1)}); - } - } - } - public: /// Process the MC/DC Record in order to produce a result for a boolean /// expression. This process includes tracking the conditions that comprise @@ -509,13 +517,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder { // Using Profile Bitmap from runtime, mark the executed test vectors. findExecutedTestVectors(); - // Compare executed test vectors against each other to find an independence - // pairs for each condition. This processing takes the most time. - findIndependencePairs(); - // Record Test vectors, executed vectors, and independence pairs. - return MCDCRecord(Region, std::move(ExecVectors), - std::move(IndependencePairs), std::move(Folded), + return MCDCRecord(Region, std::move(ExecVectors), std::move(Folded), std::move(PosToID), std::move(CondLoc)); } };