Skip to content

Commit 9709795

Browse files
authored
[Coverage] MCDC: Move findIndependencePairs deferred into MCDCRecord (#121188)
The result of "Independence pairs" is not mergeable. This change makes defers re-calculation of "Independence pairs" after merging test vectors. No apparent behavior changes.
1 parent 4dc34b0 commit 9709795

File tree

2 files changed

+51
-43
lines changed

2 files changed

+51
-43
lines changed

llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <cstdint>
3636
#include <iterator>
3737
#include <memory>
38+
#include <optional>
3839
#include <sstream>
3940
#include <string>
4041
#include <system_error>
@@ -448,19 +449,22 @@ struct MCDCRecord {
448449
private:
449450
CounterMappingRegion Region;
450451
TestVectors TV;
451-
TVPairMap IndependencePairs;
452+
std::optional<TVPairMap> IndependencePairs;
452453
BoolVector Folded;
453454
CondIDMap PosToID;
454455
LineColPairMap CondLoc;
455456

456457
public:
457458
MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV,
458-
TVPairMap &&IndependencePairs, BoolVector &&Folded,
459-
CondIDMap &&PosToID, LineColPairMap &&CondLoc)
460-
: Region(Region), TV(std::move(TV)),
461-
IndependencePairs(std::move(IndependencePairs)),
462-
Folded(std::move(Folded)), PosToID(std::move(PosToID)),
463-
CondLoc(std::move(CondLoc)){};
459+
BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc)
460+
: Region(Region), TV(std::move(TV)), Folded(std::move(Folded)),
461+
PosToID(std::move(PosToID)), CondLoc(std::move(CondLoc)) {
462+
findIndependencePairs();
463+
}
464+
465+
// Compare executed test vectors against each other to find an independence
466+
// pairs for each condition. This processing takes the most time.
467+
void findIndependencePairs();
464468

