Skip to content
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

[MC/DC][Coverage] Loosen the limit of NumConds from 6 #82448

Merged
merged 48 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d168e0c
Implement MCDCTVIdxBuilder and MCDCTestVectorBuilder (LLVM side)
chapuni Feb 4, 2024
35b19ea
Revert "Implement MCDCTVIdxBuilder and MCDCTestVectorBuilder (LLVM si…
chapuni Feb 6, 2024
8c777eb
[Coverage] MCDCRecordProcessor: Find `ExecVectors` directly
chapuni Feb 6, 2024
56042d3
Merge branch 'mcdc/xv' into HEAD
chapuni Feb 6, 2024
5432aec
Implement MCDCTVIdxBuilder (LLVM side)
chapuni Feb 4, 2024
3ee8a61
Update comments and assertions
chapuni Feb 6, 2024
2fd504a
Merge remote-tracking branch 'origin/main' into mcdc/tvidx
chapuni Feb 8, 2024
1f0f3fc
Reorganize TVIdxBuilder
chapuni Feb 12, 2024
06c0801
Merge remote-tracking branch 'origin/main' into mcdc/tvidx
chapuni Feb 13, 2024
aa5b2f5
Merge remote-tracking branch 'origin/main' into HEAD
chapuni Feb 15, 2024
e3de647
[CoverageMapping] Refactor `mcdc::TVIdxBuilder`
chapuni Feb 15, 2024
753d0ad
remove <functional>
chapuni Feb 15, 2024
17cbac7
Update comments.
chapuni Feb 21, 2024
1a4ffa7
Add unittest
chapuni Feb 21, 2024
b5ecfcc
[MC/DC][Coverage] Loosen the limit of NumConds from 6
chapuni Feb 15, 2024
0ffad9c
Update testcases
chapuni Feb 21, 2024
c96fd2c
Use llvm::sort
chapuni Feb 21, 2024
357a693
EXPECT_
chapuni Feb 21, 2024
83d104c
Merge branch 'mcdc/tvidx' into HEAD
chapuni Feb 21, 2024
14c795e
Hide NConds
chapuni Feb 21, 2024
b6c1174
Merge remote-tracking branch 'chapuni/main' into mcdc/tvidx
chapuni Feb 25, 2024
cf936f6
Merge branch 'users/chapuni/mcdc/tvidx' into HEAD
chapuni Feb 25, 2024
662bdd6
Reformat
chapuni Feb 25, 2024
ac16655
Merge remote-tracking branch 'origin/main' into mcdc/clangtvidx
chapuni Feb 26, 2024
90bf8e9
Clarify bool
chapuni Feb 26, 2024
9eb6951
Update comments
chapuni Feb 26, 2024
86d67c6
Use MutableArrayRef :)
chapuni Feb 26, 2024
01abca2
Merge remote-tracking branch 'origin/main' into mcdc/clangtvidx
chapuni Feb 27, 2024
183c706
Merge branch 'main' into mcdc/clangtvidx
chapuni Apr 19, 2024
dd6f8be
Clarify 3rd arg of mcdc.tvbitmap.update is unused
chapuni May 9, 2024
cdd5531
Modify 3rd arg of mcdc.parameters to bits
chapuni May 8, 2024
54e6044
isMCDCBranch: Remove assert
chapuni May 9, 2024
b1a7100
isMCDCDecision: Remove assert
chapuni May 9, 2024
39802c5
Make llvm-cov capable of clang-18's profdata
chapuni May 14, 2024
f54c64d
Fix unittest
chapuni May 15, 2024
a6f7eef
Introduce `-fmcdc-max-conditions` and `-fmcdc-max-test-vectors`
chapuni May 16, 2024
0dd7ead
Merge branch 'main' into HEAD
chapuni May 20, 2024
cf837ae
mcdc-system-headers.cpp: Update
chapuni May 20, 2024
9e14c2a
llvm-cov tests for old (Version11) files
chapuni May 20, 2024
04f18ae
Merge branch 'main' into mcdc/clangtvidx
chapuni May 27, 2024
3ff3eb7
Update CoverageMapping/mcdc-scratch-space.c
chapuni May 27, 2024
296f5c5
Don't create tvbitmap_update if the record is allocated but excluded.
chapuni May 27, 2024
722424b
Update mcdc-error-conditions.cpp
chapuni Jun 10, 2024
183bc52
Update documents
chapuni Jun 10, 2024
83088f1
mcdc.tvupdate doesn't depend on condupdate
chapuni Jun 10, 2024
40872f5
Update SourceBasedCodeCoverage.rst
chapuni Jun 11, 2024
be5b28b
SourceBasedCodeCoverage.rst: s/you/users/
chapuni Jun 11, 2024
450d86b
SourceBasedCodeCoverage.rst: Clarify to be excluded.
chapuni Jun 13, 2024
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
Prev Previous commit
Next Next commit
Implement MCDCTVIdxBuilder (LLVM side)
This accepts current version of profdata. The output might be different.

