Skip to content

Commit 4926f12

Browse files
authored
[Coverage] ProfileData: Handle MC/DC Bitmap as BitVector. NFC. (#80608)
* `getFunctionBitmap()` stores not `std::vector<uint8_t>` but `BitVector`. * `CounterMappingContext` holds `Bitmap` (instead of the ref of bytes) * `Bitmap` and `BitmapIdx` are used instead of `evaluateBitmap()`. FIXME: `InstrProfRecord` itself should handle `Bitmap` as `BitVector`.
1 parent 067882c commit 4926f12

File tree

4 files changed

+42
-63
lines changed

4 files changed

+42
-63
lines changed

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -562,15 +562,15 @@ struct MCDCRecord {
562562
class CounterMappingContext {
563563
ArrayRef<CounterExpression> Expressions;
564564
ArrayRef<uint64_t> CounterValues;
565-
ArrayRef<uint8_t> BitmapBytes;
565+
BitVector Bitmap;
566566

567567
public:
568568
CounterMappingContext(ArrayRef<CounterExpression> Expressions,
569569
ArrayRef<uint64_t> CounterValues = std::nullopt)
570570
: Expressions(Expressions), CounterValues(CounterValues) {}
571571

572572
void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; }
573-
void setBitmapBytes(ArrayRef<uint8_t> Bytes) { BitmapBytes = Bytes; }
573+
void setBitmap(BitVector &&Bitmap_) { Bitmap = std::move(Bitmap_); }
574574

575575
void dump(const Counter &C, raw_ostream &OS) const;
576576
void dump(const Counter &C) const { dump(C, dbgs()); }
@@ -579,16 +579,10 @@ class CounterMappingContext {
579579
/// counter was executed.
580580
Expected<int64_t> evaluate(const Counter &C) const;
581581

582-
/// Return the number of times that a region of code associated with this
583-
/// counter was executed.
584-
Expected<BitVector>
585-
evaluateBitmap(const CounterMappingRegion *MCDCDecision) const;
586-
587582
/// Return an MCDC record that indicates executed test vectors and condition
588583
/// pairs.
589584
Expected<MCDCRecord>
590585
evaluateMCDCRegion(const CounterMappingRegion &Region,
591-
const BitVector &Bitmap,
592586
ArrayRef<const CounterMappingRegion *> Branches);
593587

594588
unsigned getMaxCounterID(const Counter &C) const;

llvm/include/llvm/ProfileData/InstrProfReader.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -736,9 +736,9 @@ class IndexedInstrProfReader : public InstrProfReader {
736736
Error getFunctionCounts(StringRef FuncName, uint64_t FuncHash,
737737
std::vector<uint64_t> &Counts);
738738

739-
/// Fill Bitmap Bytes with the profile data for the given function name.
740-
Error getFunctionBitmapBytes(StringRef FuncName, uint64_t FuncHash,
741-
std::vector<uint8_t> &BitmapBytes);
739+
/// Fill Bitmap with the profile data for the given function name.
740+
Error getFunctionBitmap(StringRef FuncName, uint64_t FuncHash,
741+
BitVector &Bitmap);
742742

743743
/// Return the maximum of all known function counts.
744744
/// \c UseCS indicates whether to use the context-sensitive count.

llvm/lib/ProfileData/Coverage/CoverageMapping.cpp

Lines changed: 20 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -223,33 +223,12 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
223223
return LastPoppedValue;
224224
}
225225

226-
Expected<BitVector> CounterMappingContext::evaluateBitmap(
227-
const CounterMappingRegion *MCDCDecision) const {
228-
unsigned ID = MCDCDecision->MCDCParams.BitmapIdx;
229-
unsigned NC = MCDCDecision->MCDCParams.NumConditions;
230-
unsigned SizeInBits = llvm::alignTo(uint64_t(1) << NC, CHAR_BIT);
231-
unsigned SizeInBytes = SizeInBits / CHAR_BIT;
232-
233-
assert(ID + SizeInBytes <= BitmapBytes.size() && "BitmapBytes overrun");
234-
ArrayRef<uint8_t> Bytes(&BitmapBytes[ID], SizeInBytes);
235-
236-
// Mask each bitmap byte into the BitVector. Go in reverse so that the
237-
// bitvector can just be shifted over by one byte on each iteration.
238-
BitVector Result(SizeInBits, false);
239-
for (auto Byte = std::rbegin(Bytes); Byte != std::rend(Bytes); ++Byte) {
240-
uint32_t Data = *Byte;
241-
Result <<= CHAR_BIT;
242-
Result.setBitsInMask(&Data, 1);
243-
}
244-
return Result;
245-
}
246-
247226
class MCDCRecordProcessor {
248227
/// A bitmap representing the executed test vectors for a boolean expression.
249228
/// Each index of the bitmap corresponds to a possible test vector. An index
250229
/// with a bit value of '1' indicates that the corresponding Test Vector
251230
/// identified by that index was executed.
252-
const BitVector &ExecutedTestVectorBitmap;
231+
const BitVector &Bitmap;
253232

254233
/// Decision Region to which the ExecutedTestVectorBitmap applies.
255234
const CounterMappingRegion &Region;
@@ -261,6 +240,8 @@ class MCDCRecordProcessor {
261240
/// Total number of conditions in the boolean expression.
262241
unsigned NumConditions;
263242

243+
unsigned BitmapIdx;
244+
264245
/// Mapping of a condition ID to its corresponding branch region.
265246
llvm::DenseMap<unsigned, const CounterMappingRegion *> Map;
266247

@@ -281,8 +262,9 @@ class MCDCRecordProcessor {
281262
MCDCRecordProcessor(const BitVector &Bitmap,
282263
const CounterMappingRegion &Region,
283264
ArrayRef<const CounterMappingRegion *> Branches)
284-
: ExecutedTestVectorBitmap(Bitmap), Region(Region), Branches(Branches),
265+
: Bitmap(Bitmap), Region(Region), Branches(Branches),
285266
NumConditions(Region.MCDCParams.NumConditions),
267+
BitmapIdx(Region.MCDCParams.BitmapIdx * CHAR_BIT),
286268
Folded(NumConditions, false), IndependencePairs(NumConditions),
287269
TestVectors((size_t)1 << NumConditions) {}
288270

@@ -323,9 +305,10 @@ class MCDCRecordProcessor {
323305

324306
/// Walk the bits in the bitmap. A bit set to '1' indicates that the test
325307
/// vector at the corresponding index was executed during a test run.
326-
void findExecutedTestVectors(const BitVector &ExecutedTestVectorBitmap) {
327-
for (unsigned Idx = 0; Idx < ExecutedTestVectorBitmap.size(); ++Idx) {
328-
if (ExecutedTestVectorBitmap[Idx] == 0)
308+
void findExecutedTestVectors() {
309+
for (unsigned Idx = 0; Idx < (1u << NumConditions); ++Idx) {
310+
assert(BitmapIdx + Idx < Bitmap.size() && "Bitmap overrun");
311+
if (Bitmap[BitmapIdx + Idx] == 0)
329312
continue;
330313
assert(!TestVectors[Idx].empty() && "Test Vector doesn't exist.");
331314
ExecVectors.push_back(TestVectors[Idx]);
@@ -402,7 +385,7 @@ class MCDCRecordProcessor {
402385
buildTestVector(TV, 1, 0);
403386

404387
// Using Profile Bitmap from runtime, mark the executed test vectors.
405-
findExecutedTestVectors(ExecutedTestVectorBitmap);
388+
findExecutedTestVectors();
406389

407390
// Compare executed test vectors against each other to find an independence
408391
// pairs for each condition. This processing takes the most time.
@@ -417,10 +400,9 @@ class MCDCRecordProcessor {
417400

418401
Expected<MCDCRecord> CounterMappingContext::evaluateMCDCRegion(
419402
const CounterMappingRegion &Region,
420-
const BitVector &ExecutedTestVectorBitmap,
421403
ArrayRef<const CounterMappingRegion *> Branches) {
422404

423-
MCDCRecordProcessor MCDCProcessor(ExecutedTestVectorBitmap, Region, Branches);
405+
MCDCRecordProcessor MCDCProcessor(Bitmap, Region, Branches);
424406
return MCDCProcessor.processMCDCRecord();
425407
}
426408

@@ -506,6 +488,7 @@ static unsigned getMaxCounterID(const CounterMappingContext &Ctx,
506488
return MaxCounterID;
507489
}
508490

491+
/// Returns the bit count
509492
static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx,
510493
const CoverageMappingRecord &Record) {
511494
unsigned MaxBitmapID = 0;
@@ -521,7 +504,7 @@ static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx,
521504
}
522505
}
523506
unsigned SizeInBits = llvm::alignTo(uint64_t(1) << NumConditions, CHAR_BIT);
524-
return MaxBitmapID + (SizeInBits / CHAR_BIT);
507+
return MaxBitmapID * CHAR_BIT + SizeInBits;
525508
}
526509

527510
namespace {
@@ -708,9 +691,9 @@ Error CoverageMapping::loadFunctionRecord(
708691
}
709692
Ctx.setCounts(Counts);
710693

711-
std::vector<uint8_t> BitmapBytes;
712-
if (Error E = ProfileReader.getFunctionBitmapBytes(
713-
Record.FunctionName, Record.FunctionHash, BitmapBytes)) {
694+
BitVector Bitmap;
695+
if (Error E = ProfileReader.getFunctionBitmap(Record.FunctionName,
696+
Record.FunctionHash, Bitmap)) {
714697
instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
715698
if (IPE == instrprof_error::hash_mismatch) {
716699
FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
@@ -719,9 +702,9 @@ Error CoverageMapping::loadFunctionRecord(
719702
}
720703
if (IPE != instrprof_error::unknown_function)
721704
return make_error<InstrProfError>(IPE);
722-
BitmapBytes.assign(getMaxBitmapSize(Ctx, Record) + 1, 0);
705+
Bitmap = BitVector(getMaxBitmapSize(Ctx, Record));
723706
}
724-
Ctx.setBitmapBytes(BitmapBytes);
707+
Ctx.setBitmap(std::move(Bitmap));
725708

726709
assert(!Record.MappingRegions.empty() && "Function has no regions");
727710

@@ -772,23 +755,11 @@ Error CoverageMapping::loadFunctionRecord(
772755
auto MCDCDecision = Result->first;
773756
auto &MCDCBranches = Result->second;
774757

775-
// Evaluating the test vector bitmap for the decision region entails
776-
// calculating precisely what bits are pertinent to this region alone.
777-
// This is calculated based on the recorded offset into the global
778-
// profile bitmap; the length is calculated based on the recorded
779-
// number of conditions.
780-
Expected<BitVector> ExecutedTestVectorBitmap =
781-
Ctx.evaluateBitmap(MCDCDecision);
782-
if (auto E = ExecutedTestVectorBitmap.takeError()) {
783-
consumeError(std::move(E));
784-
return Error::success();
785-
}
786-
787758
// Since the bitmap identifies the executed test vectors for an MC/DC
788759
// DecisionRegion, all of the information is now available to process.
789760
// This is where the bulk of the MC/DC progressing takes place.
790-
Expected<MCDCRecord> Record = Ctx.evaluateMCDCRegion(
791-
*MCDCDecision, *ExecutedTestVectorBitmap, MCDCBranches);
761+
Expected<MCDCRecord> Record =
762+
Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches);
792763
if (auto E = Record.takeError()) {
793764
consumeError(std::move(E));
794765
return Error::success();

llvm/lib/ProfileData/InstrProfReader.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,13 +1435,27 @@ Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
14351435
return success();
14361436
}
14371437

1438-
Error IndexedInstrProfReader::getFunctionBitmapBytes(
1439-
StringRef FuncName, uint64_t FuncHash, std::vector<uint8_t> &BitmapBytes) {
1438+
Error IndexedInstrProfReader::getFunctionBitmap(StringRef FuncName,
1439+
uint64_t FuncHash,
1440+
BitVector &Bitmap) {
14401441
Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
14411442
if (Error E = Record.takeError())
14421443
return error(std::move(E));
14431444

1444-
BitmapBytes = Record.get().BitmapBytes;
1445+
const auto &BitmapBytes = Record.get().BitmapBytes;
1446+
size_t I = 0, E = BitmapBytes.size();
1447+
Bitmap.resize(E * CHAR_BIT);
1448+
BitVector::apply(
1449+
[&](auto x) {
1450+
decltype(x) W = 0;
1451+
size_t N = std::min(E - I, sizeof(W));
1452+
std::memcpy((void *)&W, &BitmapBytes[I], N);
1453+
I += N;
1454+
return W;
1455+
},
1456+
Bitmap, Bitmap);
1457+
assert(I == E);
1458+
14451459
return success();
14461460
}
14471461

0 commit comments

Comments
 (0)