465469
const CounterMappingRegion &getDecisionRegion() const { return Region; }
466470
unsigned getNumConditions() const {
@@ -493,10 +497,10 @@ struct MCDCRecord {
493497
/// TestVectors requires a translation from a ordinal position to actual
494498
/// condition ID. This is done via PosToID[].
495499
bool isConditionIndependencePairCovered(unsigned Condition) const {
500+
assert(IndependencePairs);
496501
auto It = PosToID.find(Condition);
497-
if (It != PosToID.end())
498-
return IndependencePairs.contains(It->second);
499-
llvm_unreachable("Condition ID without an Ordinal mapping");
502+
assert(It != PosToID.end() && "Condition ID without an Ordinal mapping");
503+
return IndependencePairs->contains(It->second);
500504
}
501505

502506
/// Return the Independence Pair that covers the given condition. Because
@@ -506,7 +510,8 @@ struct MCDCRecord {
506510
/// via PosToID[].
507511
TVRowPair getConditionIndependencePair(unsigned Condition) {
508512
assert(isConditionIndependencePairCovered(Condition));
509-
return IndependencePairs[PosToID[Condition]];
513+
assert(IndependencePairs);
514+
return (*IndependencePairs)[PosToID[Condition]];
510515
}
511516

512517
float getPercentCovered() const {

llvm/lib/ProfileData/Coverage/CoverageMapping.cpp

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,40 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
221221
return LastPoppedValue;
222222
}
223223

224+
// Find an independence pair for each condition:
225+
// - The condition is true in one test and false in the other.
226+
// - The decision outcome is true one test and false in the other.
227+
// - All other conditions' values must be equal or marked as "don't care".
228+
void MCDCRecord::findIndependencePairs() {
229+
if (IndependencePairs)
230+
return;
231+
232+
IndependencePairs.emplace();
233+
234+
unsigned NumTVs = TV.size();
235+
// Will be replaced to shorter expr.
236+
unsigned TVTrueIdx = std::distance(
237+
TV.begin(),
238+
std::find_if(TV.begin(), TV.end(),
239+
[&](auto I) { return (I.second == MCDCRecord::MCDC_True); })
240+
241+
);
242+
for (unsigned I = TVTrueIdx; I < NumTVs; ++I) {
243+
const auto &[A, ACond] = TV[I];
244+
assert(ACond == MCDCRecord::MCDC_True);
245+
for (unsigned J = 0; J < TVTrueIdx; ++J) {
246+
const auto &[B, BCond] = TV[J];
247+
assert(BCond == MCDCRecord::MCDC_False);
248+
// If the two vectors differ in exactly one condition, ignoring DontCare
249+
// conditions, we have found an independence pair.
250+
auto AB = A.getDifferences(B);
251+
if (AB.count() == 1)
252+
IndependencePairs->insert(
253+
{AB.find_first(), std::make_pair(J + 1, I + 1)});
254+
}
255+
}
256+
}
257+
224258
mcdc::TVIdxBuilder::TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs,
225259
int Offset)
226260
: Indices(NextIDs.size()) {
@@ -375,9 +409,6 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
375409
/// ExecutedTestVectorBitmap.
376410
MCDCRecord::TestVectors &ExecVectors;
377411

378-
/// Number of False items in ExecVectors
379-
unsigned NumExecVectorsF;
380-
381412
#ifndef NDEBUG
382413
DenseSet<unsigned> TVIdxs;
383414
#endif
@@ -447,34 +478,11 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
447478
// Fill ExecVectors order by False items and True items.
448479
// ExecVectors is the alias of ExecVectorsByCond[false], so
449480
// Append ExecVectorsByCond[true] on it.
450-
NumExecVectorsF = ExecVectors.size();
451481
auto &ExecVectorsT = ExecVectorsByCond[true];
452482
ExecVectors.append(std::make_move_iterator(ExecVectorsT.begin()),
453483
std::make_move_iterator(ExecVectorsT.end()));
454484
}
455485

456-
// Find an independence pair for each condition:
457-
// - The condition is true in one test and false in the other.
458-
// - The decision outcome is true one test and false in the other.
459-
// - All other conditions' values must be equal or marked as "don't care".
460-
void findIndependencePairs() {
461-
unsigned NumTVs = ExecVectors.size();
462-
for (unsigned I = NumExecVectorsF; I < NumTVs; ++I) {
463-
const auto &[A, ACond] = ExecVectors[I];
464-
assert(ACond == MCDCRecord::MCDC_True);
465-
for (unsigned J = 0; J < NumExecVectorsF; ++J) {
466-
const auto &[B, BCond] = ExecVectors[J];
467-
assert(BCond == MCDCRecord::MCDC_False);
468-
// If the two vectors differ in exactly one condition, ignoring DontCare
469-
// conditions, we have found an independence pair.
470-
auto AB = A.getDifferences(B);
471-
if (AB.count() == 1)
472-
IndependencePairs.insert(
473-
{AB.find_first(), std::make_pair(J + 1, I + 1)});
474-
}
475-
}
476-
}
477-
478486
public:
479487
/// Process the MC/DC Record in order to produce a result for a boolean
480488
/// expression. This process includes tracking the conditions that comprise
@@ -510,13 +518,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
510518
// Using Profile Bitmap from runtime, mark the executed test vectors.
511519
findExecutedTestVectors();
512520

513-
// Compare executed test vectors against each other to find an independence
514-
// pairs for each condition. This processing takes the most time.
515-
findIndependencePairs();
516-
517521
// Record Test vectors, executed vectors, and independence pairs.
518-
return MCDCRecord(Region, std::move(ExecVectors),
519-
std::move(IndependencePairs), std::move(Folded),
522+
return MCDCRecord(Region, std::move(ExecVectors), std::move(Folded),
520523
std::move(PosToID), std::move(CondLoc));
521524
}
522525
};

0 commit comments

Comments
 (0)