See also
https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798
  • Loading branch information
chapuni committed Feb 6, 2024
commit 5432aecffd203f232842607ff581a20cbbf1ba3b
24 changes: 24 additions & 0 deletions llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <functional>
#include <iterator>
#include <memory>
#include <sstream>
Expand Down Expand Up @@ -557,6 +558,29 @@ struct MCDCRecord {
}
};

class MCDCTVIdxBuilder {
public:
struct MCDCNode {
int InCount = 0;
int Width;
struct {
int ID;
int Idx;
} Conds[2];
};

SmallVector<MCDCNode> Nodes;
unsigned NumTestVectors;

public:
using NodeIDs = std::tuple<unsigned, // ID1 (ends with 0)
unsigned, // ID1 for False
unsigned // ID1 for True
>;

MCDCTVIdxBuilder(std::function<NodeIDs(bool TellSize)> Fetcher);
};

/// A Counter mapping context is used to connect the counters, expressions
/// and the obtained counter values.
class CounterMappingContext {
Expand Down
162 changes: 142 additions & 20 deletions llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,119 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
return LastPoppedValue;
}

MCDCTVIdxBuilder::MCDCTVIdxBuilder(
std::function<NodeIDs(bool TellSize)> Fetcher) {
// Build Nodes and set up each InCount
int MaxID = -1;
Nodes.resize(std::get<0>(Fetcher(true)));
while (true) {
auto [ID1, FalseID1, TrueID1] = Fetcher(false);
if (ID1 == 0)
break;
int ID = ID1 - 1;
MaxID = std::max(MaxID, ID);
auto &Node = Nodes[ID];
Node.Conds[0].ID = FalseID1 - 1;
Node.Conds[1].ID = TrueID1 - 1;
for (unsigned I = 0; I < 2; ++I) {
#ifndef NDEBUG
Node.Conds[I].Idx = INT_MIN;
#endif
int NextID = Node.Conds[I].ID;
if (NextID >= 0)
++Nodes[NextID].InCount;
}
}

if (MaxID < 0)
return;

// Sort key ordered by <-Width, Ord>
SmallVector<std::tuple<int, /// -Width
unsigned, /// Ord
int, /// ID
unsigned /// Cond (0 or 1)
>>
Decisions;
chapuni marked this conversation as resolved.
Show resolved Hide resolved

// Traverse Nodes to assign Idx
SmallVector<int> Q;
assert(Nodes[0].InCount == 0);
Nodes[0].Width = 1;
Q.push_back(0);

unsigned Ord = 0;
while (!Q.empty()) {
int ID = *Q.begin();
Q.erase(Q.begin());
auto &Node = Nodes[ID];
assert(Node.Width > 0);

for (unsigned I = 0; I < 2; ++I) {
int NextID = Node.Conds[I].ID;
assert(NextID != 0);
if (NextID < 0) {
Decisions.emplace_back(-Node.Width, Ord++, ID, I);
chapuni marked this conversation as resolved.
Show resolved Hide resolved
assert(Ord == Decisions.size());
continue;
}

auto &NextNode = Nodes[NextID];
assert(NextNode.InCount > 0);
assert(Node.Conds[I].Idx == INT_MIN);
Node.Conds[I].Idx = NextNode.Width;
NextNode.Width += Node.Width;
if (--NextNode.InCount == 0)
Q.push_back(NextID);
}
}

std::sort(Decisions.begin(), Decisions.end());

// Assign TestVector Index
unsigned CurIdx = 0;
for (auto [NegWidth, Ord, ID, C] : Decisions) {
int Width = -NegWidth;
chapuni marked this conversation as resolved.
Show resolved Hide resolved
assert(Nodes[ID].Width == Width);
assert(Nodes[ID].Conds[C].Idx == INT_MIN);
assert(Nodes[ID].Conds[C].ID < 0);
Nodes[ID].Conds[C].Idx = CurIdx;
CurIdx += Width;
}
NumTestVectors = CurIdx;

#ifndef NDEBUG
for (const auto &Node : Nodes)
for (const auto &Cond : Node.Conds)
assert(Cond.Idx != INT_MIN);
#endif
}

