-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Coverage] MCDC: Move findIndependencePairs deferred into MCDCRecord #121188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,7 @@ | |
#include <cstdint> | ||
#include <iterator> | ||
#include <memory> | ||
#include <optional> | ||
#include <sstream> | ||
#include <string> | ||
#include <system_error> | ||
|
@@ -451,19 +452,22 @@ struct MCDCRecord { | |
private: | ||
CounterMappingRegion Region; | ||
TestVectors TV; | ||
TVPairMap IndependencePairs; | ||
std::optional<TVPairMap> 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"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this changed to an assert from unreachable? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we expect "satisfies or crash" here? I wanted to eliminate the condition. |
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assert is unneeded due to immediate dereference There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's redundant since |
||
return (*IndependencePairs)[PosToID[Condition]]; | ||
} | ||
|
||
float getPercentCovered() const { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -221,6 +221,40 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const { | |
return LastPoppedValue; | ||
} | ||
|
||
// Find an independence pair for each condition: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can this be a doxygen comment in CoverageMapping.h? |
||
// - 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Debug output for something like "independence pairs already computed; not finding anything"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Soft updates" is assumed. It is invalidated if "merging" is executed. |
||
return; | ||
|
||
IndependencePairs.emplace(); | ||
|
||
unsigned NumTVs = TV.size(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const? |
||
// Will be replaced to shorter expr. | ||
unsigned TVTrueIdx = std::distance( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const? |
||
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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if I understand correctly, we assume that
I think this renaming may be clearer:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah this is all code movement. Duh. Perhaps we can address this in a follow-up NFC commit. |
||
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<ConditionIDs> &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<unsigned> 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)); | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense to have this actually return the
std::optional<TVPairMap>
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd make sense since it always flush and reconstruct the map.