Skip to content

[MC/DC] Refactor: Isolate the final result out of TestVector #82282

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

Merged
merged 4 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ struct MCDCRecord {
enum CondState { MCDC_DontCare = -1, MCDC_False = 0, MCDC_True = 1 };

using TestVector = llvm::SmallVector<CondState>;
using TestVectors = llvm::SmallVector<TestVector>;
using TestVectors = llvm::SmallVector<std::pair<TestVector, CondState>>;
using BoolVector = llvm::SmallVector<bool>;
using TVRowPair = std::pair<unsigned, unsigned>;
using TVPairMap = llvm::DenseMap<unsigned, TVRowPair>;
Expand Down Expand Up @@ -422,13 +422,13 @@ struct MCDCRecord {
/// accessing conditions in the TestVectors requires a translation from a
/// ordinal position to actual condition ID. This is done via PosToID[].
CondState getTVCondition(unsigned TestVectorIndex, unsigned Condition) {
return TV[TestVectorIndex][PosToID[Condition]];
return TV[TestVectorIndex].first[PosToID[Condition]];
}

/// Return the Result evaluation for an executed test vector.
/// See MCDCRecordProcessor::RecordTestVector().
CondState getTVResult(unsigned TestVectorIndex) {
return TV[TestVectorIndex][getNumConditions()];
return TV[TestVectorIndex].second;
}

/// Determine whether a given condition (indicated by Condition) is covered
Expand Down
37 changes: 25 additions & 12 deletions llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,16 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
/// Mapping of calculated MC/DC Independence Pairs for each condition.
MCDCRecord::TVPairMap IndependencePairs;

/// Storage for ExecVectors
/// ExecVectors is the alias of its 0th element.
std::array<MCDCRecord::TestVectors, 2> ExecVectorsByCond;

/// Actual executed Test Vectors for the boolean expression, based on
/// ExecutedTestVectorBitmap.
MCDCRecord::TestVectors ExecVectors;
MCDCRecord::TestVectors &ExecVectors;

/// Number of False items in ExecVectors
unsigned NumExecVectorsF;

#ifndef NDEBUG
DenseSet<unsigned> TVIdxs;
Expand All @@ -385,7 +392,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
: NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
Region(Region), DecisionParams(Region.getDecisionParams()),
Branches(Branches), NumConditions(DecisionParams.NumConditions),
Folded(NumConditions, false), IndependencePairs(NumConditions) {}
Folded(NumConditions, false), IndependencePairs(NumConditions),
ExecVectors(ExecVectorsByCond[false]) {}

private:
// Walk the binary decision diagram and try assigning both false and true to
Expand Down Expand Up @@ -415,11 +423,9 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
continue;

// Copy the completed test vector to the vector of testvectors.
ExecVectors.push_back(TV);

// The final value (T,F) is equal to the last non-dontcare state on the
// path (in a short-circuiting system).
ExecVectors.back().push_back(MCDCCond);
ExecVectorsByCond[MCDCCond].push_back({TV, MCDCCond});
}

// Reset back to DontCare.
Expand All @@ -437,6 +443,14 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
buildTestVector(TV, 0, 0, 0);
assert(TVIdxs.size() == unsigned(NumTestVectors) &&
"TVIdxs wasn't fulfilled");

// 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:
Expand All @@ -445,13 +459,12 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
// - All other conditions' values must be equal or marked as "don't care".
void findIndependencePairs() {
unsigned NumTVs = ExecVectors.size();
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;
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);
unsigned Flip = NumConditions, Idx;
for (Idx = 0; Idx < NumConditions; ++Idx) {
MCDCRecord::CondState ACond = A[Idx], BCond = B[Idx];
Expand Down