namespace {

class MCDCRecordProcessor {
class BranchProvider {
using NodeIDs = MCDCTVIdxBuilder::NodeIDs;
ArrayRef<const CounterMappingRegion *> Branches;
unsigned BranchIdx = 0;

public:
BranchProvider(ArrayRef<const CounterMappingRegion *> Branches)
: Branches(Branches) {}

std::function<NodeIDs(bool)> getFetcher() {
return [this](bool TellSize) {
if (TellSize)
return NodeIDs(Branches.size(), 0, 0);
if (BranchIdx >= Branches.size())
return NodeIDs(0, 0, 0);
const auto *B = Branches[BranchIdx++];
return NodeIDs(B->MCDCParams.ID, B->MCDCParams.FalseID,
B->MCDCParams.TrueID);
};
}
};

class MCDCRecordProcessor : MCDCTVIdxBuilder {
/// A bitmap representing the executed test vectors for a boolean expression.
/// Each index of the bitmap corresponds to a possible test vector. An index
/// with a bit value of '1' indicates that the corresponding Test Vector
Expand Down Expand Up @@ -257,18 +367,28 @@ class MCDCRecordProcessor {
/// ExecutedTestVectorBitmap.
MCDCRecord::TestVectors ExecVectors;

#ifndef NDEBUG
DenseSet<unsigned> TVIDs;
#endif

public:
MCDCRecordProcessor(const BitVector &Bitmap,
const CounterMappingRegion &Region,
ArrayRef<const CounterMappingRegion *> Branches)
: Bitmap(Bitmap), Region(Region), Branches(Branches),
: MCDCTVIdxBuilder(BranchProvider(Branches).getFetcher()), Bitmap(Bitmap),
Region(Region), Branches(Branches),
NumConditions(Region.MCDCParams.NumConditions),
BitmapIdx(Region.MCDCParams.BitmapIdx * CHAR_BIT),
Folded(NumConditions, false), IndependencePairs(NumConditions) {}

private:
void recordTestVector(MCDCRecord::TestVector &TV, unsigned Index,
void recordTestVector(MCDCRecord::TestVector &TV, int TVIdx, unsigned Index,
MCDCRecord::CondState Result) {
#ifndef NDEBUG
assert(!TVIDs.contains(TVIdx));
TVIDs.insert(TVIdx);
#endif

if (!Bitmap[BitmapIdx + Index])
return;

Expand All @@ -283,25 +403,26 @@ class MCDCRecordProcessor {
// Walk the binary decision diagram 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,
void buildTestVector(MCDCRecord::TestVector &TV, int ID, int TVIdx,
unsigned Index) {
const CounterMappingRegion *Branch = Map[ID];

TV[ID - 1] = MCDCRecord::MCDC_False;
if (Branch->MCDCParams.FalseID > 0)
buildTestVector(TV, Branch->MCDCParams.FalseID, Index);
else
recordTestVector(TV, Index, MCDCRecord::MCDC_False);

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);
const auto &Node = Nodes[ID];

for (unsigned I = 0; I < 2; ++I) {
auto MCDCCond = (I ? MCDCRecord::MCDC_True : MCDCRecord::MCDC_False);
const auto &Cond = Node.Conds[I];
auto NextID = Cond.ID;
Index |= I << ID;
TV[ID] = MCDCCond;
if (NextID >= 0) {
buildTestVector(TV, NextID, TVIdx + Cond.Idx, Index);
} else {
assert(TVIdx < Node.Width);
recordTestVector(TV, Cond.Idx + TVIdx, Index, MCDCCond);
}
}

// Reset back to DontCare.
TV[ID - 1] = MCDCRecord::MCDC_DontCare;
TV[ID] = MCDCRecord::MCDC_DontCare;
}

/// Walk the bits in the bitmap. A bit set to '1' indicates that the test
Expand All @@ -311,7 +432,8 @@ class MCDCRecordProcessor {
// We start at the root node (ID == 1) with all values being DontCare.
// `Index` encodes the bitmask of true values and is initially 0.
MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare);
buildTestVector(TV, 1, 0);
buildTestVector(TV, 0, 0, 0);
assert(TVIDs.size() == NumTestVectors);
}

// Find an independence pair for each condition:
Expand Down
Loading