[clang] [compiler-rt] [llvm] llvm-cov: Merge records for template instantiations (PR #121197)
NAKAMURA Takumi via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 27 05:31:40 PST 2024
https://github.com/chapuni updated https://github.com/llvm/llvm-project/pull/121197
>From 178b57cbbcb2b21b7d13f90ffd75903417913438 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 2 Oct 2024 23:11:36 +0900
Subject: [PATCH 01/30] [Coverage] Move SingleByteCoverage out of CountedRegion
`SingleByteCoverage` is not per-region attribute at least.
At the moment, this change moves it into `FunctionRecord`.
---
.../ProfileData/Coverage/CoverageMapping.h | 27 +++++++-------
.../ProfileData/Coverage/CoverageMapping.cpp | 36 ++++++++++++-------
2 files changed, 36 insertions(+), 27 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index fa07b3a9e8b14f..77c447efe1a7c9 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -359,19 +359,15 @@ struct CountedRegion : public CounterMappingRegion {
uint64_t ExecutionCount;
uint64_t FalseExecutionCount;
bool Folded;
- bool HasSingleByteCoverage;
- CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
- bool HasSingleByteCoverage)
+ CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
- FalseExecutionCount(0), Folded(false),
- HasSingleByteCoverage(HasSingleByteCoverage) {}
+ FalseExecutionCount(0), Folded(false) {}
CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
- uint64_t FalseExecutionCount, bool HasSingleByteCoverage)
+ uint64_t FalseExecutionCount)
: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
- FalseExecutionCount(FalseExecutionCount), Folded(false),
- HasSingleByteCoverage(HasSingleByteCoverage) {}
+ FalseExecutionCount(FalseExecutionCount), Folded(false) {}
};
/// MCDC Record grouping all information together.
@@ -702,9 +698,12 @@ struct FunctionRecord {
std::vector<MCDCRecord> MCDCRecords;
/// The number of times this function was executed.
uint64_t ExecutionCount = 0;
+ bool SingleByteCoverage;
- FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
- : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
+ FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
+ bool SingleByteCoverage)
+ : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
+ SingleByteCoverage(SingleByteCoverage) {}
FunctionRecord(FunctionRecord &&FR) = default;
FunctionRecord &operator=(FunctionRecord &&) = default;
@@ -714,11 +713,10 @@ struct FunctionRecord {
}
void pushRegion(CounterMappingRegion Region, uint64_t Count,
- uint64_t FalseCount, bool HasSingleByteCoverage) {
+ uint64_t FalseCount) {
if (Region.Kind == CounterMappingRegion::BranchRegion ||
Region.Kind == CounterMappingRegion::MCDCBranchRegion) {
- CountedBranchRegions.emplace_back(Region, Count, FalseCount,
- HasSingleByteCoverage);
+ CountedBranchRegions.emplace_back(Region, Count, FalseCount);
// If both counters are hard-coded to zero, then this region represents a
// constant-folded branch.
if (Region.Count.isZero() && Region.FalseCount.isZero())
@@ -727,8 +725,7 @@ struct FunctionRecord {
}
if (CountedRegions.empty())
ExecutionCount = Count;
- CountedRegions.emplace_back(Region, Count, FalseCount,
- HasSingleByteCoverage);
+ CountedRegions.emplace_back(Region, Count, FalseCount);
}
};
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 18643c6b44485e..a02136d5b0386d 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -808,6 +808,7 @@ Error CoverageMapping::loadFunctionRecord(
else
OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
+ bool SingleByteCoverage = ProfileReader.hasSingleByteCoverage();
CounterMappingContext Ctx(Record.Expressions);
std::vector<uint64_t> Counts;
@@ -855,7 +856,7 @@ Error CoverageMapping::loadFunctionRecord(
return Error::success();
MCDCDecisionRecorder MCDCDecisions;
- FunctionRecord Function(OrigFuncName, Record.Filenames);
+ FunctionRecord Function(OrigFuncName, Record.Filenames, SingleByteCoverage);
for (const auto &Region : Record.MappingRegions) {
// MCDCDecisionRegion should be handled first since it overlaps with
// others inside.
@@ -873,8 +874,7 @@ Error CoverageMapping::loadFunctionRecord(
consumeError(std::move(E));
return Error::success();
}
- Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount,
- ProfileReader.hasSingleByteCoverage());
+ Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
// Record ExpansionRegion.
if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
@@ -1270,7 +1270,8 @@ class SegmentBuilder {
/// Combine counts of regions which cover the same area.
static ArrayRef<CountedRegion>
- combineRegions(MutableArrayRef<CountedRegion> Regions) {
+ combineRegions(MutableArrayRef<CountedRegion> Regions,
+ bool SingleByteCoverage) {
if (Regions.empty())
return Regions;
auto Active = Regions.begin();
@@ -1297,9 +1298,7 @@ class SegmentBuilder {
// We add counts of the regions of the same kind as the active region
// to handle the both situations.
if (I->Kind == Active->Kind) {
- assert(I->HasSingleByteCoverage == Active->HasSingleByteCoverage &&
- "Regions are generated in different coverage modes");
- if (I->HasSingleByteCoverage)
+ if (SingleByteCoverage)
Active->ExecutionCount = Active->ExecutionCount || I->ExecutionCount;
else
Active->ExecutionCount += I->ExecutionCount;
@@ -1311,12 +1310,14 @@ class SegmentBuilder {
public:
/// Build a sorted list of CoverageSegments from a list of Regions.
static std::vector<CoverageSegment>
- buildSegments(MutableArrayRef<CountedRegion> Regions) {
+ buildSegments(MutableArrayRef<CountedRegion> Regions,
+ bool SingleByteCoverage) {
std::vector<CoverageSegment> Segments;
SegmentBuilder Builder(Segments);
sortNestedRegions(Regions);
- ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
+ ArrayRef<CountedRegion> CombinedRegions =
+ combineRegions(Regions, SingleByteCoverage);
LLVM_DEBUG({
dbgs() << "Combined regions:\n";
@@ -1403,10 +1404,14 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
// the filename, we may get back some records that are not in the file.
ArrayRef<unsigned> RecordIndices =
getImpreciseRecordIndicesForFilename(Filename);
+ std::optional<bool> SingleByteCoverage;
for (unsigned RecordIndex : RecordIndices) {
const FunctionRecord &Function = Functions[RecordIndex];
auto MainFileID = findMainViewFileID(Filename, Function);
auto FileIDs = gatherFileIDs(Filename, Function);
+ assert(!SingleByteCoverage ||
+ *SingleByteCoverage == Function.SingleByteCoverage);
+ SingleByteCoverage = Function.SingleByteCoverage;
for (const auto &CR : Function.CountedRegions)
if (FileIDs.test(CR.FileID)) {
Regions.push_back(CR);
@@ -1424,7 +1429,8 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
}
LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
- FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
+ FileCoverage.Segments =
+ SegmentBuilder::buildSegments(Regions, *SingleByteCoverage);
return FileCoverage;
}
@@ -1480,7 +1486,8 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
<< "\n");
- FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
+ FunctionCoverage.Segments =
+ SegmentBuilder::buildSegments(Regions, Function.SingleByteCoverage);
return FunctionCoverage;
}
@@ -1490,8 +1497,12 @@ CoverageData CoverageMapping::getCoverageForExpansion(
CoverageData ExpansionCoverage(
Expansion.Function.Filenames[Expansion.FileID]);
std::vector<CountedRegion> Regions;
+ std::optional<bool> SingleByteCoverage;
for (const auto &CR : Expansion.Function.CountedRegions)
if (CR.FileID == Expansion.FileID) {
+ assert(!SingleByteCoverage ||
+ *SingleByteCoverage == Expansion.Function.SingleByteCoverage);
+ SingleByteCoverage = Expansion.Function.SingleByteCoverage;
Regions.push_back(CR);
if (isExpansion(CR, Expansion.FileID))
ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
@@ -1503,7 +1514,8 @@ CoverageData CoverageMapping::getCoverageForExpansion(
LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
<< Expansion.FileID << "\n");
- ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
+ ExpansionCoverage.Segments =
+ SegmentBuilder::buildSegments(Regions, *SingleByteCoverage);
return ExpansionCoverage;
}
>From aacb50ddf87d96b4a0644c7ef5d0a86dc94f069b Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 2 Oct 2024 23:25:52 +0900
Subject: [PATCH 02/30] [Coverage] Make SingleByteCoverage work consistent to
merging
- Round `Counts` as 1/0
- Confirm both `ExecutionCount` and `AltExecutionCount` are in range.
---
compiler-rt/test/profile/instrprof-block-coverage.c | 2 +-
compiler-rt/test/profile/instrprof-entry-coverage.c | 2 +-
llvm/include/llvm/ProfileData/InstrProf.h | 5 ++++-
llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 3 +++
llvm/lib/ProfileData/InstrProf.cpp | 2 +-
llvm/lib/ProfileData/InstrProfReader.cpp | 1 +
6 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/compiler-rt/test/profile/instrprof-block-coverage.c b/compiler-rt/test/profile/instrprof-block-coverage.c
index 829d5af8dc3f9e..8d924e1cac64d8 100644
--- a/compiler-rt/test/profile/instrprof-block-coverage.c
+++ b/compiler-rt/test/profile/instrprof-block-coverage.c
@@ -49,4 +49,4 @@ int main(int argc, char *argv[]) {
// CHECK-ERROR-NOT: warning: {{.*}}: Found inconsistent block coverage
-// COUNTS: Maximum function count: 4
+// COUNTS: Maximum function count: 1
diff --git a/compiler-rt/test/profile/instrprof-entry-coverage.c b/compiler-rt/test/profile/instrprof-entry-coverage.c
index 1c6816ba01964b..b93a4e0c43ccd6 100644
--- a/compiler-rt/test/profile/instrprof-entry-coverage.c
+++ b/compiler-rt/test/profile/instrprof-entry-coverage.c
@@ -36,4 +36,4 @@ int main(int argc, char *argv[]) {
// CHECK-DAG: foo
// CHECK-DAG: bar
-// COUNTS: Maximum function count: 2
+// COUNTS: Maximum function count: 1
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index b0b2258735e2ae..df9e76966bf42b 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -830,6 +830,7 @@ struct InstrProfValueSiteRecord {
/// Profiling information for a single function.
struct InstrProfRecord {
std::vector<uint64_t> Counts;
+ bool SingleByteCoverage = false;
std::vector<uint8_t> BitmapBytes;
InstrProfRecord() = default;
@@ -839,13 +840,15 @@ struct InstrProfRecord {
: Counts(std::move(Counts)), BitmapBytes(std::move(BitmapBytes)) {}
InstrProfRecord(InstrProfRecord &&) = default;
InstrProfRecord(const InstrProfRecord &RHS)
- : Counts(RHS.Counts), BitmapBytes(RHS.BitmapBytes),
+ : Counts(RHS.Counts), SingleByteCoverage(RHS.SingleByteCoverage),
+ BitmapBytes(RHS.BitmapBytes),
ValueData(RHS.ValueData
? std::make_unique<ValueProfData>(*RHS.ValueData)
: nullptr) {}
InstrProfRecord &operator=(InstrProfRecord &&) = default;
InstrProfRecord &operator=(const InstrProfRecord &RHS) {
Counts = RHS.Counts;
+ SingleByteCoverage = RHS.SingleByteCoverage;
BitmapBytes = RHS.BitmapBytes;
if (!RHS.ValueData) {
ValueData = nullptr;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index a02136d5b0386d..bc765c59381718 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -874,6 +874,9 @@ Error CoverageMapping::loadFunctionRecord(
consumeError(std::move(E));
return Error::success();
}
+ assert(!SingleByteCoverage ||
+ (0 <= *ExecutionCount && *ExecutionCount <= 1 &&
+ 0 <= *AltExecutionCount && *AltExecutionCount <= 1));
Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
// Record ExpansionRegion.
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index b9937c9429b77d..0f6677b4d35718 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -952,7 +952,7 @@ void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight,
Value = getInstrMaxCountValue();
Overflowed = true;
}
- Counts[I] = Value;
+ Counts[I] = (SingleByteCoverage && Value != 0 ? 1 : Value);
if (Overflowed)
Warn(instrprof_error::counter_overflow);
}
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index b90617c74f6d13..a07d7f573275ba 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -743,6 +743,7 @@ Error RawInstrProfReader<IntPtrT>::readRawCounts(
Record.Counts.clear();
Record.Counts.reserve(NumCounters);
+ Record.SingleByteCoverage = hasSingleByteCoverage();
for (uint32_t I = 0; I < NumCounters; I++) {
const char *Ptr =
CountersStart + CounterBaseOffset + I * getCounterTypeSize();
>From b9bbc7cac3076594cd326ffa7f2d4fc4a92fabb9 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 5 Oct 2024 10:43:26 +0900
Subject: [PATCH 03/30] Rework. (Also reverts "[Coverage] Move
SingleByteCoverage out of CountedRegion")
---
.../test/profile/instrprof-block-coverage.c | 2 +-
.../test/profile/instrprof-entry-coverage.c | 2 +-
.../ProfileData/Coverage/CoverageMapping.h | 27 +++++++------
llvm/include/llvm/ProfileData/InstrProf.h | 5 +--
.../ProfileData/Coverage/CoverageMapping.cpp | 40 +++++++------------
llvm/lib/ProfileData/InstrProf.cpp | 2 +-
llvm/lib/ProfileData/InstrProfReader.cpp | 1 -
7 files changed, 33 insertions(+), 46 deletions(-)
diff --git a/compiler-rt/test/profile/instrprof-block-coverage.c b/compiler-rt/test/profile/instrprof-block-coverage.c
index 8d924e1cac64d8..829d5af8dc3f9e 100644
--- a/compiler-rt/test/profile/instrprof-block-coverage.c
+++ b/compiler-rt/test/profile/instrprof-block-coverage.c
@@ -49,4 +49,4 @@ int main(int argc, char *argv[]) {
// CHECK-ERROR-NOT: warning: {{.*}}: Found inconsistent block coverage
-// COUNTS: Maximum function count: 1
+// COUNTS: Maximum function count: 4
diff --git a/compiler-rt/test/profile/instrprof-entry-coverage.c b/compiler-rt/test/profile/instrprof-entry-coverage.c
index b93a4e0c43ccd6..1c6816ba01964b 100644
--- a/compiler-rt/test/profile/instrprof-entry-coverage.c
+++ b/compiler-rt/test/profile/instrprof-entry-coverage.c
@@ -36,4 +36,4 @@ int main(int argc, char *argv[]) {
// CHECK-DAG: foo
// CHECK-DAG: bar
-// COUNTS: Maximum function count: 1
+// COUNTS: Maximum function count: 2
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 77c447efe1a7c9..fa07b3a9e8b14f 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -359,15 +359,19 @@ struct CountedRegion : public CounterMappingRegion {
uint64_t ExecutionCount;
uint64_t FalseExecutionCount;
bool Folded;
+ bool HasSingleByteCoverage;
- CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
+ CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
+ bool HasSingleByteCoverage)
: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
- FalseExecutionCount(0), Folded(false) {}
+ FalseExecutionCount(0), Folded(false),
+ HasSingleByteCoverage(HasSingleByteCoverage) {}
CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
- uint64_t FalseExecutionCount)
+ uint64_t FalseExecutionCount, bool HasSingleByteCoverage)
: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
- FalseExecutionCount(FalseExecutionCount), Folded(false) {}
+ FalseExecutionCount(FalseExecutionCount), Folded(false),
+ HasSingleByteCoverage(HasSingleByteCoverage) {}
};
/// MCDC Record grouping all information together.
@@ -698,12 +702,9 @@ struct FunctionRecord {
std::vector<MCDCRecord> MCDCRecords;
/// The number of times this function was executed.
uint64_t ExecutionCount = 0;
- bool SingleByteCoverage;
- FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames,
- bool SingleByteCoverage)
- : Name(Name), Filenames(Filenames.begin(), Filenames.end()),
- SingleByteCoverage(SingleByteCoverage) {}
+ FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
+ : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
FunctionRecord(FunctionRecord &&FR) = default;
FunctionRecord &operator=(FunctionRecord &&) = default;
@@ -713,10 +714,11 @@ struct FunctionRecord {
}
void pushRegion(CounterMappingRegion Region, uint64_t Count,
- uint64_t FalseCount) {
+ uint64_t FalseCount, bool HasSingleByteCoverage) {
if (Region.Kind == CounterMappingRegion::BranchRegion ||
Region.Kind == CounterMappingRegion::MCDCBranchRegion) {
- CountedBranchRegions.emplace_back(Region, Count, FalseCount);
+ CountedBranchRegions.emplace_back(Region, Count, FalseCount,
+ HasSingleByteCoverage);
// If both counters are hard-coded to zero, then this region represents a
// constant-folded branch.
if (Region.Count.isZero() && Region.FalseCount.isZero())
@@ -725,7 +727,8 @@ struct FunctionRecord {
}
if (CountedRegions.empty())
ExecutionCount = Count;
- CountedRegions.emplace_back(Region, Count, FalseCount);
+ CountedRegions.emplace_back(Region, Count, FalseCount,
+ HasSingleByteCoverage);
}
};
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index df9e76966bf42b..b0b2258735e2ae 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -830,7 +830,6 @@ struct InstrProfValueSiteRecord {
/// Profiling information for a single function.
struct InstrProfRecord {
std::vector<uint64_t> Counts;
- bool SingleByteCoverage = false;
std::vector<uint8_t> BitmapBytes;
InstrProfRecord() = default;
@@ -840,15 +839,13 @@ struct InstrProfRecord {
: Counts(std::move(Counts)), BitmapBytes(std::move(BitmapBytes)) {}
InstrProfRecord(InstrProfRecord &&) = default;
InstrProfRecord(const InstrProfRecord &RHS)
- : Counts(RHS.Counts), SingleByteCoverage(RHS.SingleByteCoverage),
- BitmapBytes(RHS.BitmapBytes),
+ : Counts(RHS.Counts), BitmapBytes(RHS.BitmapBytes),
ValueData(RHS.ValueData
? std::make_unique<ValueProfData>(*RHS.ValueData)
: nullptr) {}
InstrProfRecord &operator=(InstrProfRecord &&) = default;
InstrProfRecord &operator=(const InstrProfRecord &RHS) {
Counts = RHS.Counts;
- SingleByteCoverage = RHS.SingleByteCoverage;
BitmapBytes = RHS.BitmapBytes;
if (!RHS.ValueData) {
ValueData = nullptr;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index bc765c59381718..9a03dede84b6df 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -856,7 +856,7 @@ Error CoverageMapping::loadFunctionRecord(
return Error::success();
MCDCDecisionRecorder MCDCDecisions;
- FunctionRecord Function(OrigFuncName, Record.Filenames, SingleByteCoverage);
+ FunctionRecord Function(OrigFuncName, Record.Filenames);
for (const auto &Region : Record.MappingRegions) {
// MCDCDecisionRegion should be handled first since it overlaps with
// others inside.
@@ -874,10 +874,10 @@ Error CoverageMapping::loadFunctionRecord(
consumeError(std::move(E));
return Error::success();
}
- assert(!SingleByteCoverage ||
- (0 <= *ExecutionCount && *ExecutionCount <= 1 &&
- 0 <= *AltExecutionCount && *AltExecutionCount <= 1));
- Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
+ Function.pushRegion(
+ Region, (SingleByteCoverage && *ExecutionCount ? 1 : *ExecutionCount),
+ (SingleByteCoverage && *AltExecutionCount ? 1 : *AltExecutionCount),
+ SingleByteCoverage);
// Record ExpansionRegion.
if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
@@ -1273,8 +1273,7 @@ class SegmentBuilder {
/// Combine counts of regions which cover the same area.
static ArrayRef<CountedRegion>
- combineRegions(MutableArrayRef<CountedRegion> Regions,
- bool SingleByteCoverage) {
+ combineRegions(MutableArrayRef<CountedRegion> Regions) {
if (Regions.empty())
return Regions;
auto Active = Regions.begin();
@@ -1301,7 +1300,9 @@ class SegmentBuilder {
// We add counts of the regions of the same kind as the active region
// to handle the both situations.
if (I->Kind == Active->Kind) {
- if (SingleByteCoverage)
+ assert(I->HasSingleByteCoverage == Active->HasSingleByteCoverage &&
+ "Regions are generated in different coverage modes");
+ if (I->HasSingleByteCoverage)
Active->ExecutionCount = Active->ExecutionCount || I->ExecutionCount;
else
Active->ExecutionCount += I->ExecutionCount;
@@ -1313,14 +1314,12 @@ class SegmentBuilder {
public:
/// Build a sorted list of CoverageSegments from a list of Regions.
static std::vector<CoverageSegment>
- buildSegments(MutableArrayRef<CountedRegion> Regions,
- bool SingleByteCoverage) {
+ buildSegments(MutableArrayRef<CountedRegion> Regions) {
std::vector<CoverageSegment> Segments;
SegmentBuilder Builder(Segments);
sortNestedRegions(Regions);
- ArrayRef<CountedRegion> CombinedRegions =
- combineRegions(Regions, SingleByteCoverage);
+ ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
LLVM_DEBUG({
dbgs() << "Combined regions:\n";
@@ -1407,14 +1406,10 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
// the filename, we may get back some records that are not in the file.
ArrayRef<unsigned> RecordIndices =
getImpreciseRecordIndicesForFilename(Filename);
- std::optional<bool> SingleByteCoverage;
for (unsigned RecordIndex : RecordIndices) {
const FunctionRecord &Function = Functions[RecordIndex];
auto MainFileID = findMainViewFileID(Filename, Function);
auto FileIDs = gatherFileIDs(Filename, Function);
- assert(!SingleByteCoverage ||
- *SingleByteCoverage == Function.SingleByteCoverage);
- SingleByteCoverage = Function.SingleByteCoverage;
for (const auto &CR : Function.CountedRegions)
if (FileIDs.test(CR.FileID)) {
Regions.push_back(CR);
@@ -1432,8 +1427,7 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
}
LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
- FileCoverage.Segments =
- SegmentBuilder::buildSegments(Regions, *SingleByteCoverage);
+ FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
return FileCoverage;
}
@@ -1489,8 +1483,7 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
<< "\n");
- FunctionCoverage.Segments =
- SegmentBuilder::buildSegments(Regions, Function.SingleByteCoverage);
+ FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
return FunctionCoverage;
}
@@ -1500,12 +1493,8 @@ CoverageData CoverageMapping::getCoverageForExpansion(
CoverageData ExpansionCoverage(
Expansion.Function.Filenames[Expansion.FileID]);
std::vector<CountedRegion> Regions;
- std::optional<bool> SingleByteCoverage;
for (const auto &CR : Expansion.Function.CountedRegions)
if (CR.FileID == Expansion.FileID) {
- assert(!SingleByteCoverage ||
- *SingleByteCoverage == Expansion.Function.SingleByteCoverage);
- SingleByteCoverage = Expansion.Function.SingleByteCoverage;
Regions.push_back(CR);
if (isExpansion(CR, Expansion.FileID))
ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);
@@ -1517,8 +1506,7 @@ CoverageData CoverageMapping::getCoverageForExpansion(
LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
<< Expansion.FileID << "\n");
- ExpansionCoverage.Segments =
- SegmentBuilder::buildSegments(Regions, *SingleByteCoverage);
+ ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
return ExpansionCoverage;
}
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 0f6677b4d35718..b9937c9429b77d 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -952,7 +952,7 @@ void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight,
Value = getInstrMaxCountValue();
Overflowed = true;
}
- Counts[I] = (SingleByteCoverage && Value != 0 ? 1 : Value);
+ Counts[I] = Value;
if (Overflowed)
Warn(instrprof_error::counter_overflow);
}
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index a07d7f573275ba..b90617c74f6d13 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -743,7 +743,6 @@ Error RawInstrProfReader<IntPtrT>::readRawCounts(
Record.Counts.clear();
Record.Counts.reserve(NumCounters);
- Record.SingleByteCoverage = hasSingleByteCoverage();
for (uint32_t I = 0; I < NumCounters; I++) {
const char *Ptr =
CountersStart + CounterBaseOffset + I * getCounterTypeSize();
>From 52f072e5058267660aa8c8fbb00c5d09634f22b3 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 18 Oct 2024 08:32:39 +0900
Subject: [PATCH 04/30] clang/test/CoverageMapping/single-byte-counters.cpp:
Rewrite counter matches
---
.../CoverageMapping/single-byte-counters.cpp | 163 +++++++-----------
1 file changed, 65 insertions(+), 98 deletions(-)
diff --git a/clang/test/CoverageMapping/single-byte-counters.cpp b/clang/test/CoverageMapping/single-byte-counters.cpp
index 8e9b613dcc68f7..d20b695bc2636a 100644
--- a/clang/test/CoverageMapping/single-byte-counters.cpp
+++ b/clang/test/CoverageMapping/single-byte-counters.cpp
@@ -1,169 +1,136 @@
// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -mllvm -enable-single-byte-coverage=true -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name single-byte-counters.cpp %s | FileCheck %s
// CHECK: testIf
-int testIf(int x) { // CHECK-NEXT: File 0, [[@LINE]]:19 -> [[@LINE+10]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:13 = #0
- // CHECK-NEXT: Gap,File 0, [[@LINE+4]]:14 -> [[@LINE+5]]:5 = #1
- // CHECK-NEXT: File 0, [[@LINE+4]]:5 -> [[@LINE+4]]:16 = #1
- // CHECK-NEXT: File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:16 = #2
+int testIf(int x) { // CHECK-NEXT: File 0, [[@LINE]]:19 -> [[@LINE+7]]:2 = [[C00:#0]]
int result = 0;
- if (x == 0)
- result = -1;
+ if (x == 0) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:13 = [[C00]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:5 = [[C0T:#1]]
+ result = -1; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:16 = [[C0T]]
- return result;
+ return result; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:16 = [[C0E:#2]]
}
// CHECK-NEXT: testIfElse
-int testIfElse(int x) { // CHECK-NEXT: File 0, [[@LINE]]:23 -> [[@LINE+13]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+7]]:7 -> [[@LINE+7]]:12 = #0
- // CHECK-NEXT: Gap,File 0, [[@LINE+6]]:13 -> [[@LINE+7]]:5 = #1
- // CHECK-NEXT: File 0, [[@LINE+6]]:5 -> [[@LINE+6]]:15 = #1
- // CHECK-NEXT: Gap,File 0, [[@LINE+5]]:16 -> [[@LINE+7]]:5 = #2
- // CHECK-NEXT: File 0, [[@LINE+6]]:5 -> [[@LINE+6]]:19 = #2
- // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+6]]:16 = #3
+int testIfElse(int x) { // CHECK-NEXT: File 0, [[@LINE]]:23 -> [[@LINE+8]]:2 = [[C10:#0]]
int result = 0;
- if (x < 0)
- result = 0;
- else
- result = x * x;
- return result;
+ if (x < 0) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = [[C10]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+1]]:5 = [[C1T:#1]]
+ result = 0; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:15 = [[C1T]]
+ else // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:16 -> [[@LINE+1]]:5 = [[C1F:#2]]
+ result = x * x; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:19 = [[C1F]]
+ return result; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:16 = [[C1E:#3]]
}
// CHECK-NEXT: testIfElseReturn
-int testIfElseReturn(int x) { // CHECK-NEXT: File 0, [[@LINE]]:29 -> [[@LINE+14]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+8]]:7 -> [[@LINE+8]]:12 = #0
- // CHECK-NEXT: Gap,File 0, [[@LINE+7]]:13 -> [[@LINE+8]]:5 = #1
- // CHECK-NEXT: File 0, [[@LINE+7]]:5 -> [[@LINE+7]]:19 = #1
- // CHECK-NEXT: Gap,File 0, [[@LINE+6]]:20 -> [[@LINE+8]]:5 = #2
- // CHECK-NEXT: File 0, [[@LINE+7]]:5 -> [[@LINE+7]]:13 = #2
- // CHECK-NEXT: Gap,File 0, [[@LINE+6]]:14 -> [[@LINE+7]]:3 = #3
- // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+6]]:16 = #3
+int testIfElseReturn(int x) { // CHECK-NEXT: File 0, [[@LINE]]:29 -> [[@LINE+9]]:2 = [[C20:#0]]
int result = 0;
- if (x > 0)
- result = x * x;
- else
- return 0;
- return result;
+ if (x > 0) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = [[C20]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:13 -> [[@LINE+1]]:5 = [[C2T:#1]]
+ result = x * x; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:19 = [[C2T]]
+ else // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:20 -> [[@LINE+1]]:5 = [[C2F:#2]]
+ return 0; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE]]:13 = [[C2F]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+1]]:3 = [[C2E:#3]]
+ return result; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:16 = [[C2E:#3]]
}
// CHECK-NEXT: testSwitch
-int testSwitch(int x) { // CHECK-NEXT: File 0, [[@LINE]]:23 -> [[@LINE+22]]:2 = #0
- // CHECK-NEXT: Gap,File 0, [[@LINE+9]]:14 -> [[@LINE+17]]:15 = 0
- // CHECK-NEXT: File 0, [[@LINE+9]]:3 -> [[@LINE+11]]:10 = #2
- // CHECK-NEXT: Gap,File 0, [[@LINE+10]]:11 -> [[@LINE+11]]:3 = 0
- // CHECK-NEXT: File 0, [[@LINE+10]]:3 -> [[@LINE+12]]:10 = #3
- // CHECK-NEXT: Gap,File 0, [[@LINE+11]]:11 -> [[@LINE+12]]:3 = 0
- // CHECK-NEXT: File 0, [[@LINE+11]]:3 -> [[@LINE+12]]:15 = #4
- // CHECK-NEXT: Gap,File 0, [[@LINE+12]]:4 -> [[@LINE+14]]:3 = #1
- // CHECK-NEXT: File 0, [[@LINE+13]]:3 -> [[@LINE+13]]:16 = #1
+int testSwitch(int x) { // CHECK-NEXT: File 0, [[@LINE]]:23 -> [[@LINE+17]]:2 = [[C30:#0]]
int result;
switch (x) {
- case 1:
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:14 -> [[@LINE+10]]:15 = 0
+ case 1: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = [[C31:#2]]
result = 1;
break;
- case 2:
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = 0
+ case 2: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+2]]:10 = [[C32:#3]]
result = 2;
break;
- default:
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:11 -> [[@LINE+1]]:3 = 0
+ default: // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE+1]]:15 = [[C3D:#4]]
result = 0;
}
-
- return result;
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE+1]]:3 = [[C3E:#1]]
+ return result; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:16 = [[C3E]]
}
// CHECK-NEXT: testWhile
-int testWhile() { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+13]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+6]]:10 -> [[@LINE+6]]:16 = #1
- // CHECK-NEXT: Gap,File 0, [[@LINE+5]]:17 -> [[@LINE+5]]:18 = #2
- // CHECK-NEXT: File 0, [[@LINE+4]]:18 -> [[@LINE+7]]:4 = #2
- // CHECK-NEXT: File 0, [[@LINE+8]]:3 -> [[@LINE+8]]:13 = #3
+int testWhile() { // CHECK-NEXT: File 0, [[@LINE]]:17 -> [[@LINE+11]]:2 = [[C40:#0]]
int i = 0;
int sum = 0;
- while (i < 10) {
+ while (i < 10) { // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE]]:16 = [[C4C:#1]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:17 -> [[@LINE-1]]:18 = [[C4T:#2]]
+ // CHECK-NEXT: File 0, [[@LINE-2]]:18 -> [[@LINE+3]]:4 = [[C4T]]
sum += i;
i++;
}
- return sum;
+ return sum; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:13 = [[C4E:#3]]
}
// CHECK-NEXT: testContinue
-int testContinue() { // CHECK-NEXT: File 0, [[@LINE]]:20 -> [[@LINE+21]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+12]]:10 -> [[@LINE+12]]:16 = #1
- // CHECK-NEXT: Gap,File 0, [[@LINE+11]]:17 -> [[@LINE+11]]:18 = #2
- // CHECK-NEXT: File 0, [[@LINE+10]]:18 -> [[@LINE+15]]:4 = #2
- // CHECK-NEXT: File 0, [[@LINE+10]]:9 -> [[@LINE+10]]:15 = #2
- // CHECK-NEXT: Gap,File 0, [[@LINE+9]]:16 -> [[@LINE+10]]:7 = #4
- // CHECK-NEXT: File 0, [[@LINE+9]]:7 -> [[@LINE+9]]:15 = #4
- // CHECK-NEXT: Gap,File 0, [[@LINE+8]]:16 -> [[@LINE+9]]:5 = #5
- // CHECK-NEXT: File 0, [[@LINE+8]]:5 -> [[@LINE+10]]:4 = #5
- // CHECK-NEXT: Gap,File 0, [[@LINE+9]]:4 -> [[@LINE+11]]:3 = #3
- // CHECK-NEXT: File 0, [[@LINE+10]]:3 -> [[@LINE+10]]:13 = #3
+int testContinue() { // CHECK-NEXT: File 0, [[@LINE]]:20 -> [[@LINE+15]]:2 = [[C50:#0]]
int i = 0;
int sum = 0;
- while (i < 10) {
- if (i == 4)
- continue;
- sum += i;
+ while (i < 10) { // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE]]:16 = [[C5C:#1]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:17 -> [[@LINE-1]]:18 = [[C5B:#2]]
+ // CHECK-NEXT: File 0, [[@LINE-2]]:18 -> [[@LINE+7]]:4 = [[C5B]]
+ if (i == 4) // CHECK-NEXT: File 0, [[@LINE]]:9 -> [[@LINE]]:15 = [[C5B]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:16 -> [[@LINE+1]]:7 = [[C5T:#4]]
+ continue; // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:15 = [[C5T]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:16 -> [[@LINE+1]]:5 = [[C5F:#5]]
+ sum += i; // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+2]]:4 = [[C5F]]
i++;
}
-
- return sum;
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:4 -> [[@LINE+1]]:3 = [[C5E:#3]]
+ return sum; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:13 = [[C5E]]
}
// CHECK-NEXT: testFor
-int testFor() { // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE+13]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+7]]:19 -> [[@LINE+7]]:25 = #1
- // CHECK-NEXT: File 0, [[@LINE+6]]:27 -> [[@LINE+6]]:30 = #2
- // CHECK-NEXT: Gap,File 0, [[@LINE+5]]:31 -> [[@LINE+5]]:32 = #3
- // CHECK-NEXT: File 0, [[@LINE+4]]:32 -> [[@LINE+6]]:4 = #3
- // CHECK-NEXT: File 0, [[@LINE+7]]:3 -> [[@LINE+7]]:13 = #4
+int testFor() { // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE+12]]:2 = [[C60:#0]]
int i;
int sum = 0;
+ // CHECK-NEXT: File 0, [[@LINE+2]]:19 -> [[@LINE+2]]:25 = [[C61:#1]]
+ // CHECK-NEXT: File 0, [[@LINE+1]]:27 -> [[@LINE+1]]:30 = [[C6C:#2]]
for (int i = 0; i < 10; i++) {
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:31 -> [[@LINE-1]]:32 = [[C6B:#3]]
+ // CHECK-NEXT: File 0, [[@LINE-2]]:32 -> [[@LINE+2]]:4 = [[C6B]]
sum += i;
}
- return sum;
+ return sum; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:13 = [[C6E:#4]]
}
// CHECK-NEXT: testForRange
-int testForRange() { // CHECK-NEXT: File 0, [[@LINE]]:20 -> [[@LINE+12]]:2 = #0
- // CHECK-NEXT: Gap,File 0, [[@LINE+6]]:28 -> [[@LINE+6]]:29 = #1
- // CHECK-NEXT: File 0, [[@LINE+5]]:29 -> [[@LINE+7]]:4 = #1
- // CHECK-NEXT: File 0, [[@LINE+8]]:3 -> [[@LINE+8]]:13 = #2
+int testForRange() { // CHECK-NEXT: File 0, [[@LINE]]:20 -> [[@LINE+11]]:2 = [[C70:#0]]
int sum = 0;
int array[] = {1, 2, 3, 4, 5};
for (int element : array) {
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:28 -> [[@LINE-1]]:29 = [[C7B:#1]]
+ // CHECK-NEXT: File 0, [[@LINE-2]]:29 -> [[@LINE+2]]:4 = [[C7B]]
sum += element;
}
- return sum;
+ return sum; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:13 = [[C7E:#2]]
}
// CHECK-NEXT: testDo
-int testDo() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+12]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+5]]:6 -> [[@LINE+8]]:4 = #1
- // CHECK-NEXT: File 0, [[@LINE+7]]:12 -> [[@LINE+7]]:17 = #2
- // CHECK-NEXT: File 0, [[@LINE+8]]:3 -> [[@LINE+8]]:13 = #3
+int testDo() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+9]]:2 = [[C80:#0]]
int i = 0;
int sum = 0;
- do {
+ do { // CHECK-NEXT: File 0, [[@LINE]]:6 -> [[@LINE+3]]:4 = [[C8B:#1]]
sum += i;
i++;
- } while (i < 5);
+ } while (i < 5); // CHECK-NEXT: File 0, [[@LINE]]:12 -> [[@LINE]]:17 = [[C8C:#2]]
- return sum;
+ return sum; // CHECK-NEXT: File 0, [[@LINE]]:3 -> [[@LINE]]:13 = [[C8E:#3]]
}
// CHECK-NEXT: testConditional
-int testConditional(int x) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+8]]:2 = #0
- // CHECK-NEXT: File 0, [[@LINE+5]]:15 -> [[@LINE+5]]:22 = #0
- // CHECK-NEXT: Gap,File 0, [[@LINE+4]]:24 -> [[@LINE+4]]:25 = #2
- // CHECK-NEXT: File 0, [[@LINE+3]]:25 -> [[@LINE+3]]:26 = #2
- // CHECK-NEXT: File 0, [[@LINE+2]]:29 -> [[@LINE+2]]:31 = #3
- // CHECK-NEXT: File 0, [[@LINE+2]]:2 -> [[@LINE+2]]:15 = #1
- int result = (x > 0) ? 1 : -1;
- return result;
+int testConditional(int x) { // CHECK-NEXT: File 0, [[@LINE]]:28 -> [[@LINE+6]]:2 = [[C90:#0]]
+ int result = (x > 0) ? 1 : -1; // CHECK-NEXT: File 0, [[@LINE]]:15 -> [[@LINE]]:22 = [[C90]]
+ // CHECK-NEXT: Gap,File 0, [[@LINE-1]]:24 -> [[@LINE-1]]:25 = [[C9T:#2]]
+ // CHECK-NEXT: File 0, [[@LINE-2]]:25 -> [[@LINE-2]]:26 = [[C9T]]
+ // CHECK-NEXT: File 0, [[@LINE-3]]:29 -> [[@LINE-3]]:31 = [[C9F:#3]]
+ return result; // CHECK-NEXT: File 0, [[@LINE]]:2 -> [[@LINE]]:15 = [[C9E:#1]]
}
>From 97a4a8f40afb53250639c29e193edd814cb82f58 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 20 Nov 2024 23:33:51 +0900
Subject: [PATCH 05/30] test/llvm-cov: Transform %.c* tests to {%.test,
Inputs/%.c*}
And reformat. NFC.
---
.../{ => Inputs}/branch-logical-mixed.cpp | 13 +---
.../llvm-cov/{ => Inputs}/branch-macros.cpp | 14 +---
.../Inputs/branch-showBranchPercentage.c | 58 +++++++++++++++
.../llvm-cov/Inputs/branch-templates.cpp | 38 ++++++++++
.../Inputs/showLineExecutionCounts.cpp | 29 ++++++++
.../test/tools/llvm-cov/branch-c-general.test | 2 +-
.../tools/llvm-cov/branch-logical-mixed.test | 11 +++
llvm/test/tools/llvm-cov/branch-macros.test | 11 +++
.../tools/llvm-cov/branch-noShowBranch.test | 8 +-
...age.c => branch-showBranchPercentage.test} | 57 +--------------
...ch-templates.cpp => branch-templates.test} | 46 ++----------
.../llvm-cov/showLineExecutionCounts.cpp | 73 -------------------
.../llvm-cov/showLineExecutionCounts.test | 43 +++++++++++
13 files changed, 209 insertions(+), 194 deletions(-)
rename llvm/test/tools/llvm-cov/{ => Inputs}/branch-logical-mixed.cpp (80%)
rename llvm/test/tools/llvm-cov/{ => Inputs}/branch-macros.cpp (70%)
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
create mode 100644 llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
create mode 100644 llvm/test/tools/llvm-cov/branch-logical-mixed.test
create mode 100644 llvm/test/tools/llvm-cov/branch-macros.test
rename llvm/test/tools/llvm-cov/{branch-showBranchPercentage.c => branch-showBranchPercentage.test} (51%)
rename llvm/test/tools/llvm-cov/{branch-templates.cpp => branch-templates.test} (54%)
delete mode 100644 llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
create mode 100644 llvm/test/tools/llvm-cov/showLineExecutionCounts.test
diff --git a/llvm/test/tools/llvm-cov/branch-logical-mixed.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
similarity index 80%
rename from llvm/test/tools/llvm-cov/branch-logical-mixed.cpp
rename to llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
index f5f78711244677..0a7d8d89671158 100644
--- a/llvm/test/tools/llvm-cov/branch-logical-mixed.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
@@ -1,6 +1,6 @@
-// RUN: llvm-profdata merge %S/Inputs/branch-logical-mixed.proftext -o %t.profdata
-// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
-// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
+
+
+
#include <stdio.h>
#include <stdlib.h>
@@ -81,10 +81,3 @@ int main(int argc, char *argv[])
__llvm_profile_write_file();
return 0;
}
-
-// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
-// REPORT-NEXT: ---
-// REPORT-NEXT: _Z4funcii 77 9 88.31% 68 3 95.59% 80 32 60.00%
-// REPORT-NEXT: main 1 0 100.00% 5 0 100.00% 0 0 0.00%
-// REPORT-NEXT: ---
-// REPORT-NEXT: TOTAL 78 9 88.46% 73 3 95.89% 80 32 60.00%
diff --git a/llvm/test/tools/llvm-cov/branch-macros.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
similarity index 70%
rename from llvm/test/tools/llvm-cov/branch-macros.cpp
rename to llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
index 73042ac397d406..712b2790f774aa 100644
--- a/llvm/test/tools/llvm-cov/branch-macros.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
@@ -1,6 +1,6 @@
-// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
-// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
-// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
+
+
+
#define COND1 (a == b)
#define COND2 (a != b)
@@ -50,11 +50,3 @@ int main(int argc, char *argv[])
__llvm_profile_write_file();
return 0;
}
-
-// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
-// REPORT-NEXT: ---
-// REPORT-NEXT: _Z4funcii 28 4 85.71% 18 0 100.00% 30 14 53.33%
-// REPORT-NEXT: _Z5func2ii 13 1 92.31% 8 0 100.00% 10 2 80.00%
-// REPORT-NEXT: main 1 0 100.00% 6 0 100.00% 0 0 0.00%
-// REPORT-NEXT: ---
-// REPORT-NEXT: TOTAL 42 5 88.10% 32 0 100.00% 40 16 60.00%
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c
new file mode 100644
index 00000000000000..c41739ff0b22f1
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c
@@ -0,0 +1,58 @@
+
+
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern void __llvm_profile_write_file(void);
+
+int main(int argc, char *argv[])
+{
+ int i = 0;
+ if (argc < 3) // CHECK: Branch ([[@LINE]]:7): [True: 16.67%, False: 83.33%]
+ {
+ __llvm_profile_write_file();
+ return 0;
+ }
+
+ int a = atoi(argv[1]);
+ int b = atoi(argv[2]);
+
+ // CHECK: Branch ([[@LINE+4]]:8): [True: 20.00%, False: 80.00%]
+ // CHECK: Branch ([[@LINE+3]]:18): [True: 0.00%, False: 100.00%]
+ // CHECK: Branch ([[@LINE+2]]:29): [True: 0.00%, False: 100.00%]
+ // CHECK: Branch ([[@LINE+1]]:40): [True: 40.00%, False: 60.00%]
+ if ((a == 0 && b == 2) || b == 34 || a == b)
+ printf("case1\n");
+
+ b = (a != 0 || a == 2) ? b : b+2; // CHECK: Branch ([[@LINE]]:8): [True: 80.00%, False: 20.00%]
+ // CHECK: Branch ([[@LINE-1]]:18): [True: 0.00%, False: 100.00%]
+ b = (a != 0 && a == 1); // CHECK: Branch ([[@LINE]]:8): [True: 80.00%, False: 20.00%]
+ // CHECK: Branch ([[@LINE-1]]:18): [True: 25.00%, False: 75.00%]
+ for (i = 0; i < b; i++) { a = 2 + b + b; }
+ // CHECK: Branch ([[@LINE-1]]:15): [True: 16.67%, False: 83.33%]
+
+ b = a;
+
+ switch (a)
+ {
+ case 0: // CHECK: Branch ([[@LINE]]:5): [True: 20.00%, False: 80.00%]
+ printf("case0\n");
+ case 2: // CHECK: Branch ([[@LINE]]:5): [True: 20.00%, False: 80.00%]
+ printf("case2\n");
+ case 3: // CHECK: Branch ([[@LINE]]:5): [True: 0.00%, False: 100.00%]
+ printf("case3\n");
+ default: break; // CHECK: Branch ([[@LINE]]:5): [True: 60.00%, False: 40.00%]
+ }
+
+ i = 0;
+ do {
+ printf("loop\n");
+ } while (i++ < 10); // CHECK: Branch ([[@LINE]]:12): [True: 90.91%, False: 9.09%]
+
+ __llvm_profile_write_file();
+
+ return b;
+}
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
new file mode 100644
index 00000000000000..0795a5346380de
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
@@ -0,0 +1,38 @@
+
+
+
+
+
+#include <stdio.h>
+template<typename T>
+void unused(T x) {
+ return;
+}
+
+template<typename T>
+int func(T x) {
+ if(x) // CHECK: | Branch ([[@LINE]]:6): [True: 0, False: 1]
+ return 0; // CHECK: | Branch ([[@LINE-1]]:6): [True: 1, False: 0]
+ else // CHECK: | Branch ([[@LINE-2]]:6): [True: 0, False: 1]
+ return 1;
+ int j = 1;
+}
+
+ // CHECK-LABEL: _Z4funcIiEiT_:
+ // CHECK: | | Branch ([[@LINE-8]]:6): [True: 0, False: 1]
+ // CHECK-LABEL: _Z4funcIbEiT_:
+ // CHECK: | | Branch ([[@LINE-10]]:6): [True: 1, False: 0]
+ // CHECK-LABEL: _Z4funcIfEiT_:
+ // CHECK: | | Branch ([[@LINE-12]]:6): [True: 0, False: 1]
+
+extern "C" { extern void __llvm_profile_write_file(void); }
+int main() {
+ if (func<int>(0)) // CHECK: | Branch ([[@LINE]]:7): [True: 1, False: 0]
+ printf("case1\n");
+ if (func<bool>(true)) // CHECK: | Branch ([[@LINE]]:7): [True: 0, False: 1]
+ printf("case2\n");
+ if (func<float>(0.0)) // CHECK: | Branch ([[@LINE]]:7): [True: 1, False: 0]
+ printf("case3\n");
+ __llvm_profile_write_file();
+ return 0;
+}
diff --git a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
new file mode 100644
index 00000000000000..c7e8c8fb0c75e4
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
@@ -0,0 +1,29 @@
+// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE+2]]' href='#L[[@LINE+2]]'><pre>[[@LINE+2]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
+// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE+1]]' href='#L[[@LINE+1]]'><pre>[[@LINE+1]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
+// before any coverage // WHOLE-FILE: [[@LINE]]| |// before
+ // FILTER-NOT: [[@LINE-1]]| |// before
+// HTML: <td class='line-number'><a name='L[[@LINE+1]]' href='#L[[@LINE+1]]'><pre>[[@LINE+1]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
+int main() { // TEXT: [[@LINE]]| 161|int main(
+ int x = 0; // TEXT: [[@LINE]]| 161| int x
+ // TEXT: [[@LINE]]| 161|
+ if (x) { // TEXT: [[@LINE]]| 161| if (x)
+ x = 0; // TEXT: [[@LINE]]| 0| x = 0
+ } else { // TEXT: [[@LINE]]| 161| } else
+ x = 1; // TEXT: [[@LINE]]| 161| x = 1
+ } // TEXT: [[@LINE]]| 161| }
+ // TEXT: [[@LINE]]| 161|
+ for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| 16.2k| for (
+ x = 1; // TEXT: [[@LINE]]| 16.1k| x = 1
+ } // TEXT: [[@LINE]]| 16.1k| }
+ // TEXT: [[@LINE]]| 161|
+ x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| 161| x =
+ x = x > 10 ? // TEXT: [[@LINE]]| 161| x =
+ x - 1: // TEXT: [[@LINE]]| 0| x
+ x + 1; // TEXT: [[@LINE]]| 161| x
+ // TEXT: [[@LINE]]| 161|
+ return 0; // TEXT: [[@LINE]]| 161| return
+} // TEXT: [[@LINE]]| 161|}
+// after coverage // WHOLE-FILE: [[@LINE]]| |// after
+ // FILTER-NOT: [[@LINE-1]]| |// after
+// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-2]]' href='#L[[@LINE-2]]'><pre>[[@LINE-2]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
+// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-3]]' href='#L[[@LINE-3]]'><pre>[[@LINE-3]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
diff --git a/llvm/test/tools/llvm-cov/branch-c-general.test b/llvm/test/tools/llvm-cov/branch-c-general.test
index 2fa99dfe61532e..865a2662460e83 100644
--- a/llvm/test/tools/llvm-cov/branch-c-general.test
+++ b/llvm/test/tools/llvm-cov/branch-c-general.test
@@ -114,7 +114,7 @@
-// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
+// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
// REPORT-NEXT: simple_loops 8 0 100.00% 9 0 100.00% 6 0 100.00%
// REPORT-NEXT: conditionals 24 0 100.00% 15 0 100.00% 16 2 87.50%
diff --git a/llvm/test/tools/llvm-cov/branch-logical-mixed.test b/llvm/test/tools/llvm-cov/branch-logical-mixed.test
new file mode 100644
index 00000000000000..a07d2357f2c34d
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-logical-mixed.test
@@ -0,0 +1,11 @@
+// RUN: llvm-profdata merge %S/Inputs/branch-logical-mixed.proftext -o %t.profdata
+// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-logical-mixed.cpp
+| FileCheck %s -check-prefix=REPORT
+
+// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
+// REPORT-NEXT: ---
+// REPORT-NEXT: _Z4funcii 77 15 80.52% 60 2 96.67% 80 30 62.50%
+// REPORT-NEXT: main 1 0 100.00% 5 0 100.00% 0 0 0.00%
+// REPORT-NEXT: ---
+// REPORT-NEXT: TOTAL 78 15 80.77% 65 2 96.92% 80 30 62.50%
diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test
new file mode 100644
index 00000000000000..fbe7694b4f4e05
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-macros.test
@@ -0,0 +1,11 @@
+// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
+// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s -check-prefix=REPORT
+
+// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
+// REPORT-NEXT: ---
+// REPORT-NEXT: _Z4funcii 28 4 85.71% 18 0 100.00% 30 14 53.33%
+// REPORT-NEXT: _Z5func2ii 13 1 92.31% 8 0 100.00% 10 2 80.00%
+// REPORT-NEXT: main 1 0 100.00% 6 0 100.00% 0 0 0.00%
+// REPORT-NEXT: ---
+// REPORT-NEXT: TOTAL 42 5 88.10% 32 0 100.00% 40 16 60.00%
diff --git a/llvm/test/tools/llvm-cov/branch-noShowBranch.test b/llvm/test/tools/llvm-cov/branch-noShowBranch.test
index 25a98d59481aa1..cabeeb01bfe3e7 100644
--- a/llvm/test/tools/llvm-cov/branch-noShowBranch.test
+++ b/llvm/test/tools/llvm-cov/branch-noShowBranch.test
@@ -5,9 +5,9 @@
// CHECK-NOT: | Branch
-// REPORT: Name Regions Miss Cover Lines Miss Cover
+// REPORT: Name Regions Miss Cover Lines Miss Cover
// REPORT-NOT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
-// REPORT: ---
+// REPORT: ---
// REPORT-NOT: simple_loops 8 0 100.00% 9 0 100.00% 6 0 100.00%
// REPORT-NOT: conditionals 24 0 100.00% 15 0 100.00% 16 2 87.50%
// REPORT-NOT: early_exits 20 4 80.00% 25 2 92.00% 16 6 62.50%
@@ -20,6 +20,6 @@
// REPORT-NOT: do_fallthrough 9 0 100.00% 12 0 100.00% 6 0 100.00%
// REPORT-NOT: main 1 0 100.00% 16 0 100.00% 0 0 0.00%
// REPORT-NOT: c-general.c:static_func 4 0 100.00% 4 0 100.00% 2 0 100.00%
-// REPORT: TOTAL 197 24 87.82% 234 8 96.58%
-// REPORT-NOT: TOTAL 197 24 87.82% 234 13 94.44% 174 38 78.16%
+// REPORT: TOTAL 197 24 87.82% 234 8 96.58%
+// REPORT-NOT: TOTAL 197 24 87.82% 234 13 94.44% 174 38 78.16%
diff --git a/llvm/test/tools/llvm-cov/branch-showBranchPercentage.c b/llvm/test/tools/llvm-cov/branch-showBranchPercentage.test
similarity index 51%
rename from llvm/test/tools/llvm-cov/branch-showBranchPercentage.c
rename to llvm/test/tools/llvm-cov/branch-showBranchPercentage.test
index a649462116a08e..f6f9e3df742b4a 100644
--- a/llvm/test/tools/llvm-cov/branch-showBranchPercentage.c
+++ b/llvm/test/tools/llvm-cov/branch-showBranchPercentage.test
@@ -1,63 +1,10 @@
// Test visualization of branch taken percentages
// RUN: llvm-profdata merge %S/Inputs/branch-showBranchPercentage.proftext -o %t.profdata
-// RUN: llvm-cov show --show-branches=percent %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
+// RUN: llvm-cov show --show-branches=percent %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-showBranchPercentage.c
-#include <stdio.h>
-#include <stdlib.h>
-
-extern void __llvm_profile_write_file(void);
-
-int main(int argc, char *argv[])
-{
- int i = 0;
- if (argc < 3) // CHECK: Branch ([[@LINE]]:7): [True: 16.67%, False: 83.33%]
- {
- __llvm_profile_write_file();
- return 0;
- }
-
- int a = atoi(argv[1]);
- int b = atoi(argv[2]);
-
- // CHECK: Branch ([[@LINE+4]]:8): [True: 20.00%, False: 80.00%]
- // CHECK: Branch ([[@LINE+3]]:18): [True: 0.00%, False: 100.00%]
- // CHECK: Branch ([[@LINE+2]]:29): [True: 0.00%, False: 100.00%]
- // CHECK: Branch ([[@LINE+1]]:40): [True: 40.00%, False: 60.00%]
- if ((a == 0 && b == 2) || b == 34 || a == b)
- printf("case1\n");
-
- b = (a != 0 || a == 2) ? b : b+2; // CHECK: Branch ([[@LINE]]:8): [True: 80.00%, False: 20.00%]
- // CHECK: Branch ([[@LINE-1]]:18): [True: 0.00%, False: 100.00%]
- b = (a != 0 && a == 1); // CHECK: Branch ([[@LINE]]:8): [True: 80.00%, False: 20.00%]
- // CHECK: Branch ([[@LINE-1]]:18): [True: 25.00%, False: 75.00%]
- for (i = 0; i < b; i++) { a = 2 + b + b; }
- // CHECK: Branch ([[@LINE-1]]:15): [True: 16.67%, False: 83.33%]
-
- b = a;
-
- switch (a)
- {
- case 0: // CHECK: Branch ([[@LINE]]:5): [True: 20.00%, False: 80.00%]
- printf("case0\n");
- case 2: // CHECK: Branch ([[@LINE]]:5): [True: 20.00%, False: 80.00%]
- printf("case2\n");
- case 3: // CHECK: Branch ([[@LINE]]:5): [True: 0.00%, False: 100.00%]
- printf("case3\n");
- default: break; // CHECK: Branch ([[@LINE]]:5): [True: 60.00%, False: 40.00%]
- }
-
- i = 0;
- do {
- printf("loop\n");
- } while (i++ < 10); // CHECK: Branch ([[@LINE]]:12): [True: 90.91%, False: 9.09%]
-
- __llvm_profile_write_file();
-
- return b;
-}
// RUN: llvm-profdata merge %S/Inputs/branch-showBranchPercentage.proftext -o %t.profdata
-// RUN: llvm-cov show --show-branches=percent %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s -format html -o %t.html.dir
+// RUN: llvm-cov show --show-branches=percent %S/Inputs/branch-showBranchPercentage.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -format html -o %t.html.dir
// Test html output.
// RUN: FileCheck -check-prefix=HTML -input-file=%t.html.dir/coverage/tmp/branch-showBranchPercentage.c.html %s
diff --git a/llvm/test/tools/llvm-cov/branch-templates.cpp b/llvm/test/tools/llvm-cov/branch-templates.test
similarity index 54%
rename from llvm/test/tools/llvm-cov/branch-templates.cpp
rename to llvm/test/tools/llvm-cov/branch-templates.test
index 4797428f8835ae..74aef16050228a 100644
--- a/llvm/test/tools/llvm-cov/branch-templates.cpp
+++ b/llvm/test/tools/llvm-cov/branch-templates.test
@@ -1,43 +1,9 @@
// RUN: llvm-profdata merge %S/Inputs/branch-templates.proftext -o %t.profdata
-// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
-// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
-// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORTFILE
+// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-templates.cpp
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-templates.cpp | FileCheck %s -check-prefix=REPORT
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %s -check-prefix=REPORTFILE
-#include <stdio.h>
-template<typename T>
-void unused(T x) {
- return;
-}
-
-template<typename T>
-int func(T x) {
- if(x) // CHECK: | Branch ([[@LINE]]:6): [True: 0, False: 1]
- return 0; // CHECK: | Branch ([[@LINE-1]]:6): [True: 1, False: 0]
- else // CHECK: | Branch ([[@LINE-2]]:6): [True: 0, False: 1]
- return 1;
- int j = 1;
-}
-
- // CHECK-LABEL: _Z4funcIiEiT_:
- // CHECK: | | Branch ([[@LINE-8]]:6): [True: 0, False: 1]
- // CHECK-LABEL: _Z4funcIbEiT_:
- // CHECK: | | Branch ([[@LINE-10]]:6): [True: 1, False: 0]
- // CHECK-LABEL: _Z4funcIfEiT_:
- // CHECK: | | Branch ([[@LINE-12]]:6): [True: 0, False: 1]
-
-extern "C" { extern void __llvm_profile_write_file(void); }
-int main() {
- if (func<int>(0)) // CHECK: | Branch ([[@LINE]]:7): [True: 1, False: 0]
- printf("case1\n");
- if (func<bool>(true)) // CHECK: | Branch ([[@LINE]]:7): [True: 0, False: 1]
- printf("case2\n");
- if (func<float>(0.0)) // CHECK: | Branch ([[@LINE]]:7): [True: 1, False: 0]
- printf("case3\n");
- __llvm_profile_write_file();
- return 0;
-}
-
-// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
+// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
// REPORT-NEXT: main 7 1 85.71% 10 1 90.00% 6 3 50.00%
// REPORT-NEXT: _Z4funcIiEiT_ 5 2 60.00% 7 3 57.14% 2 1 50.00%
@@ -54,8 +20,8 @@ int main() {
// respectively). This is returned by: FunctionCoverageSummary::get(const
// InstantiationGroup &Group, ...)
-// REPORTFILE: Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover
+// REPORTFILE: Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover
// REPORTFILE-NEXT: ---
// REPORTFILE-NEXT: branch-templates.cpp 12 3 75.00% 2 0 100.00% 17 4 76.47% 8 4 50.00%
// REPORTFILE-NEXT: ---
-// REPORTFILE-NEXT: TOTAL 12 3 75.00% 2 0 100.00% 17 4 76.47% 8 4 50.00%
+// REPORTFILE-NEXT: TOTAL 12 3 75.00% 2 0 100.00% 17 4 76.47% 8 4 50.00%
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
deleted file mode 100644
index f72a9978b8a734..00000000000000
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-// Basic handling of line counts.
-// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
-
-// before any coverage // WHOLE-FILE: [[@LINE]]| |// before
- // FILTER-NOT: [[@LINE-1]]| |// before
-int main() { // TEXT: [[@LINE]]| 161|int main(
- int x = 0; // TEXT: [[@LINE]]| 161| int x
- // TEXT: [[@LINE]]| 161|
- if (x) { // TEXT: [[@LINE]]| 161| if (x)
- x = 0; // TEXT: [[@LINE]]| 0| x = 0
- } else { // TEXT: [[@LINE]]| 161| } else
- x = 1; // TEXT: [[@LINE]]| 161| x = 1
- } // TEXT: [[@LINE]]| 161| }
- // TEXT: [[@LINE]]| 161|
- for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| 16.2k| for (
- x = 1; // TEXT: [[@LINE]]| 16.1k| x = 1
- } // TEXT: [[@LINE]]| 16.1k| }
- // TEXT: [[@LINE]]| 161|
- x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| 161| x =
- x = x > 10 ? // TEXT: [[@LINE]]| 161| x =
- x - 1: // TEXT: [[@LINE]]| 0| x
- x + 1; // TEXT: [[@LINE]]| 161| x
- // TEXT: [[@LINE]]| 161|
- return 0; // TEXT: [[@LINE]]| 161| return
-} // TEXT: [[@LINE]]| 161|}
-// after coverage // WHOLE-FILE: [[@LINE]]| |// after
- // FILTER-NOT: [[@LINE-1]]| |// after
-
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck -check-prefixes=TEXT,WHOLE-FILE %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s | FileCheck -check-prefixes=TEXT,FILTER %s
-
-// Test -output-dir.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
-// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
-// RUN: FileCheck -check-prefixes=TEXT,FILTER -input-file %t.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
-//
-// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
-// RUN: not grep '"name":"main"' %t.export-summary.json
-//
-// Test html output.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
-// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.html.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
-// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.html.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
-//
-// HTML-WHOLE-FILE: <td class='line-number'><a name='L4' href='#L4'><pre>4</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
-// HTML-FILTER-NOT: <td class='line-number'><a name='L4' href='#L4'><pre>4</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
-// HTML: <td class='line-number'><a name='L6' href='#L6'><pre>6</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
-// HTML-WHOLE-FILE: <td class='line-number'><a name='L26' href='#L26'><pre>26</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
-// HTML-FILTER-NOT: <td class='line-number'><a name='L26' href='#L26'><pre>26</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
-//
-// Test index creation.
-// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/index.txt %s
-// TEXT-INDEX: Filename
-// TEXT-INDEX-NEXT: ---
-// TEXT-INDEX-NEXT: {{.*}}showLineExecutionCounts.cpp
-//
-// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
-// HTML-INDEX-LABEL: <table>
-// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
-// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
-// HTML-INDEX: <a href='coverage{{.*}}showLineExecutionCounts.cpp.html'{{.*}}showLineExecutionCounts.cpp</a>
-// HTML-INDEX: <td class='column-entry-green'>
-// HTML-INDEX: 100.00% (1/1)
-// HTML-INDEX: <td class='column-entry-yellow'>
-// HTML-INDEX: 90.00% (18/20)
-// HTML-INDEX: <td class='column-entry-red'>
-// HTML-INDEX: 72.73% (8/11)
-// HTML-INDEX: <tr class='light-row-bold'>
-// HTML-INDEX: Totals
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
new file mode 100644
index 00000000000000..997b16a0b8e94f
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
@@ -0,0 +1,43 @@
+// Basic handling of line counts.
+// RUN: rm -rf %t*.dir
+// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
+
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER %S/Inputs/showLineExecutionCounts.cpp
+
+// Test -output-dir.
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
+// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=TEXT,FILTER -input-file %t.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+//
+// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
+// RUN: not grep '"name":"main"' %t.export-summary.json
+//
+// Test html output.
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
+// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.html.dir/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.html.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
+//
+// Test index creation.
+// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/index.txt %s
+// TEXT-INDEX: Filename
+// TEXT-INDEX-NEXT: ---
+// TEXT-INDEX-NEXT: {{.*}}showLineExecutionCounts.cpp
+//
+// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
+// HTML-INDEX-LABEL: <table>
+// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
+// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
+// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
+// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
+// HTML-INDEX: <a href='coverage{{.*}}showLineExecutionCounts.cpp.html'{{.*}}showLineExecutionCounts.cpp</a>
+// HTML-INDEX: <td class='column-entry-green'>
+// HTML-INDEX: 100.00% (1/1)
+// HTML-INDEX: <td class='column-entry-yellow'>
+// HTML-INDEX: 90.00% (18/20)
+// HTML-INDEX: <td class='column-entry-red'>
+// HTML-INDEX: 72.73% (8/11)
+// HTML-INDEX: <tr class='light-row-bold'>
+// HTML-INDEX: Totals
>From c50c492964a9239fc9e07ffe4a56bdbd4bf17aa8 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 20 Nov 2024 23:34:04 +0900
Subject: [PATCH 06/30] Introduce test/llvm-cov/Inputs/yaml.makefile for
convenience.
---
llvm/test/tools/llvm-cov/Inputs/yaml.makefile | 96 +++++++++++++++++++
1 file changed, 96 insertions(+)
create mode 100644 llvm/test/tools/llvm-cov/Inputs/yaml.makefile
diff --git a/llvm/test/tools/llvm-cov/Inputs/yaml.makefile b/llvm/test/tools/llvm-cov/Inputs/yaml.makefile
new file mode 100644
index 00000000000000..2a256f0cffc0b9
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/yaml.makefile
@@ -0,0 +1,96 @@
+# This is for developers' convenience and not expected to be in build steps.
+#
+# Usage:
+# cd /path/to/llvm-project/llvm/test/tools/llvm-cov/Inputs
+# PATH=/path/to/build/bin:$PATH make -f yaml.makefile
+
+CFLAGS_COVMAP = -fcoverage-compilation-dir=. \
+ -mllvm -runtime-counter-relocation=true \
+ -mllvm -conditional-counter-update=true \
+ -mllvm -enable-name-compression=false \
+ -fprofile-instr-generate -fcoverage-mapping \
+ $(if $(filter mcdc-%, $*), $(CFLAGS_MCDC))
+
+CFLAGS_MCDC = -fcoverage-mcdc
+
+%.o: %.cpp
+ clang++ $< -c -o $@ $(CFLAGS_COVMAP)
+
+%.o: %.c
+ clang $< -c -o $@ $(CFLAGS_COVMAP)
+
+%-single.o: %.cpp
+ clang++ $< -c -o $@ \
+ -mllvm -enable-single-byte-coverage=true \
+ $(CFLAGS_COVMAP)
+
+%-single.o: %.c
+ clang $< -c -o $@ \
+ -mllvm -enable-single-byte-coverage=true \
+ $(CFLAGS_COVMAP)
+
+%.covmap.o: %.o
+ llvm-objcopy \
+ --only-section=__llvm_covfun \
+ --only-section=__llvm_covmap \
+ --only-section=__llvm_prf_names \
+ --strip-unneeded \
+ $< $@
+
+%.yaml: %.covmap.o
+ obj2yaml $< > $@
+
+%.exe: %.o
+ clang++ -fprofile-instr-generate $^ -o $@
+
+ARGS_branch-logical-mixed := \
+ 0 0; \
+ 0 1; \
+ 1 0; \
+ 1 1
+
+ARGS_branch-macros := \
+ 0 1; \
+ 1 0; \
+ 1 1
+
+ARGS_branch-showBranchPercentage := \
+ 0 1; \
+ 1 1; \
+ 2 2; \
+ 4 0; \
+ 5 0; \
+ 1
+
+ARGS_showLineExecutionCounts := $(patsubst %,%;,$(shell seq 161))
+
+ARGS_mcdc-const-folding := \
+ 0 1; \
+ 1 0; \
+ 1 1; \
+ 1 1
+
+%.profdata: %.exe
+ -find -name '$*.*.profraw' | xargs rm -fv
+ @if [ "$(ARGS_$(patsubst %-single,%,$*))" = "" ]; then \
+ echo "Executing: $<"; \
+ LLVM_PROFILE_FILE=$*.%p%c.profraw ./$<; \
+ else \
+ LLVM_PROFILE_FILE=$*.%p%c.profraw; \
+ export LLVM_PROFILE_FILE; \
+ for xcmd in $(shell echo "$(ARGS_$(patsubst %-single,%,$*))" | tr ';[:blank:]' ' %'); do \
+ cmd=$$(echo "$$xcmd" | tr '%' ' '); \
+ echo "Executing series: $< $$cmd"; \
+ eval "./$< $$cmd"; \
+ done; \
+ fi
+ find -name '$*.*.profraw' | xargs llvm-profdata merge --sparse -o $@
+
+%.proftext: %.profdata
+ llvm-profdata merge --text -o $@ $<
+
+.PHONY: all
+all: \
+ $(patsubst %.yaml,%.proftext, $(wildcard *.yaml)) \
+ $(wildcard *.yaml)
+ -find -name '*.profraw' | xargs rm -f
>From d7c5b4404c48a6b02ddffc331849335580e16b9b Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 20 Nov 2024 23:34:16 +0900
Subject: [PATCH 07/30] Add tests for SingleByteCoverage
---
.../Inputs/branch-c-general-single.proftext | 297 ++++++++++++++++++
.../Inputs/branch-c-general-single.yaml | 177 +++++++++++
.../tools/llvm-cov/Inputs/branch-c-general.c | 202 ++++++------
.../branch-logical-mixed-single.proftext | 84 +++++
.../Inputs/branch-logical-mixed-single.yaml | 57 ++++
.../llvm-cov/Inputs/branch-logical-mixed.cpp | 86 ++---
.../Inputs/branch-macros-single.proftext | 53 ++++
.../llvm-cov/Inputs/branch-macros-single.yaml | 69 ++++
.../tools/llvm-cov/Inputs/branch-macros.cpp | 46 +--
.../Inputs/branch-showBranchPercentage.c | 6 +-
.../Inputs/branch-templates-single.proftext | 49 +++
.../Inputs/branch-templates-single.yaml | 81 +++++
.../llvm-cov/Inputs/branch-templates.cpp | 22 +-
.../showLineExecutionCounts-single.proftext | 23 ++
.../showLineExecutionCounts-single.yaml | 45 +++
.../Inputs/showLineExecutionCounts.cpp | 40 +--
.../test/tools/llvm-cov/branch-c-general.test | 4 +
.../tools/llvm-cov/branch-logical-mixed.test | 8 +-
llvm/test/tools/llvm-cov/branch-macros.test | 6 +-
.../test/tools/llvm-cov/branch-templates.test | 4 +
.../llvm-cov/showLineExecutionCounts.test | 7 +
21 files changed, 1163 insertions(+), 203 deletions(-)
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.proftext
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.yaml
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.proftext
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.yaml
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-macros-single.proftext
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-macros-single.yaml
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-templates-single.proftext
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-templates-single.yaml
create mode 100644 llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.proftext
create mode 100644 llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.yaml
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.proftext
new file mode 100644
index 00000000000000..ea8c6f9bc634ed
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.proftext
@@ -0,0 +1,297 @@
+# Instrument block coverage
+:single_byte_coverage
+big_switch
+# Func Hash:
+13144136522122330070
+# Num Counters:
+27
+# Counter Values:
+1
+1
+1
+1
+1
+1
+1
+0
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+boolean_operators
+# Func Hash:
+1245693242827665
+# Num Counters:
+17
+# Counter Values:
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+boolop_loops
+# Func Hash:
+12402604614320574815
+# Num Counters:
+23
+# Counter Values:
+1
+0
+1
+1
+1
+1
+0
+1
+1
+1
+1
+0
+1
+1
+1
+1
+1
+0
+1
+1
+1
+1
+1
+
+branch-c-general.c:static_func
+# Func Hash:
+18129
+# Num Counters:
+5
+# Counter Values:
+1
+1
+1
+1
+1
+
+conditional_operator
+# Func Hash:
+54992
+# Num Counters:
+5
+# Counter Values:
+1
+1
+0
+1
+1
+
+conditionals
+# Func Hash:
+4904767535850050386
+# Num Counters:
+25
+# Counter Values:
+1
+1
+1
+1
+1
+1
+0
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+do_fallthrough
+# Func Hash:
+8714614136504380050
+# Num Counters:
+10
+# Counter Values:
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+early_exits
+# Func Hash:
+2880354649761471549
+# Num Counters:
+20
+# Counter Values:
+1
+0
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+0
+1
+1
+1
+0
+0
+
+jumps
+# Func Hash:
+15051420506203462683
+# Num Counters:
+38
+# Counter Values:
+1
+1
+0
+1
+0
+0
+0
+1
+0
+1
+1
+0
+1
+1
+0
+1
+1
+1
+1
+1
+1
+1
+0
+1
+1
+0
+1
+1
+1
+1
+1
+1
+1
+0
+0
+1
+1
+1
+
+main
+# Func Hash:
+24
+# Num Counters:
+1
+# Counter Values:
+1
+
+simple_loops
+# Func Hash:
+1245818015463121
+# Num Counters:
+11
+# Counter Values:
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+
+switches
+# Func Hash:
+43242458792028222
+# Num Counters:
+29
+# Counter Values:
+1
+1
+1
+1
+1
+1
+0
+1
+1
+0
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+0
+1
+1
+1
+1
+1
+1
+0
+0
+
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.yaml b/llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.yaml
new file mode 100644
index 00000000000000..9d23dcb67ad2ac
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-c-general-single.yaml
@@ -0,0 +1,177 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_X86_64
+ SectionHeaderStringTable: .strtab
+Sections:
+ - Name: __llvm_covfun
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: D7878914FBE99B074D000000D136449C106D04004C551E9517F40F4F0101000D010715080205020F0016090018001B0D001C009D808080080D001D0104110203040215000A000F19001001858080800819010500081D01030202210006000825001000181001010001
+ - Name: '__llvm_covfun (1)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 83AD05A5F1438E68EA00000052D33558163C11444C551E9517F40F4F010100260111150E02050113001A09001C001F0D002000A1808080080D00210B040D0109000E15000F009080808008150010020615010B000C21000D008E8080800821000E0010310106008C8080800831000C04063100100015290016009780808008290017020629010B000C35000D008E8080800835000E00102D0106008C808080082D000C02062D010B000C3D000D008E808080083D000E0010100201005B1D010502041D0009000A1D0009000F4D000E000F45001000918080800845001100134901050104490009000A490009000F5D000E000F55001000918080800855001100131002010001
+ - Name: '__llvm_covfun (2)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 0449C70428C57369F80000003D5C2D0E4B13F9274C551E9517F40F4F01010028012114180210020100010101070008050009008A8080800805000A000C100101000109010313020D000A00111100120093808080081100130604110209000F190010018780808008190107000C1D000D0185808080081D010502041D0009000E21000F018780808008210107000F15010402838080800810010100011501030B021500070008290009008A8080800829000A000C10010100012D010309023100060504310109000F3D00100187808080083D0107000D41000E028780808008410207000A35010C0013390015028380808008100101000139010302023900070008490009008A8080800849000A000C1001010001
+ - Name: '__llvm_covfun (3)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 55947829059F255EB80100001B9C495D3463E1D04C551E9517F40F4F01010046013B0E2F02100201000105010F001409001600190D001A009B808080080D001B040400011402858080800810010100230001050104000009000A15000B008C8080800815000C000E11010402818080800810010100011D010126021D01070008210009008A8080800821000A000C1001010001250103000D25000E0283808080081001010001000103210229000A000B2D000C008D808080082D000D03043501030204350109000A39000B008C8080800839000C000E1002010001310103000D31000E0181808080084101011B024501011A024901011902490207000C4D000D0185808080084D0105000F5100100283808080081001010001510103140255000A000F5900100091808080085900110A04610103090400011006918080800869010501110001120185808080086D0105011200011301858080800871010501115D030402838080800810010100015D0103080275000F0015790017001A7D001B009C808080087D001C0604000115028580808008100101003F0001050304000009000A8501000B008C808080088501000C000E8D01010302048D010109000A9101000B008C808080089101000C000E1002010001
+ - Name: '__llvm_covfun (4)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 7129CA3C268292BF4D0100003E688383C9A099004C551E9517F40F4F01010035016C112502100201011C000217028A80808008090103010A05020402838080800810010100620501031C020D003F0046110048004B15004C00CD8080800815004D1704000119148F80808008210105130F21010B000C25000D008E8080800825000E001010010100152D0105100F2D010B000C31000D008E8080800831000E0010350107000C35000D0185808080083901050D0F39010B000C3D000D008E808080083D000E0010410107000F4100100185808080084501050A0F45010B000C49000D008E8080800849000E00104D0107080F000012039180808008550107021155010D000E59000F00908080800859001000125D010900115101080285808080081001010001610105020F61010B0017650018018980808008650109000F1902040383808080081001010121190203020219000700116D00120093808080086D001300151001010001
+ - Name: '__llvm_covfun (5)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 3F4D1C6E6087417B32010000D6FF56B8865A69B64C551E9517F40F4F01010031019301131F02050113001909001B001E0D001F00A0808080080D00201C04000115198C80808008190105180C19010B000C1D000D008E808080081D000E00101001010015250105150C25010B000C29000D008E8080800829000E00102D0107000C2D000D018580808008310105120C31010B000C35000D008E8080800835000E0010390107000C39000D03858080800810010101013D02050D0C3D010B000C41000D008E8080800841000E0010450107000C45000D0185808080084901050A0C49010B000C4D000D008E808080084D000E0010510107000C51000D0385808080081001010101550205050C55010B000C59000D008E8080800859000E00105D0107000C5D000D018580808008610105020C61010B000C65000D008E8080800865000E0010690107000C1003010001
+ - Name: '__llvm_covfun (6)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 59A48AA8899AA3587200000091E33C8FF36C04004C551E9517F40F4F0101001501B4011A0C02050213001A09001C001F0D002000A1808080080D002108040D0109000E1500120013100101005D0D0109000E1D00120013100101005D0D0109000E0D000900172D0012001725001B001C10010100630D0109000E0D000900173D0012001735001B001C1002010063
+ - Name: '__llvm_covfun (7)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: F5953D044B505D139E0000005FD132562FE71EAC4C551E9517F40F4F0101001D01C201150D02100201000111010A000B11000A001511000F0015090016018580808008090105000810010100010D0103070225000A001125000A001C250015001C1D001D0185808080081D01050008100101000121010304023D001100123D0011001C3D0016001C31001E002135002200231001010061390103020255000A001155000A001C550015001C49001E00214D002200231001010061
+ - Name: '__llvm_covfun (8)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 20E5C369BDF15C7940000000D0D60000000000004C551E9517F40F4F0101000B01D1011D0702100201000101010B001109001300948080800809001400150D001800191001010001050103020205000B000C01001000111001010001
+ - Name: '__llvm_covfun (9)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 7DE8E7C47096EB425200000092EAF0986287F0784C551E9517F40F4F0101000D01DA01170B02050113001909001B001E0D001F00A0808080080D002009041502080606100101024D15030B00102100110092808080082100120017250018018780808008250107010619010E0013
+ - Name: '__llvm_covfun (10)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: FAD58DE7366495DB0A00000018000000000000004C551E9517F40F4F0101000101F501280F02
+ - Name: '__llvm_covfun (11)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 4CB4F49D6737EBF922000000D1460000000000004C551E9517F40F4F0101000501E7011B0302050113001909001B001E0D001F00A0808080080D00200104
+ - Name: __llvm_covmap
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 0000000017000000000000000600000002140000126272616E63682D632D67656E6572616C2E6300
+ - Name: __llvm_prf_names
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_GNU_RETAIN ]
+ AddressAlign: 0x1
+ Content: A6010073696D706C655F6C6F6F707301636F6E646974696F6E616C73016561726C795F6578697473016A756D7073017377697463686573016269675F73776974636801626F6F6C65616E5F6F70657261746F727301626F6F6C6F705F6C6F6F707301636F6E646974696F6E616C5F6F70657261746F7201646F5F66616C6C7468726F756768016D61696E016272616E63682D632D67656E6572616C2E633A7374617469635F66756E63
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .strtab
+ - Name: __llvm_covfun
+ - Name: '__llvm_covfun (1)'
+ - Name: '__llvm_covfun (2)'
+ - Name: '__llvm_covfun (3)'
+ - Name: '__llvm_covfun (4)'
+ - Name: '__llvm_covfun (5)'
+ - Name: '__llvm_covfun (6)'
+ - Name: '__llvm_covfun (7)'
+ - Name: '__llvm_covfun (8)'
+ - Name: '__llvm_covfun (9)'
+ - Name: '__llvm_covfun (10)'
+ - Name: '__llvm_covfun (11)'
+ - Name: __llvm_covmap
+ - Name: __llvm_prf_names
+ - Name: .symtab
+Symbols:
+ - Name: __llvm_covmap
+ Type: STT_SECTION
+ Section: __llvm_covmap
+ - Name: __llvm_prf_names
+ Type: STT_SECTION
+ Section: __llvm_prf_names
+ - Name: __covrec_79BE9FB148987D7u
+ Type: STT_OBJECT
+ Section: __llvm_covfun
+ Binding: STB_WEAK
+ Size: 0x69
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_688E43F1A505AD83u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (1)'
+ Binding: STB_WEAK
+ Size: 0x106
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_6973C52804C74904u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (2)'
+ Binding: STB_WEAK
+ Size: 0x114
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_5E259F0529789455u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (3)'
+ Binding: STB_WEAK
+ Size: 0x1D4
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_BF9282263CCA2971u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (4)'
+ Binding: STB_WEAK
+ Size: 0x169
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_7B4187606E1C4D3Fu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (5)'
+ Binding: STB_WEAK
+ Size: 0x14E
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_58A39A89A88AA459u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (6)'
+ Binding: STB_WEAK
+ Size: 0x8E
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_135D504B043D95F5u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (7)'
+ Binding: STB_WEAK
+ Size: 0xBA
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_795CF1BD69C3E520u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (8)'
+ Binding: STB_WEAK
+ Size: 0x5C
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_42EB9670C4E7E87Du
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (9)'
+ Binding: STB_WEAK
+ Size: 0x6E
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_DB956436E78DD5FAu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (10)'
+ Binding: STB_WEAK
+ Size: 0x26
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_F9EB37679DF4B44Cu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (11)'
+ Binding: STB_WEAK
+ Size: 0x3E
+ Other: [ STV_HIDDEN ]
+...
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c
index 2e7e773e5c3941..5ea9ecb42b0ed1 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c
@@ -4,75 +4,75 @@
-void simple_loops() {
+void simple_loops() { // CHECK: @LINE|{{.*}}simple_loops()
int i;
- for (i = 0; i < 100; ++i) {
+ for (i = 0; i < 100; ++i) { // BRCOV: Branch ([[@LINE]]:15): [True: [[C100:100|1]], False: 1]
}
- while (i > 0)
+ while (i > 0) // BRCOV: Branch ([[@LINE]]:10): [True: [[C100]], False: 1]
i--;
- do {} while (i++ < 75);
+ do {} while (i++ < 75); // BRCOV: Branch ([[@LINE]]:16): [True: [[C75:75|1]], False: 1]
}
-void conditionals() {
- for (int i = 0; i < 100; ++i) {
- if (i % 2) {
- if (i) {}
- } else if (i % 3) {
- if (i) {}
+void conditionals() { // CHECK: @LINE|{{.*}}conditionals()
+ for (int i = 0; i < 100; ++i) {//BRCOV: Branch ([[@LINE]]:19): [True: [[C100]], False: 1]
+ if (i % 2) { // BRCOV: Branch ([[@LINE]]:9): [True: [[C50:50|1]], False: [[C50]]]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C50]], False: 0]
+ } else if (i % 3) { // BRCOV: Branch ([[@LINE]]:16): [True: [[C33:33|1]], False: [[C17:17|1]]]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C33]], False: 0]
} else {
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C16:16|1]], False: 1]
}
-
- if (1 && i) {}
- if (0 || i) {}
- }
+ // BRCOV: Branch ([[@LINE+1]]:9): [True: [[C100]], Folded]
+ if (1 && i) {} // BRCOV: Branch ([[@LINE]]:14): [True: [[C99:99|1]], False: 1]
+ if (0 || i) {} // BRCOV: Branch ([[@LINE]]:9): [Folded, False: [[C100]]]
+ } // BRCOV: Branch ([[@LINE-1]]:14): [True: [[C99]], False: 1]
}
-void early_exits() {
+void early_exits() { // CHECK: @LINE|{{.*}}early_exits()
int i = 0;
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: 1]
- while (i < 100) {
+ while (i < 100) { // BRCOV: Branch ([[@LINE]]:10): [True: [[C51:51|1]], False: 0]
i++;
- if (i > 50)
+ if (i > 50) // BRCOV: Branch ([[@LINE]]:9): [True: 1, False: [[C50]]]
break;
- if (i % 2)
+ if (i % 2) // BRCOV: Branch ([[@LINE]]:9): [True: [[C25:25|1]], False: [[C25]]]
continue;
}
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:7): [True: 1, False: 0]
do {
- if (i > 75)
+ if (i > 75) // BRCOV: Branch ([[@LINE]]:9): [True: 1, False: [[C25]]]
return;
else
i++;
- } while (i < 100);
+ } while (i < 100); // BRCOV: Branch ([[@LINE]]:12): [True: [[C25]], False: 0]
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: 0]
}
-void jumps() {
+void jumps() { // CHECK: @LINE|{{.*}}jumps()
int i;
- for (i = 0; i < 2; ++i) {
+ for (i = 0; i < 2; ++i) { // BRCOV: Branch ([[@LINE]]:15): [True: 1, False: 0]
goto outofloop;
// Never reached -> no weights
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:9): [True: 0, False: 0]
}
outofloop:
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: 1]
goto loop1;
- while (i) {
+ while (i) { // BRCOV: Branch ([[@LINE]]:10): [True: 0, False: 1]
loop1:
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:9): [True: 0, False: 1]
}
goto loop2;
@@ -80,143 +80,143 @@ void jumps() {
second:
third:
i++;
- if (i < 3)
+ if (i < 3) // BRCOV: Branch ([[@LINE]]:7): [True: [[C2:2|1]], False: 1]
goto loop2;
- while (i < 3) {
+ while (i < 3) { // BRCOV: Branch ([[@LINE]]:10): [True: 0, False: 1]
loop2:
switch (i) {
- case 0:
+ case 0: // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
goto first;
- case 1:
+ case 1: // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
goto second;
- case 2:
+ case 2: // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
goto third;
}
}
- for (i = 0; i < 10; ++i) {
+ for (i = 0; i < 10; ++i) { // BRCOV: Branch ([[@LINE]]:15): [True: [[C10:10|1]], False: 1]
goto withinloop;
- // never reached -> no weights
- if (i) {}
+ // never reached -> no weights
+ if (i) {} // BRCOV: Branch ([[@LINE]]:9): [True: 0, False: 0]
withinloop:
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:9): [True: [[C9:9|1]], False: 1]
}
}
-void switches() {
+void switches() { // CHECK: @LINE|{{.*}}switches()
static int weights[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5};
// No cases -> no weights
switch (weights[0]) {
- default:
+ default: // BRCOV: Branch ([[@LINE]]:3): [True: 1, Folded]
break;
}
-
+ // BRCOV: Branch ([[@LINE+1]]:63): [True: [[C15:15|1]], False: 0]
for (int i = 0, len = sizeof(weights) / sizeof(weights[0]); i < len; ++i) {
switch (i[weights]) {
- case 1:
- if (i) {}
+ case 1: // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 0, False: 1]
// fallthrough
- case 2:
- if (i) {}
+ case 2: // BRCOV: Branch ([[@LINE]]:5): [True: [[C2]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C2]], False: 1]
break;
- case 3:
- if (i) {}
+ case 3: // BRCOV: Branch ([[@LINE]]:5): [True: [[C3:3|1]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C3]], False: 0]
continue;
- case 4:
- if (i) {}
+ case 4: // BRCOV: Branch ([[@LINE]]:5): [True: [[C4:4|1]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C4]], False: 0]
switch (i) {
- case 6 ... 9:
- if (i) {}
+ case 6 ... 9: // BRCOV: Branch ([[@LINE]]:7): [True: [[C4]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:13): [True: [[C4]], False: 0]
continue;
}
- default:
- if (i == len - 1)
+ default: // BRCOV: Branch ([[@LINE]]:5): [True: [[C5:5|1]], Folded]
+ if (i == len - 1) // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: [[C4]]]
return;
}
}
// Never reached -> no weights
- if (weights[0]) {}
+ if (weights[0]) {} // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: 0]
}
-void big_switch() {
- for (int i = 0; i < 32; ++i) {
+void big_switch() { // CHECK: @LINE|{{.*}}big_switch()
+ for (int i = 0; i < 32; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[C32:32|1]], False: 1]
switch (1 << i) {
- case (1 << 0):
- if (i) {}
+ case (1 << 0): // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 0, False: 1]
// fallthrough
- case (1 << 1):
- if (i) {}
+ case (1 << 1): // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: 1]
break;
- case (1 << 2) ... (1 << 12):
- if (i) {}
+ case (1 << 2) ... (1 << 12):// BRCOV: Branch ([[@LINE]]:5): [True: [[C11:11|1]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C11]], False: 0]
break;
// The branch for the large case range above appears after the case body.
- case (1 << 13):
- if (i) {}
+ case (1 << 13): // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: 0]
break;
- case (1 << 14) ... (1 << 28):
- if (i) {}
+ case (1 << 14) ... (1 << 28)://BRCOV: Branch ([[@LINE]]:5): [True: [[C15]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C15]], False: 0]
break;
// The branch for the large case range above appears after the case body.
case (1 << 29) ... ((1 << 29) + 1):
- if (i) {}
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: 0]
break;
- default:
- if (i) {}
+ default: // BRCOV: Branch ([[@LINE]]:5): [True: [[C2]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C2]], False: 0]
break;
}
}
}
-void boolean_operators() {
+void boolean_operators() { // CHECK: @LINE|{{.*}}boolean_operators()
int v;
for (int i = 0; i < 100; ++i) {
- v = i % 3 || i;
-
- v = i % 3 && i;
-
- v = i % 3 || i % 2 || i;
-
- v = i % 2 && i % 3 && i;
- }
-
-}
-
-void boolop_loops() {
+ v = i % 3 || i; // BRCOV: Branch ([[@LINE]]:9): [True: [[C66:66|1]], False: [[C34:34|1]]]
+ // BRCOV: Branch ([[@LINE-1]]:18): [True: [[C33]], False: 1]
+ v = i % 3 && i; // BRCOV: Branch ([[@LINE]]:9): [True: [[C66]], False: [[C34]]]
+ // BRCOV: Branch ([[@LINE-1]]:18): [True: [[C66]], False: 0]
+ v = i % 3 || i % 2 || i; // BRCOV: Branch ([[@LINE]]:9): [True: [[C66]], False: [[C34]]]
+ // BRCOV: Branch ([[@LINE-1]]:18): [True: [[C17]], False: [[C17]]]
+ v = i % 2 && i % 3 && i; // BRCOV: Branch ([[@LINE-2]]:27): [True: [[C16]], False: 1]
+ } // BRCOV: Branch ([[@LINE-1]]:9): [True: [[C50]], False: [[C50]]]
+ // BRCOV: Branch ([[@LINE-2]]:18): [True: [[C33]], False: [[C17]]]
+} // BRCOV: Branch ([[@LINE-3]]:27): [True: [[C33]], False: 0]
+
+void boolop_loops() { // CHECK: @LINE|{{.*}}boolop_loops()
int i = 100;
- while (i && i > 50)
- i--;
-
- while ((i % 2) || (i > 0))
- i--;
-
- for (i = 100; i && i > 50; --i);
+ while (i && i > 50) // BRCOV: Branch ([[@LINE]]:10): [True: [[C51]], False: 0]
+ i--; // BRCOV: Branch ([[@LINE-1]]:15): [True: [[C50]], False: 1]
- for (; (i % 2) || (i > 0); --i);
+ while ((i % 2) || (i > 0)) // BRCOV: Branch ([[@LINE]]:10): [True: [[C25]], False: [[C26:26|1]]]
+ i--; // BRCOV: Branch ([[@LINE-1]]:21): [True: [[C25]], False: 1]
+ for (i = 100; i && i > 50; --i); // BRCOV: Branch ([[@LINE]]:17): [True: [[C51]], False: 0]
+ // BRCOV: Branch ([[@LINE-1]]:22): [True: [[C50]], False: 1]
+ for (; (i % 2) || (i > 0); --i); // BRCOV: Branch ([[@LINE]]:10): [True: [[C25]], False: [[C26]]]
+ // BRCOV: Branch ([[@LINE-1]]:21): [True: [[C25]], False: 1]
}
-void conditional_operator() {
+void conditional_operator() { // CHECK: @LINE|{{.*}}conditional_operator()
int i = 100;
- int j = i < 50 ? i : 1;
+ int j = i < 50 ? i : 1; // BRCOV: Branch ([[@LINE]]:11): [True: 0, False: 1]
- int k = i ?: 0;
+ int k = i ?: 0; // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: 0]
}
-void do_fallthrough() {
- for (int i = 0; i < 10; ++i) {
+void do_fallthrough() { // CHECK: @LINE|{{.*}}do_fallthrough()
+ for (int i = 0; i < 10; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[C10]], False: 1]
int j = 0;
do {
// The number of exits out of this do-loop via the break statement
@@ -224,12 +224,12 @@ void do_fallthrough() {
// fallthrough count). Make sure that does not violate any assertions.
if (i < 8) break;
j++;
- } while (j < 2);
+ } while (j < 2); // BRCOV: Branch ([[@LINE]]:14): [True: [[C2]], False: [[C2]]]
}
}
-static void static_func() {
- for (int i = 0; i < 10; ++i) {
+static void static_func() { // CHECK: @LINE|{{.*}}static_func()
+ for (int i = 0; i < 10; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[C10]], False: 1]
}
}
@@ -254,7 +254,7 @@ int main(int argc, const char *argv[]) {
conditional_operator();
do_fallthrough();
static_func();
- extern void __llvm_profile_write_file();
- __llvm_profile_write_file();
+ (void)0;
+ (void)0;
return 0;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.proftext
new file mode 100644
index 00000000000000..f9662438de0e64
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.proftext
@@ -0,0 +1,84 @@
+# Instrument block coverage
+:single_byte_coverage
+_Z4funcii
+# Func Hash:
+8468630735863722633
+# Num Counters:
+67
+# Counter Values:
+4
+0
+0
+0
+0
+2
+0
+2
+2
+3
+2
+0
+0
+0
+0
+0
+0
+1
+0
+1
+1
+3
+3
+3
+3
+3
+3
+1
+2
+0
+3
+0
+0
+0
+1
+0
+1
+0
+3
+3
+3
+3
+4
+1
+0
+2
+1
+0
+0
+3
+0
+2
+0
+2
+0
+0
+4
+4
+4
+0
+4
+1
+3
+4
+3
+1
+4
+
+main
+# Func Hash:
+24
+# Num Counters:
+1
+# Counter Values:
+4
+
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.yaml b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.yaml
new file mode 100644
index 00000000000000..56f3d4955f4d93
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed-single.yaml
@@ -0,0 +1,57 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_X86_64
+ SectionHeaderStringTable: .strtab
+Sections:
+ - Name: __llvm_covfun
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: F0A0ED2C305C0BB32D02000089B21C19C99E86758F2950E06FBD46E8010100600108194302100701000101010C000E01000C010E01000C020E01000C030E01000C040E25010C000E1D010C000E15010C000E0D010C000E05010C000E100101000101010C000E01000C010E01000C020E01000C030E01000C040E4D010C000E45010C000E3D010C000E35010C000E2D010C000E100101000101010C011001000C031001000C051001000C071001000C091001000D000F69010D000F65010C011065000D000F71010D000F61010C011061000D000F79010D000F5D010C01105D000D000F8101010D000F59010C011059000D000F8901010D000F55010C011055000D000F9101010D000F100101000101010C011001000C031001000C051001000C071001000C091001000D000FAD01010D000FA901010C0110A901000D000FB501010D000FA501010C0110A501000D000FBD01010D000FA101010C0110A101000D000FC501010D000F9D01010C01109D01000D000FCD01010D000F9901010C01109901000D000FD501010D000F10010100010101070008DD010009018580808008DD0101050016E1010017028580808008E101020500161001010001E50101030E02E50100070008E9010009018580808008E90101050016ED010017028580808008ED01020500161001010001F10101030902F10100070008F5010009018580808008F50101050016F9010017028580808008F901020500161001010001FD0101030402FD01000700088102000901858080800881020105001685020017028580808008850202050016
+ - Name: '__llvm_covfun (1)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: FAD58DE7366495DB0900000018000000000000008F2950E06FBD46E801010001014F010402
+ - Name: __llvm_covmap
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 000000001D0000000000000006000000021A0000186272616E63682D6C6F676963616C2D6D697865642E637070000000
+ - Name: __llvm_prf_names
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_GNU_RETAIN ]
+ AddressAlign: 0x1
+ Content: 0E005F5A3466756E636969016D61696E
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .strtab
+ - Name: __llvm_covfun
+ - Name: '__llvm_covfun (1)'
+ - Name: __llvm_covmap
+ - Name: __llvm_prf_names
+ - Name: .symtab
+Symbols:
+ - Name: __llvm_covmap
+ Type: STT_SECTION
+ Section: __llvm_covmap
+ - Name: __llvm_prf_names
+ Type: STT_SECTION
+ Section: __llvm_prf_names
+ - Name: __covrec_B30B5C302CEDA0F0u
+ Type: STT_OBJECT
+ Section: __llvm_covfun
+ Binding: STB_WEAK
+ Size: 0x249
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_DB956436E78DD5FAu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (1)'
+ Binding: STB_WEAK
+ Size: 0x25
+ Other: [ STV_HIDDEN ]
+...
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
index 0a7d8d89671158..0eaf4c963ef9f4 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
@@ -4,7 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
-
+// CHECK: |{{ +}}[[C4:4|1]]|void func(
void func(int a, int b) {
bool b0 = a <= b;
bool b1 = a == b;
@@ -13,71 +13,71 @@ void func(int a, int b) {
bool b4 = a > b;
bool b5 = a != b;
- bool c = b0 && // CHECK: Branch ([[@LINE]]:12): [True: 3, False: 1]
- b1 && // CHECK: Branch ([[@LINE]]:12): [True: 2, False: 1]
- b2 && // CHECK: Branch ([[@LINE]]:12): [True: 2, False: 0]
- b3 && // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 2]
- b4 && // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
- b5; // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
+ bool c = b0 && // BRCOV: Branch ([[@LINE]]:12): [True: [[C3:3|1]], False: 1]
+ b1 && // BRCOV: Branch ([[@LINE]]:12): [True: [[C2:2|1]], False: 1]
+ b2 && // BRCOV: Branch ([[@LINE]]:12): [True: [[C2]], False: 0]
+ b3 && // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: [[C2]]]
+ b4 && // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
+ b5; // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
- bool d = b0 || // CHECK: Branch ([[@LINE]]:12): [True: 3, False: 1]
- b1 || // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 1]
- b2 || // CHECK: Branch ([[@LINE]]:12): [True: 1, False: 0]
- b3 || // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
- b4 || // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
- b5; // CHECK: Branch ([[@LINE]]:12): [True: 0, False: 0]
+ bool d = b0 || // BRCOV: Branch ([[@LINE]]:12): [True: [[C3]], False: 1]
+ b1 || // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 1]
+ b2 || // BRCOV: Branch ([[@LINE]]:12): [True: 1, False: 0]
+ b3 || // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
+ b4 || // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
+ b5; // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
- bool e = (b0 && // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 1]
- b5) || // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
- (b1 && // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 1]
- b4) || // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 2]
- (b2 && // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 0]
- b3) || // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 3]
- (b3 && // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 3]
- b2) || // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 0]
- (b4 && // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
- b1) || // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 1]
- (b5 && // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
- b0); // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 1]
+ bool e = (b0 && // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 1]
+ b5) || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
+ (b1 && // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: 1]
+ b4) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C2]]]
+ (b2 && // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 0]
+ b3) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C3]]]
+ (b3 && // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C3]]]
+ b2) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 0]
+ (b4 && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
+ b1) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 1]
+ (b5 && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
+ b0); // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 1]
- bool f = (b0 || // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 1]
- b5) && // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 0]
- (b1 || // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 2]
- b4) && // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 1]
- (b2 || // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 0]
- b3) && // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 0]
- (b3 || // CHECK: Branch ([[@LINE]]:13): [True: 0, False: 3]
- b2) && // CHECK: Branch ([[@LINE]]:13): [True: 3, False: 0]
- (b4 || // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
- b1) && // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 0]
- (b5 || // CHECK: Branch ([[@LINE]]:13): [True: 1, False: 2]
- b0); // CHECK: Branch ([[@LINE]]:13): [True: 2, False: 0]
+ bool f = (b0 || // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 1]
+ b5) && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: 0]
+ (b1 || // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: [[C2]]]
+ b4) && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: 1]
+ (b2 || // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 0]
+ b3) && // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 0]
+ (b3 || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C3]]]
+ b2) && // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 0]
+ (b4 || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
+ b1) && // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: 0]
+ (b5 || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
+ b0); // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: 0]
- if (c) // CHECK: Branch ([[@LINE]]:7): [True: 0, False: 4]
+ if (c) // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: [[C4]]]
printf("case0\n");
else
printf("case1\n");
- if (d) // CHECK: Branch ([[@LINE]]:7): [True: 4, False: 0]
+ if (d) // BRCOV: Branch ([[@LINE]]:7): [True: [[C4]], False: 0]
printf("case2\n");
else
printf("case3\n");
- if (e) // CHECK: Branch ([[@LINE]]:7): [True: 1, False: 3]
+ if (e) // BRCOV: Branch ([[@LINE]]:7): [True: 1, False: [[C3]]]
printf("case4\n");
else
printf("case5\n");
- if (f) // CHECK: Branch ([[@LINE]]:7): [True: 3, False: 1]
+ if (f) // BRCOV: Branch ([[@LINE]]:7): [True: [[C3]], False: 1]
printf("case6\n");
else
printf("case7\n");
}
-extern "C" { extern void __llvm_profile_write_file(void); }
+
int main(int argc, char *argv[])
{
func(atoi(argv[1]), atoi(argv[2]));
- __llvm_profile_write_file();
+ (void)0;
return 0;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-macros-single.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-macros-single.proftext
new file mode 100644
index 00000000000000..afb4b1038d3f8f
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-macros-single.proftext
@@ -0,0 +1,53 @@
+# Instrument block coverage
+:single_byte_coverage
+_Z4funcii
+# Func Hash:
+456046650042366162
+# Num Counters:
+19
+# Counter Values:
+3
+1
+0
+1
+0
+1
+0
+1
+0
+1
+0
+0
+0
+0
+0
+0
+0
+0
+0
+
+_Z5func2ii
+# Func Hash:
+14151920320560143107
+# Num Counters:
+10
+# Counter Values:
+3
+3
+2
+1
+0
+3
+0
+3
+1
+0
+
+main
+# Func Hash:
+24
+# Num Counters:
+1
+# Counter Values:
+3
+
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-macros-single.yaml b/llvm/test/tools/llvm-cov/Inputs/branch-macros-single.yaml
new file mode 100644
index 00000000000000..5c5f62b11863bd
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-macros-single.yaml
@@ -0,0 +1,69 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_X86_64
+ SectionHeaderStringTable: .strtab
+Sections:
+ - Name: __llvm_covfun
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: F0A0ED2C305C0BB33F010000D238C8100334540693E696313ECE8F5D15010101010101010101010101010101010101010101001501101911020C010C0011140015001A100101005C1C010C0011100101006224010C001210010100682C010C0012100101006E34010C0012100101007401010A000B01000A001001000A001501000A001A45000F00103D00140015350019001A2D001E001F10010104550201050F001701000F00170105060F00170301070F001F3C00100015440019001E014C0910001501540A100016015C0B1000160201050F001701000F0017010D060F00170301070F001F64001000156C0019001E017409100015017C0A1000160201050F001701000F00170115060F00170301070F001F8401001000158C010019001E019401091000150201050F001701000F0017011D060F00170301070F001F9C0100100015A4010019001E0201050F001701000F00170125060F0017
+ - Name: '__llvm_covfun (1)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: B01D983FC67363959E000000039B9E2C8DB865C493E696313ECE8F5D0D01010101010101010101010101000401241A07020C010E0014140018001D1001010365011C0B1000160405080F002624001000152C0018001D3400200025013C0A1000160305070F001F44001000154C0019001E0119060F0017011D050F00170154091000150205050F001705000F00170121060F00170401070F001F01000F001F5C00100015640019001E0201050F001701000F0017010D060F0017
+ - Name: '__llvm_covfun (2)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: FAD58DE7366495DB09000000180000000000000093E696313ECE8F5D01010001012F010502
+ - Name: __llvm_covmap
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 0000000016000000000000000600000002130000116272616E63682D6D6163726F732E6370700000
+ - Name: __llvm_prf_names
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_GNU_RETAIN ]
+ AddressAlign: 0x1
+ Content: 19005F5A3466756E636969015F5A3566756E63326969016D61696E
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .strtab
+ - Name: __llvm_covfun
+ - Name: '__llvm_covfun (1)'
+ - Name: '__llvm_covfun (2)'
+ - Name: __llvm_covmap
+ - Name: __llvm_prf_names
+ - Name: .symtab
+Symbols:
+ - Name: __llvm_covmap
+ Type: STT_SECTION
+ Section: __llvm_covmap
+ - Name: __llvm_prf_names
+ Type: STT_SECTION
+ Section: __llvm_prf_names
+ - Name: __covrec_B30B5C302CEDA0F0u
+ Type: STT_OBJECT
+ Section: __llvm_covfun
+ Binding: STB_WEAK
+ Size: 0x15B
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_956373C63F981DB0u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (1)'
+ Binding: STB_WEAK
+ Size: 0xBA
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_DB956436E78DD5FAu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (2)'
+ Binding: STB_WEAK
+ Size: 0x25
+ Other: [ STV_HIDDEN ]
+...
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
index 712b2790f774aa..e2abe748d86dc8 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
@@ -12,41 +12,41 @@
#include <stdlib.h>
-
+// CHECK: |{{ +}}[[C3:3|1]]|bool func(
bool func(int a, int b) {
- bool c = COND1 && COND2; // CHECK: | | | Branch ([[@LINE-12]]:15): [True: 1, False: 2]
- // CHECK: | | | Branch ([[@LINE-12]]:15): [True: 0, False: 1]
- bool d = COND3; // CHECK: | | | | | Branch ([[@LINE-14]]:15): [True: 1, False: 2]
- // CHECK: | | | | | Branch ([[@LINE-14]]:15): [True: 0, False: 1]
- bool e = MACRO1; // CHECK: | | | | | | | Branch ([[@LINE-16]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | Branch ([[@LINE-16]]:15): [True: 0, False: 1]
- bool f = MACRO2; // CHECK: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 0, False: 1]
- bool g = MACRO3; // CHECK: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 0, False: 1]
+ bool c = COND1 && COND2; // BRCOV: | | | Branch ([[@LINE-12]]:15): [True: 1, False: [[C2:2|1]]]
+ // BRCOV: | | | Branch ([[@LINE-12]]:15): [True: 0, False: 1]
+ bool d = COND3; // BRCOV: | | | | | Branch ([[@LINE-14]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | | | Branch ([[@LINE-14]]:15): [True: 0, False: 1]
+ bool e = MACRO1; // BRCOV: | | | | | | | Branch ([[@LINE-16]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | | | | | Branch ([[@LINE-16]]:15): [True: 0, False: 1]
+ bool f = MACRO2; // BRCOV: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 0, False: 1]
+ bool g = MACRO3; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 0, False: 1]
return c && d && e && f && g;
- // CHECK: | Branch ([[@LINE-1]]:10): [True: 0, False: 3]
- // CHECK: | Branch ([[@LINE-2]]:15): [True: 0, False: 0]
- // CHECK: | Branch ([[@LINE-3]]:20): [True: 0, False: 0]
- // CHECK: | Branch ([[@LINE-4]]:25): [True: 0, False: 0]
- // CHECK: | Branch ([[@LINE-5]]:30): [True: 0, False: 0]
+ // BRCOV: | Branch ([[@LINE-1]]:10): [True: 0, False: [[C3]]]
+ // BRCOV: | Branch ([[@LINE-2]]:15): [True: 0, False: 0]
+ // BRCOV: | Branch ([[@LINE-3]]:20): [True: 0, False: 0]
+ // BRCOV: | Branch ([[@LINE-4]]:25): [True: 0, False: 0]
+ // BRCOV: | Branch ([[@LINE-5]]:30): [True: 0, False: 0]
}
bool func2(int a, int b) {
- bool h = MACRO3 || COND4; // CHECK: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 0, False: 1]
- // CHECK: | | | | | | | Branch ([[@LINE-34]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | Branch ([[@LINE-34]]:15): [True: 0, False: 1]
- // CHECK: | | | Branch ([[@LINE-33]]:15): [True: 1, False: 2]
+ bool h = MACRO3 || COND4; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 0, False: 1]
+ // BRCOV: | | | | | | | Branch ([[@LINE-34]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | | | | | Branch ([[@LINE-34]]:15): [True: 0, False: 1]
+ // BRCOV: | | | Branch ([[@LINE-33]]:15): [True: 1, False: [[C2]]]
return h;
}
-extern "C" { extern void __llvm_profile_write_file(void); }
+
int main(int argc, char *argv[])
{
func(atoi(argv[1]), atoi(argv[2]));
func2(atoi(argv[1]), atoi(argv[2]));
- __llvm_profile_write_file();
+ (void)0;
return 0;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c
index c41739ff0b22f1..6db980a8bd64a8 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-showBranchPercentage.c
@@ -13,7 +13,7 @@ int main(int argc, char *argv[])
int i = 0;
if (argc < 3) // CHECK: Branch ([[@LINE]]:7): [True: 16.67%, False: 83.33%]
{
- __llvm_profile_write_file();
+ (void)0;
return 0;
}
@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
printf("loop\n");
} while (i++ < 10); // CHECK: Branch ([[@LINE]]:12): [True: 90.91%, False: 9.09%]
- __llvm_profile_write_file();
+ (void)b;
- return b;
+ return 0;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-templates-single.proftext b/llvm/test/tools/llvm-cov/Inputs/branch-templates-single.proftext
new file mode 100644
index 00000000000000..829431334478f3
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-templates-single.proftext
@@ -0,0 +1,49 @@
+# Instrument block coverage
+:single_byte_coverage
+_Z4funcIbEiT_
+# Func Hash:
+11045778961
+# Num Counters:
+4
+# Counter Values:
+1
+1
+0
+0
+
+_Z4funcIfEiT_
+# Func Hash:
+11045778961
+# Num Counters:
+4
+# Counter Values:
+1
+0
+1
+0
+
+_Z4funcIiEiT_
+# Func Hash:
+11045778961
+# Num Counters:
+4
+# Counter Values:
+1
+0
+1
+0
+
+main
+# Func Hash:
+185286008276329560
+# Num Counters:
+7
+# Counter Values:
+1
+1
+1
+0
+1
+1
+1
+
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-templates-single.yaml b/llvm/test/tools/llvm-cov/Inputs/branch-templates-single.yaml
new file mode 100644
index 00000000000000..d4ede6db448e61
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-templates-single.yaml
@@ -0,0 +1,81 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_X86_64
+ SectionHeaderStringTable: .strtab
+Sections:
+ - Name: __llvm_covfun
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: FAD58DE7366495DB5100000058242991A444920226ED9A40DAABBC6B0101000D011D0C090201010700130500140185808080080501050016090103060209000700170D00180185808080080D01050016110103040211000700171500180185808080081501050016190103010B
+ - Name: '__llvm_covfun (1)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 5427717259E0E43E38000000113661920200000026ED9A40DAABBC6B01010008010D0F06020101060007050008018580808008050105000D09000E028580808008090205000D0D000E0183808080080D01030102
+ - Name: '__llvm_covfun (2)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 4B7E22082F0551AA38000000113661920200000026ED9A40DAABBC6B01010008010D0F06020101060007050008018580808008050105000D09000E028580808008090205000D0D000E0183808080080D01030102
+ - Name: '__llvm_covfun (3)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: AC1440BC3DA3E41A38000000113661920200000026ED9A40DAABBC6B01010008010D0F06020101060007050008018580808008050105000D09000E028580808008090205000D0D000E0183808080080D01030102
+ - Name: __llvm_covmap
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 0000000019000000000000000600000002160000146272616E63682D74656D706C617465732E637070000000
+ - Name: __llvm_prf_names
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_GNU_RETAIN ]
+ AddressAlign: 0x1
+ Content: 2E006D61696E015F5A3466756E6349694569545F015F5A3466756E6349624569545F015F5A3466756E6349664569545F
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .strtab
+ - Name: __llvm_covfun
+ - Name: '__llvm_covfun (1)'
+ - Name: '__llvm_covfun (2)'
+ - Name: '__llvm_covfun (3)'
+ - Name: __llvm_covmap
+ - Name: __llvm_prf_names
+ - Name: .symtab
+Symbols:
+ - Name: __llvm_covmap
+ Type: STT_SECTION
+ Section: __llvm_covmap
+ - Name: __llvm_prf_names
+ Type: STT_SECTION
+ Section: __llvm_prf_names
+ - Name: __covrec_DB956436E78DD5FAu
+ Type: STT_OBJECT
+ Section: __llvm_covfun
+ Binding: STB_WEAK
+ Size: 0x6D
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_3EE4E05972712754u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (1)'
+ Binding: STB_WEAK
+ Size: 0x54
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_AA51052F08227E4Bu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (2)'
+ Binding: STB_WEAK
+ Size: 0x54
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_1AE4A33DBC4014ACu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (3)'
+ Binding: STB_WEAK
+ Size: 0x54
+ Other: [ STV_HIDDEN ]
+...
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
index 0795a5346380de..4d932eaf5944a8 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
@@ -11,28 +11,28 @@ void unused(T x) {
template<typename T>
int func(T x) {
- if(x) // CHECK: | Branch ([[@LINE]]:6): [True: 0, False: 1]
- return 0; // CHECK: | Branch ([[@LINE-1]]:6): [True: 1, False: 0]
- else // CHECK: | Branch ([[@LINE-2]]:6): [True: 0, False: 1]
+ if(x) // BRCOV: | Branch ([[@LINE]]:6): [True: 0, False: 1]
+ return 0; // BRCOV: | Branch ([[@LINE-1]]:6): [True: 1, False: 0]
+ else // BRCOV: | Branch ([[@LINE-2]]:6): [True: 0, False: 1]
return 1;
int j = 1;
}
// CHECK-LABEL: _Z4funcIiEiT_:
- // CHECK: | | Branch ([[@LINE-8]]:6): [True: 0, False: 1]
+ // BRCOV: | | Branch ([[@LINE-8]]:6): [True: 0, False: 1]
// CHECK-LABEL: _Z4funcIbEiT_:
- // CHECK: | | Branch ([[@LINE-10]]:6): [True: 1, False: 0]
+ // BRCOV: | | Branch ([[@LINE-10]]:6): [True: 1, False: 0]
// CHECK-LABEL: _Z4funcIfEiT_:
- // CHECK: | | Branch ([[@LINE-12]]:6): [True: 0, False: 1]
+ // BRCOV: | | Branch ([[@LINE-12]]:6): [True: 0, False: 1]
+
-extern "C" { extern void __llvm_profile_write_file(void); }
int main() {
- if (func<int>(0)) // CHECK: | Branch ([[@LINE]]:7): [True: 1, False: 0]
+ if (func<int>(0)) // BRCOV: | Branch ([[@LINE]]:7): [True: 1, False: 0]
printf("case1\n");
- if (func<bool>(true)) // CHECK: | Branch ([[@LINE]]:7): [True: 0, False: 1]
+ if (func<bool>(true)) // BRCOV: | Branch ([[@LINE]]:7): [True: 0, False: 1]
printf("case2\n");
- if (func<float>(0.0)) // CHECK: | Branch ([[@LINE]]:7): [True: 1, False: 0]
+ if (func<float>(0.0)) // BRCOV: | Branch ([[@LINE]]:7): [True: 1, False: 0]
printf("case3\n");
- __llvm_profile_write_file();
+ (void)0;
return 0;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.proftext b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.proftext
new file mode 100644
index 00000000000000..1b7b949de49625
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.proftext
@@ -0,0 +1,23 @@
+# Instrument block coverage
+:single_byte_coverage
+main
+# Func Hash:
+15239891155360101223
+# Num Counters:
+14
+# Counter Values:
+161
+0
+161
+161
+161
+161
+161
+161
+161
+161
+0
+161
+0
+161
+
diff --git a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.yaml b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.yaml
new file mode 100644
index 00000000000000..84b184023f0822
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts-single.yaml
@@ -0,0 +1,45 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_X86_64
+ SectionHeaderStringTable: .strtab
+Sections:
+ - Name: __llvm_covfun
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: FAD58DE7366495DB9A0000006733DBEA42F87ED3C60E0B951FF3509D0101001A01060C130210020100010101070008050009008A8080800805000A0204090204008A8080800809000A020410030100010D01030A02110013001A15001C001F19002000A180808008190021020410030100011D010306021D0007000D25000F0090808080082500100015290018001D2101030502210007000D31000F018980808008310109000E350109000E10010100012D0103000B
+ - Name: __llvm_covmap
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 00000000200000000000000006000000021D00001B73686F774C696E65457865637574696F6E436F756E74732E637070
+ - Name: __llvm_prf_names
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_GNU_RETAIN ]
+ AddressAlign: 0x1
+ Content: 04006D61696E
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .strtab
+ - Name: __llvm_covfun
+ - Name: __llvm_covmap
+ - Name: __llvm_prf_names
+ - Name: .symtab
+Symbols:
+ - Name: __llvm_covmap
+ Type: STT_SECTION
+ Section: __llvm_covmap
+ - Name: __llvm_prf_names
+ Type: STT_SECTION
+ Section: __llvm_prf_names
+ - Name: __covrec_DB956436E78DD5FAu
+ Type: STT_OBJECT
+ Section: __llvm_covfun
+ Binding: STB_WEAK
+ Size: 0xB6
+ Other: [ STV_HIDDEN ]
+...
diff --git a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
index c7e8c8fb0c75e4..b14409f173849d 100644
--- a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
@@ -3,26 +3,26 @@
// before any coverage // WHOLE-FILE: [[@LINE]]| |// before
// FILTER-NOT: [[@LINE-1]]| |// before
// HTML: <td class='line-number'><a name='L[[@LINE+1]]' href='#L[[@LINE+1]]'><pre>[[@LINE+1]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
-int main() { // TEXT: [[@LINE]]| 161|int main(
- int x = 0; // TEXT: [[@LINE]]| 161| int x
- // TEXT: [[@LINE]]| 161|
- if (x) { // TEXT: [[@LINE]]| 161| if (x)
- x = 0; // TEXT: [[@LINE]]| 0| x = 0
- } else { // TEXT: [[@LINE]]| 161| } else
- x = 1; // TEXT: [[@LINE]]| 161| x = 1
- } // TEXT: [[@LINE]]| 161| }
- // TEXT: [[@LINE]]| 161|
- for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| 16.2k| for (
- x = 1; // TEXT: [[@LINE]]| 16.1k| x = 1
- } // TEXT: [[@LINE]]| 16.1k| }
- // TEXT: [[@LINE]]| 161|
- x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| 161| x =
- x = x > 10 ? // TEXT: [[@LINE]]| 161| x =
- x - 1: // TEXT: [[@LINE]]| 0| x
- x + 1; // TEXT: [[@LINE]]| 161| x
- // TEXT: [[@LINE]]| 161|
- return 0; // TEXT: [[@LINE]]| 161| return
-} // TEXT: [[@LINE]]| 161|}
+int main() { // TEXT: [[@LINE]]| [[C161:161|1]]|int main(
+ int x = 0; // TEXT: [[@LINE]]| [[C161]]| int x
+
+ if (x) { // TEXT: [[@LINE]]| [[C161]]| if (x)
+ x = 0; // TEXT: [[@LINE]]| 0| x = 0
+ } else { // TEXT: [[@LINE]]| [[C161]]| } else
+ x = 1; // TEXT: [[@LINE]]| [[C161]]| x = 1
+ } // TEXT: [[@LINE]]| [[C161]]| }
+
+ for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| [[C16K2:16\.2k|161]]| for (
+ x = 1; // TEXT: [[@LINE]]| [[C16K1:16\.1k|161]]| x = 1
+ } // TEXT: [[@LINE]]| [[C16K1]]| }
+
+ x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| [[C161]]| x =
+ x = x > 10 ? // TEXT: [[@LINE]]| [[C161]]| x =
+ x - 1: // TEXT: [[@LINE]]| 0| x
+ x + 1; // TEXT: [[@LINE]]| [[C161]]| x
+
+ return 0; // TEXT: [[@LINE]]| [[C161]]| return
+} // TEXT: [[@LINE]]| [[C161]]|}
// after coverage // WHOLE-FILE: [[@LINE]]| |// after
// FILTER-NOT: [[@LINE-1]]| |// after
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-2]]' href='#L[[@LINE-2]]'><pre>[[@LINE-2]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
diff --git a/llvm/test/tools/llvm-cov/branch-c-general.test b/llvm/test/tools/llvm-cov/branch-c-general.test
index 865a2662460e83..3d0b7ee563222d 100644
--- a/llvm/test/tools/llvm-cov/branch-c-general.test
+++ b/llvm/test/tools/llvm-cov/branch-c-general.test
@@ -164,3 +164,7 @@
// HTML-INDEX: 79.07% (136/172)
// HTML-INDEX: <tr class='light-row-bold'>
// HTML-INDEX: Totals
+
+// RUN: yaml2obj %S/Inputs/branch-c-general-single.yaml -o %t.o
+// RUN: llvm-profdata merge %S/Inputs/branch-c-general-single.proftext -o %t.profdata
+// RUN: llvm-cov show --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs %S/Inputs/branch-c-general.c | FileCheck %S/Inputs/branch-c-general.c
diff --git a/llvm/test/tools/llvm-cov/branch-logical-mixed.test b/llvm/test/tools/llvm-cov/branch-logical-mixed.test
index a07d2357f2c34d..b03cabeb01855b 100644
--- a/llvm/test/tools/llvm-cov/branch-logical-mixed.test
+++ b/llvm/test/tools/llvm-cov/branch-logical-mixed.test
@@ -1,8 +1,14 @@
// RUN: llvm-profdata merge %S/Inputs/branch-logical-mixed.proftext -o %t.profdata
-// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp
+// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp -check-prefixes=CHECK,BRCOV
// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-logical-mixed.cpp
| FileCheck %s -check-prefix=REPORT
+// RUN: yaml2obj %S/Inputs/branch-logical-mixed-single.yaml -o %t.o
+// RUN: llvm-profdata merge %S/Inputs/branch-logical-mixed-single.proftext -o %t.profdata
+// RUN: llvm-cov show --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp
+// RUN: llvm-cov report --show-branch-summary %t.o -instr-profile %t.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/branch-logical-mixed.cpp
+| FileCheck %s -check-prefix=REPORT
+
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
// REPORT-NEXT: _Z4funcii 77 15 80.52% 60 2 96.67% 80 30 62.50%
diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test
index fbe7694b4f4e05..a4790afc534228 100644
--- a/llvm/test/tools/llvm-cov/branch-macros.test
+++ b/llvm/test/tools/llvm-cov/branch-macros.test
@@ -1,7 +1,11 @@
// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
-// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp
+// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -check-prefixes=CHECK,BRCOV
// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s -check-prefix=REPORT
+// RUN: yaml2obj %S/Inputs/branch-macros-single.yaml -o %t.o
+// RUN: llvm-profdata merge %S/Inputs/branch-macros-single.proftext -o %t.profdata
+// RUN: llvm-cov show --show-expansions --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp
+
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
// REPORT-NEXT: _Z4funcii 28 4 85.71% 18 0 100.00% 30 14 53.33%
diff --git a/llvm/test/tools/llvm-cov/branch-templates.test b/llvm/test/tools/llvm-cov/branch-templates.test
index 74aef16050228a..d5535022239f5f 100644
--- a/llvm/test/tools/llvm-cov/branch-templates.test
+++ b/llvm/test/tools/llvm-cov/branch-templates.test
@@ -3,6 +3,10 @@
// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-templates.cpp | FileCheck %s -check-prefix=REPORT
// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-templates.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %s -check-prefix=REPORTFILE
+// RUN: yaml2obj %S/Inputs/branch-templates-single.yaml -o %t.o
+// RUN: llvm-profdata merge %S/Inputs/branch-templates-single.proftext -o %t.profdata
+// RUN: llvm-cov show --show-expansions --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-templates.cpp
+
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
// REPORT-NEXT: main 7 1 85.71% 10 1 90.00% 6 3 50.00%
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
index 997b16a0b8e94f..2c0669a7cec42a 100644
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
@@ -41,3 +41,10 @@
// HTML-INDEX: 72.73% (8/11)
// HTML-INDEX: <tr class='light-row-bold'>
// HTML-INDEX: Totals
+
+// Single byte
+// RUN: yaml2obj %S/Inputs/showLineExecutionCounts-single.yaml -o %t.o
+// RUN: llvm-profdata merge %S/Inputs/showLineExecutionCounts-single.proftext -o %t.profdata
+
+// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER %S/Inputs/showLineExecutionCounts.cpp
>From 5fc3408628a72560490c5271de171a636f5be50a Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 20 Nov 2024 23:46:58 +0900
Subject: [PATCH 08/30] Fix a test to fix linecount=1
---
llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
index b14409f173849d..b63247341a28e4 100644
--- a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
@@ -12,8 +12,8 @@ int main() { // TEXT: [[@LINE]]| [[C161:161|1]]
x = 1; // TEXT: [[@LINE]]| [[C161]]| x = 1
} // TEXT: [[@LINE]]| [[C161]]| }
- for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| [[C16K2:16\.2k|161]]| for (
- x = 1; // TEXT: [[@LINE]]| [[C16K1:16\.1k|161]]| x = 1
+ for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| [[C16K2:16\.2k|1]]| for (
+ x = 1; // TEXT: [[@LINE]]| [[C16K1:16\.1k|1]]| x = 1
} // TEXT: [[@LINE]]| [[C16K1]]| }
x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| [[C161]]| x =
>From eb7fff9a3b8356851770d1b5c6a4f0a69a79af05 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 21 Nov 2024 07:57:37 +0900
Subject: [PATCH 09/30] threads.c: Fixup on the clean testdir
---
llvm/test/tools/llvm-cov/threads.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/threads.c b/llvm/test/tools/llvm-cov/threads.c
index b162b6ac5a8011..73dd82c3a74646 100644
--- a/llvm/test/tools/llvm-cov/threads.c
+++ b/llvm/test/tools/llvm-cov/threads.c
@@ -1,9 +1,10 @@
// Coverage/profile data recycled from the showLineExecutionCounts.cpp test.
//
+// RUN: rm -rf %t*.dir
// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t1.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t2.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t3.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t1.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t2.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t3.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
//
// RUN: diff %t1.dir/index.txt %t2.dir/index.txt
// RUN: diff %t1.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %t2.dir/coverage/tmp/showLineExecutionCounts.cpp.txt
>From 75430950a1a347f4a1c3d9dc0804afe9a3f25aaa Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 21 Nov 2024 23:20:19 +0900
Subject: [PATCH 10/30] Rename threads.c to threads.test since it is no longer
C source file.
---
llvm/test/tools/llvm-cov/{threads.c => threads.test} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename llvm/test/tools/llvm-cov/{threads.c => threads.test} (100%)
diff --git a/llvm/test/tools/llvm-cov/threads.c b/llvm/test/tools/llvm-cov/threads.test
similarity index 100%
rename from llvm/test/tools/llvm-cov/threads.c
rename to llvm/test/tools/llvm-cov/threads.test
>From 00ac90d232a5793a94f6863dcba2274f4e0126cb Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Thu, 21 Nov 2024 23:25:06 +0900
Subject: [PATCH 11/30] llvm/test/tools/llvm-cov/Inputs: Avoid wildcards `rm
-rf %t*.dir`
---
.../llvm-cov/showLineExecutionCounts.test | 22 +++++++++----------
llvm/test/tools/llvm-cov/threads.test | 16 +++++++-------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
index 2c0669a7cec42a..1c1e894922827f 100644
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
@@ -1,32 +1,32 @@
// Basic handling of line counts.
-// RUN: rm -rf %t*.dir
+// RUN: rm -rf %t.dir
// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE %S/Inputs/showLineExecutionCounts.cpp
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER %S/Inputs/showLineExecutionCounts.cpp
// Test -output-dir.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
-// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
-// RUN: FileCheck -check-prefixes=TEXT,FILTER -input-file %t.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir/show -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir/show.filtered -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
+// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -input-file %t.dir/show/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=TEXT,FILTER -input-file %t.dir/show.filtered/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
//
// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
// RUN: not grep '"name":"main"' %t.export-summary.json
//
// Test html output.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
-// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.html.dir/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
-// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.html.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.dir/html -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.dir/html.filtered -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
+// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.dir/html/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.dir/html.filtered/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
//
// Test index creation.
-// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/index.txt %s
+// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/show/index.txt %s
// TEXT-INDEX: Filename
// TEXT-INDEX-NEXT: ---
// TEXT-INDEX-NEXT: {{.*}}showLineExecutionCounts.cpp
//
-// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
+// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.dir/html/index.html %s
// HTML-INDEX-LABEL: <table>
// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
diff --git a/llvm/test/tools/llvm-cov/threads.test b/llvm/test/tools/llvm-cov/threads.test
index 73dd82c3a74646..a51406ca14efa9 100644
--- a/llvm/test/tools/llvm-cov/threads.test
+++ b/llvm/test/tools/llvm-cov/threads.test
@@ -1,12 +1,12 @@
// Coverage/profile data recycled from the showLineExecutionCounts.cpp test.
//
-// RUN: rm -rf %t*.dir
+// RUN: rm -rf %t.dir
// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t1.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t2.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t3.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t.dir/1 -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t.dir/2 -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir/3 -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
//
-// RUN: diff %t1.dir/index.txt %t2.dir/index.txt
-// RUN: diff %t1.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %t2.dir/coverage/tmp/showLineExecutionCounts.cpp.txt
-// RUN: diff %t1.dir/index.txt %t3.dir/index.txt
-// RUN: diff %t1.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %t3.dir/coverage/tmp/showLineExecutionCounts.cpp.txt
+// RUN: diff %t.dir/1/index.txt %t.dir/2/index.txt
+// RUN: diff %t.dir/1/coverage/tmp/showLineExecutionCounts.cpp.txt %t.dir/2/coverage/tmp/showLineExecutionCounts.cpp.txt
+// RUN: diff %t.dir/1/index.txt %t.dir/3/index.txt
+// RUN: diff %t.dir/1/coverage/tmp/showLineExecutionCounts.cpp.txt %t.dir/3/coverage/tmp/showLineExecutionCounts.cpp.txt
>From 5fa862ad60b75814c15f9317d6d59384524f5717 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 21 Dec 2024 17:30:24 +0900
Subject: [PATCH 12/30] Use `[[#min(C,n)]]` for tests
---
.../tools/llvm-cov/Inputs/branch-c-general.c | 120 +++++++++---------
.../llvm-cov/Inputs/branch-logical-mixed.cpp | 54 ++++----
.../tools/llvm-cov/Inputs/branch-macros.cpp | 22 ++--
.../Inputs/showLineExecutionCounts.cpp | 45 +++----
.../test/tools/llvm-cov/branch-c-general.test | 2 +-
.../tools/llvm-cov/branch-logical-mixed.test | 4 +-
llvm/test/tools/llvm-cov/branch-macros.test | 4 +-
.../llvm-cov/showLineExecutionCounts.test | 12 +-
8 files changed, 132 insertions(+), 131 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c
index 5ea9ecb42b0ed1..9660e857092bcb 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-c-general.c
@@ -6,27 +6,27 @@
void simple_loops() { // CHECK: @LINE|{{.*}}simple_loops()
int i;
- for (i = 0; i < 100; ++i) { // BRCOV: Branch ([[@LINE]]:15): [True: [[C100:100|1]], False: 1]
+ for (i = 0; i < 100; ++i) { // BRCOV: Branch ([[@LINE]]:15): [True: [[#min(C,100)]], False: 1]
}
- while (i > 0) // BRCOV: Branch ([[@LINE]]:10): [True: [[C100]], False: 1]
+ while (i > 0) // BRCOV: Branch ([[@LINE]]:10): [True: [[#min(C,100)]], False: 1]
i--;
- do {} while (i++ < 75); // BRCOV: Branch ([[@LINE]]:16): [True: [[C75:75|1]], False: 1]
+ do {} while (i++ < 75); // BRCOV: Branch ([[@LINE]]:16): [True: [[#min(C,75)]], False: 1]
}
void conditionals() { // CHECK: @LINE|{{.*}}conditionals()
- for (int i = 0; i < 100; ++i) {//BRCOV: Branch ([[@LINE]]:19): [True: [[C100]], False: 1]
- if (i % 2) { // BRCOV: Branch ([[@LINE]]:9): [True: [[C50:50|1]], False: [[C50]]]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C50]], False: 0]
- } else if (i % 3) { // BRCOV: Branch ([[@LINE]]:16): [True: [[C33:33|1]], False: [[C17:17|1]]]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C33]], False: 0]
+ for (int i = 0; i < 100; ++i) {//BRCOV: Branch ([[@LINE]]:19): [True: [[#min(C,100)]], False: 1]
+ if (i % 2) { // BRCOV: Branch ([[@LINE]]:9): [True: [[#min(C,50)]], False: [[#min(C,50)]]]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,50)]], False: 0]
+ } else if (i % 3) { // BRCOV: Branch ([[@LINE]]:16): [True: [[#min(C,33)]], False: [[#min(C,17)]]]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,33)]], False: 0]
} else {
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C16:16|1]], False: 1]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,16)]], False: 1]
}
- // BRCOV: Branch ([[@LINE+1]]:9): [True: [[C100]], Folded]
- if (1 && i) {} // BRCOV: Branch ([[@LINE]]:14): [True: [[C99:99|1]], False: 1]
- if (0 || i) {} // BRCOV: Branch ([[@LINE]]:9): [Folded, False: [[C100]]]
- } // BRCOV: Branch ([[@LINE-1]]:14): [True: [[C99]], False: 1]
+ // BRCOV: Branch ([[@LINE+1]]:9): [True: [[#min(C,100)]], Folded]
+ if (1 && i) {} // BRCOV: Branch ([[@LINE]]:14): [True: [[#min(C,99)]], False: 1]
+ if (0 || i) {} // BRCOV: Branch ([[@LINE]]:9): [Folded, False: [[#min(C,100)]]]
+ } // BRCOV: Branch ([[@LINE-1]]:14): [True: [[#min(C,99)]], False: 1]
}
@@ -35,22 +35,22 @@ void early_exits() { // CHECK: @LINE|{{.*}}early_exits()
if (i) {} // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: 1]
- while (i < 100) { // BRCOV: Branch ([[@LINE]]:10): [True: [[C51:51|1]], False: 0]
+ while (i < 100) { // BRCOV: Branch ([[@LINE]]:10): [True: [[#min(C,51)]], False: 0]
i++;
- if (i > 50) // BRCOV: Branch ([[@LINE]]:9): [True: 1, False: [[C50]]]
+ if (i > 50) // BRCOV: Branch ([[@LINE]]:9): [True: 1, False: [[#min(C,50)]]]
break;
- if (i % 2) // BRCOV: Branch ([[@LINE]]:9): [True: [[C25:25|1]], False: [[C25]]]
+ if (i % 2) // BRCOV: Branch ([[@LINE]]:9): [True: [[#min(C,25)]], False: [[#min(C,25)]]]
continue;
}
if (i) {} // BRCOV: Branch ([[@LINE]]:7): [True: 1, False: 0]
do {
- if (i > 75) // BRCOV: Branch ([[@LINE]]:9): [True: 1, False: [[C25]]]
+ if (i > 75) // BRCOV: Branch ([[@LINE]]:9): [True: 1, False: [[#min(C,25)]]]
return;
else
i++;
- } while (i < 100); // BRCOV: Branch ([[@LINE]]:12): [True: [[C25]], False: 0]
+ } while (i < 100); // BRCOV: Branch ([[@LINE]]:12): [True: [[#min(C,25)]], False: 0]
if (i) {} // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: 0]
@@ -80,7 +80,7 @@ void jumps() { // CHECK: @LINE|{{.*}}jumps()
second:
third:
i++;
- if (i < 3) // BRCOV: Branch ([[@LINE]]:7): [True: [[C2:2|1]], False: 1]
+ if (i < 3) // BRCOV: Branch ([[@LINE]]:7): [True: [[#min(C,2)]], False: 1]
goto loop2;
while (i < 3) { // BRCOV: Branch ([[@LINE]]:10): [True: 0, False: 1]
@@ -95,12 +95,12 @@ void jumps() { // CHECK: @LINE|{{.*}}jumps()
}
}
- for (i = 0; i < 10; ++i) { // BRCOV: Branch ([[@LINE]]:15): [True: [[C10:10|1]], False: 1]
+ for (i = 0; i < 10; ++i) { // BRCOV: Branch ([[@LINE]]:15): [True: [[#min(C,10)]], False: 1]
goto withinloop;
// never reached -> no weights
if (i) {} // BRCOV: Branch ([[@LINE]]:9): [True: 0, False: 0]
withinloop:
- if (i) {} // BRCOV: Branch ([[@LINE]]:9): [True: [[C9:9|1]], False: 1]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:9): [True: [[#min(C,9)]], False: 1]
}
}
@@ -113,28 +113,28 @@ void switches() { // CHECK: @LINE|{{.*}}switches()
default: // BRCOV: Branch ([[@LINE]]:3): [True: 1, Folded]
break;
}
- // BRCOV: Branch ([[@LINE+1]]:63): [True: [[C15:15|1]], False: 0]
+ // BRCOV: Branch ([[@LINE+1]]:63): [True: [[#min(C,15)]], False: 0]
for (int i = 0, len = sizeof(weights) / sizeof(weights[0]); i < len; ++i) {
switch (i[weights]) {
case 1: // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 0, False: 1]
// fallthrough
- case 2: // BRCOV: Branch ([[@LINE]]:5): [True: [[C2]], Folded]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C2]], False: 1]
+ case 2: // BRCOV: Branch ([[@LINE]]:5): [True: [[#min(C,2)]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,2)]], False: 1]
break;
- case 3: // BRCOV: Branch ([[@LINE]]:5): [True: [[C3:3|1]], Folded]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C3]], False: 0]
+ case 3: // BRCOV: Branch ([[@LINE]]:5): [True: [[#min(C,3)]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,3)]], False: 0]
continue;
- case 4: // BRCOV: Branch ([[@LINE]]:5): [True: [[C4:4|1]], Folded]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C4]], False: 0]
+ case 4: // BRCOV: Branch ([[@LINE]]:5): [True: [[#min(C,4)]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,4)]], False: 0]
switch (i) {
- case 6 ... 9: // BRCOV: Branch ([[@LINE]]:7): [True: [[C4]], Folded]
- if (i) {} // BRCOV: Branch ([[@LINE]]:13): [True: [[C4]], False: 0]
+ case 6 ... 9: // BRCOV: Branch ([[@LINE]]:7): [True: [[#min(C,4)]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,4)]], False: 0]
continue;
}
- default: // BRCOV: Branch ([[@LINE]]:5): [True: [[C5:5|1]], Folded]
- if (i == len - 1) // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: [[C4]]]
+ default: // BRCOV: Branch ([[@LINE]]:5): [True: [[#min(C,5)]], Folded]
+ if (i == len - 1) // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: [[#min(C,4)]]]
return;
}
}
@@ -145,7 +145,7 @@ void switches() { // CHECK: @LINE|{{.*}}switches()
}
void big_switch() { // CHECK: @LINE|{{.*}}big_switch()
- for (int i = 0; i < 32; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[C32:32|1]], False: 1]
+ for (int i = 0; i < 32; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[#min(C,32)]], False: 1]
switch (1 << i) {
case (1 << 0): // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 0, False: 1]
@@ -153,24 +153,24 @@ void big_switch() { // CHECK: @LINE|{{.*}}big_switch()
case (1 << 1): // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: 1]
break;
- case (1 << 2) ... (1 << 12):// BRCOV: Branch ([[@LINE]]:5): [True: [[C11:11|1]], Folded]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C11]], False: 0]
+ case (1 << 2) ... (1 << 12):// BRCOV: Branch ([[@LINE]]:5): [True: [[#min(C,11)]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,11)]], False: 0]
break;
// The branch for the large case range above appears after the case body.
case (1 << 13): // BRCOV: Branch ([[@LINE]]:5): [True: 1, Folded]
if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: 0]
break;
- case (1 << 14) ... (1 << 28)://BRCOV: Branch ([[@LINE]]:5): [True: [[C15]], Folded]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C15]], False: 0]
+ case (1 << 14) ... (1 << 28)://BRCOV: Branch ([[@LINE]]:5): [True: [[#min(C,15)]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,15)]], False: 0]
break;
// The branch for the large case range above appears after the case body.
case (1 << 29) ... ((1 << 29) + 1):
if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: 1, False: 0]
break;
- default: // BRCOV: Branch ([[@LINE]]:5): [True: [[C2]], Folded]
- if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[C2]], False: 0]
+ default: // BRCOV: Branch ([[@LINE]]:5): [True: [[#min(C,2)]], Folded]
+ if (i) {} // BRCOV: Branch ([[@LINE]]:11): [True: [[#min(C,2)]], False: 0]
break;
}
}
@@ -180,30 +180,30 @@ void big_switch() { // CHECK: @LINE|{{.*}}big_switch()
void boolean_operators() { // CHECK: @LINE|{{.*}}boolean_operators()
int v;
for (int i = 0; i < 100; ++i) {
- v = i % 3 || i; // BRCOV: Branch ([[@LINE]]:9): [True: [[C66:66|1]], False: [[C34:34|1]]]
- // BRCOV: Branch ([[@LINE-1]]:18): [True: [[C33]], False: 1]
- v = i % 3 && i; // BRCOV: Branch ([[@LINE]]:9): [True: [[C66]], False: [[C34]]]
- // BRCOV: Branch ([[@LINE-1]]:18): [True: [[C66]], False: 0]
- v = i % 3 || i % 2 || i; // BRCOV: Branch ([[@LINE]]:9): [True: [[C66]], False: [[C34]]]
- // BRCOV: Branch ([[@LINE-1]]:18): [True: [[C17]], False: [[C17]]]
- v = i % 2 && i % 3 && i; // BRCOV: Branch ([[@LINE-2]]:27): [True: [[C16]], False: 1]
- } // BRCOV: Branch ([[@LINE-1]]:9): [True: [[C50]], False: [[C50]]]
- // BRCOV: Branch ([[@LINE-2]]:18): [True: [[C33]], False: [[C17]]]
-} // BRCOV: Branch ([[@LINE-3]]:27): [True: [[C33]], False: 0]
+ v = i % 3 || i; // BRCOV: Branch ([[@LINE]]:9): [True: [[#min(C,66)]], False: [[#min(C,34)]]]
+ // BRCOV: Branch ([[@LINE-1]]:18): [True: [[#min(C,33)]], False: 1]
+ v = i % 3 && i; // BRCOV: Branch ([[@LINE]]:9): [True: [[#min(C,66)]], False: [[#min(C,34)]]]
+ // BRCOV: Branch ([[@LINE-1]]:18): [True: [[#min(C,66)]], False: 0]
+ v = i % 3 || i % 2 || i; // BRCOV: Branch ([[@LINE]]:9): [True: [[#min(C,66)]], False: [[#min(C,34)]]]
+ // BRCOV: Branch ([[@LINE-1]]:18): [True: [[#min(C,17)]], False: [[#min(C,17)]]]
+ v = i % 2 && i % 3 && i; // BRCOV: Branch ([[@LINE-2]]:27): [True: [[#min(C,16)]], False: 1]
+ } // BRCOV: Branch ([[@LINE-1]]:9): [True: [[#min(C,50)]], False: [[#min(C,50)]]]
+ // BRCOV: Branch ([[@LINE-2]]:18): [True: [[#min(C,33)]], False: [[#min(C,17)]]]
+} // BRCOV: Branch ([[@LINE-3]]:27): [True: [[#min(C,33)]], False: 0]
void boolop_loops() { // CHECK: @LINE|{{.*}}boolop_loops()
int i = 100;
- while (i && i > 50) // BRCOV: Branch ([[@LINE]]:10): [True: [[C51]], False: 0]
- i--; // BRCOV: Branch ([[@LINE-1]]:15): [True: [[C50]], False: 1]
+ while (i && i > 50) // BRCOV: Branch ([[@LINE]]:10): [True: [[#min(C,51)]], False: 0]
+ i--; // BRCOV: Branch ([[@LINE-1]]:15): [True: [[#min(C,50)]], False: 1]
- while ((i % 2) || (i > 0)) // BRCOV: Branch ([[@LINE]]:10): [True: [[C25]], False: [[C26:26|1]]]
- i--; // BRCOV: Branch ([[@LINE-1]]:21): [True: [[C25]], False: 1]
+ while ((i % 2) || (i > 0)) // BRCOV: Branch ([[@LINE]]:10): [True: [[#min(C,25)]], False: [[#min(C,26)]]]
+ i--; // BRCOV: Branch ([[@LINE-1]]:21): [True: [[#min(C,25)]], False: 1]
- for (i = 100; i && i > 50; --i); // BRCOV: Branch ([[@LINE]]:17): [True: [[C51]], False: 0]
- // BRCOV: Branch ([[@LINE-1]]:22): [True: [[C50]], False: 1]
- for (; (i % 2) || (i > 0); --i); // BRCOV: Branch ([[@LINE]]:10): [True: [[C25]], False: [[C26]]]
- // BRCOV: Branch ([[@LINE-1]]:21): [True: [[C25]], False: 1]
+ for (i = 100; i && i > 50; --i); // BRCOV: Branch ([[@LINE]]:17): [True: [[#min(C,51)]], False: 0]
+ // BRCOV: Branch ([[@LINE-1]]:22): [True: [[#min(C,50)]], False: 1]
+ for (; (i % 2) || (i > 0); --i); // BRCOV: Branch ([[@LINE]]:10): [True: [[#min(C,25)]], False: [[#min(C,26)]]]
+ // BRCOV: Branch ([[@LINE-1]]:21): [True: [[#min(C,25)]], False: 1]
}
void conditional_operator() { // CHECK: @LINE|{{.*}}conditional_operator()
@@ -216,7 +216,7 @@ void conditional_operator() { // CHECK: @LINE|{{.*}}conditional_operator()
}
void do_fallthrough() { // CHECK: @LINE|{{.*}}do_fallthrough()
- for (int i = 0; i < 10; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[C10]], False: 1]
+ for (int i = 0; i < 10; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[#min(C,10)]], False: 1]
int j = 0;
do {
// The number of exits out of this do-loop via the break statement
@@ -224,12 +224,12 @@ void do_fallthrough() { // CHECK: @LINE|{{.*}}do_fallthrough()
// fallthrough count). Make sure that does not violate any assertions.
if (i < 8) break;
j++;
- } while (j < 2); // BRCOV: Branch ([[@LINE]]:14): [True: [[C2]], False: [[C2]]]
+ } while (j < 2); // BRCOV: Branch ([[@LINE]]:14): [True: [[#min(C,2)]], False: [[#min(C,2)]]]
}
}
static void static_func() { // CHECK: @LINE|{{.*}}static_func()
- for (int i = 0; i < 10; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[C10]], False: 1]
+ for (int i = 0; i < 10; ++i) {// BRCOV: Branch ([[@LINE]]:19): [True: [[#min(C,10)]], False: 1]
}
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
index 0eaf4c963ef9f4..246b0389aa6008 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
@@ -13,62 +13,62 @@ void func(int a, int b) {
bool b4 = a > b;
bool b5 = a != b;
- bool c = b0 && // BRCOV: Branch ([[@LINE]]:12): [True: [[C3:3|1]], False: 1]
- b1 && // BRCOV: Branch ([[@LINE]]:12): [True: [[C2:2|1]], False: 1]
- b2 && // BRCOV: Branch ([[@LINE]]:12): [True: [[C2]], False: 0]
- b3 && // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: [[C2]]]
+ bool c = b0 && // BRCOV: Branch ([[@LINE]]:12): [True: [[#min(C,3)]], False: 1]
+ b1 && // BRCOV: Branch ([[@LINE]]:12): [True: [[#min(C,2)]], False: 1]
+ b2 && // BRCOV: Branch ([[@LINE]]:12): [True: [[#min(C,2)]], False: 0]
+ b3 && // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: [[#min(C,2)]]]
b4 && // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
b5; // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
- bool d = b0 || // BRCOV: Branch ([[@LINE]]:12): [True: [[C3]], False: 1]
+ bool d = b0 || // BRCOV: Branch ([[@LINE]]:12): [True: [[#min(C,3)]], False: 1]
b1 || // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 1]
b2 || // BRCOV: Branch ([[@LINE]]:12): [True: 1, False: 0]
b3 || // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
b4 || // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
b5; // BRCOV: Branch ([[@LINE]]:12): [True: 0, False: 0]
- bool e = (b0 && // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 1]
- b5) || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
- (b1 && // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: 1]
- b4) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C2]]]
- (b2 && // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 0]
- b3) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C3]]]
- (b3 && // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C3]]]
+ bool e = (b0 && // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,3)]], False: 1]
+ b5) || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[#min(C,2)]]]
+ (b1 && // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,2)]], False: 1]
+ b4) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[#min(C,2)]]]
+ (b2 && // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,3)]], False: 0]
+ b3) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[#min(C,3)]]]
+ (b3 && // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[#min(C,3)]]]
b2) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 0]
- (b4 && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
+ (b4 && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[#min(C,2)]]]
b1) || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 1]
- (b5 && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
+ (b5 && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[#min(C,2)]]]
b0); // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 1]
- bool f = (b0 || // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 1]
+ bool f = (b0 || // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,3)]], False: 1]
b5) && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: 0]
- (b1 || // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: [[C2]]]
+ (b1 || // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,2)]], False: [[#min(C,2)]]]
b4) && // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: 1]
- (b2 || // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 0]
+ (b2 || // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,3)]], False: 0]
b3) && // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: 0]
- (b3 || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[C3]]]
- b2) && // BRCOV: Branch ([[@LINE]]:13): [True: [[C3]], False: 0]
- (b4 || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
- b1) && // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: 0]
- (b5 || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[C2]]]
- b0); // BRCOV: Branch ([[@LINE]]:13): [True: [[C2]], False: 0]
+ (b3 || // BRCOV: Branch ([[@LINE]]:13): [True: 0, False: [[#min(C,3)]]]
+ b2) && // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,3)]], False: 0]
+ (b4 || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[#min(C,2)]]]
+ b1) && // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,2)]], False: 0]
+ (b5 || // BRCOV: Branch ([[@LINE]]:13): [True: 1, False: [[#min(C,2)]]]
+ b0); // BRCOV: Branch ([[@LINE]]:13): [True: [[#min(C,2)]], False: 0]
- if (c) // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: [[C4]]]
+ if (c) // BRCOV: Branch ([[@LINE]]:7): [True: 0, False: [[#min(C,4)]]]
printf("case0\n");
else
printf("case1\n");
- if (d) // BRCOV: Branch ([[@LINE]]:7): [True: [[C4]], False: 0]
+ if (d) // BRCOV: Branch ([[@LINE]]:7): [True: [[#min(C,4)]], False: 0]
printf("case2\n");
else
printf("case3\n");
- if (e) // BRCOV: Branch ([[@LINE]]:7): [True: 1, False: [[C3]]]
+ if (e) // BRCOV: Branch ([[@LINE]]:7): [True: 1, False: [[#min(C,3)]]]
printf("case4\n");
else
printf("case5\n");
- if (f) // BRCOV: Branch ([[@LINE]]:7): [True: [[C3]], False: 1]
+ if (f) // BRCOV: Branch ([[@LINE]]:7): [True: [[#min(C,3)]], False: 1]
printf("case6\n");
else
printf("case7\n");
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
index 5dc5dcefd2c3f2..ad627106f32bd5 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
@@ -5,27 +5,27 @@
#define COND1 (a == b)
#define COND2 (a != b)
#define COND3 (COND1 && COND2)
-#define COND4 (COND3 ? COND2 : COND1) // BRCOV: | Branch ([[@LINE]]:15): [True: 1, False: 2]
+#define COND4 (COND3 ? COND2 : COND1) // BRCOV: | Branch ([[@LINE]]:15): [True: 1, False: [[#min(C,2)]]]
#define MACRO1 COND3
#define MACRO2 MACRO1
#define MACRO3 MACRO2
#include <stdlib.h>
-// CHECK: |{{ +}}[[C3:3|1]]|bool func(
+// CHECK: |{{ +}}[[#min(C,3)]]|bool func(
bool func(int a, int b) {
- bool c = COND1 && COND2; // BRCOV: | | | Branch ([[@LINE-12]]:15): [True: 1, False: [[C2:2|1]]]
+ bool c = COND1 && COND2; // BRCOV: | | | Branch ([[@LINE-12]]:15): [True: 1, False: [[#min(C,2)]]]
// BRCOV: | | | Branch ([[@LINE-12]]:15): [True: 0, False: 1]
- bool d = COND3; // BRCOV: | | | | | Branch ([[@LINE-14]]:15): [True: 1, False: [[C2]]]
+ bool d = COND3; // BRCOV: | | | | | Branch ([[@LINE-14]]:15): [True: 1, False: [[#min(C,2)]]]
// BRCOV: | | | | | Branch ([[@LINE-14]]:15): [True: 0, False: 1]
- bool e = MACRO1; // BRCOV: | | | | | | | Branch ([[@LINE-16]]:15): [True: 1, False: [[C2]]]
+ bool e = MACRO1; // BRCOV: | | | | | | | Branch ([[@LINE-16]]:15): [True: 1, False: [[#min(C,2)]]]
// BRCOV: | | | | | | | Branch ([[@LINE-16]]:15): [True: 0, False: 1]
- bool f = MACRO2; // BRCOV: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 1, False: [[C2]]]
+ bool f = MACRO2; // BRCOV: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 1, False: [[#min(C,2)]]]
// BRCOV: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 0, False: 1]
- bool g = MACRO3; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 1, False: [[C2]]]
+ bool g = MACRO3; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 1, False: [[#min(C,2)]]]
// BRCOV: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 0, False: 1]
return c && d && e && f && g;
- // BRCOV: | Branch ([[@LINE-1]]:10): [True: 0, False: [[C3]]]
+ // BRCOV: | Branch ([[@LINE-1]]:10): [True: 0, False: [[#min(C,3)]]]
// BRCOV: | Branch ([[@LINE-2]]:15): [True: 0, False: 0]
// BRCOV: | Branch ([[@LINE-3]]:20): [True: 0, False: 0]
// BRCOV: | Branch ([[@LINE-4]]:25): [True: 0, False: 0]
@@ -34,11 +34,11 @@ bool func(int a, int b) {
bool func2(int a, int b) {
- bool h = MACRO3 || COND4; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 1, False: [[C2]]]
+ bool h = MACRO3 || COND4; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 1, False: [[#min(C,2)]]]
// BRCOV: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 0, False: 1]
- // BRCOV: | | | | | | | Branch ([[@LINE-34]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | | | | | Branch ([[@LINE-34]]:15): [True: 1, False: [[#min(C,2)]]]
// BRCOV: | | | | | | | Branch ([[@LINE-34]]:15): [True: 0, False: 1]
- // BRCOV: | | | Branch ([[@LINE-33]]:15): [True: 1, False: [[C2]]]
+ // BRCOV: | | | Branch ([[@LINE-33]]:15): [True: 1, False: [[#min(C,2)]]]
return h;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
index b14409f173849d..be780b45f279c5 100644
--- a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
@@ -1,29 +1,30 @@
// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE+2]]' href='#L[[@LINE+2]]'><pre>[[@LINE+2]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE+1]]' href='#L[[@LINE+1]]'><pre>[[@LINE+1]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
-// before any coverage // WHOLE-FILE: [[@LINE]]| |// before
- // FILTER-NOT: [[@LINE-1]]| |// before
+// before any coverage // WHOLE-FILE: [[@LINE]]| |// before
+ // FILTER-NOT: [[@LINE-1]]| |// before
// HTML: <td class='line-number'><a name='L[[@LINE+1]]' href='#L[[@LINE+1]]'><pre>[[@LINE+1]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
-int main() { // TEXT: [[@LINE]]| [[C161:161|1]]|int main(
- int x = 0; // TEXT: [[@LINE]]| [[C161]]| int x
+int main() { // TEXT: [[@LINE]]| [[#C161:min(C,161)]]|int main(
+ int x = 0; // TEXT: [[@LINE]]| [[#C161]]| int x
- if (x) { // TEXT: [[@LINE]]| [[C161]]| if (x)
- x = 0; // TEXT: [[@LINE]]| 0| x = 0
- } else { // TEXT: [[@LINE]]| [[C161]]| } else
- x = 1; // TEXT: [[@LINE]]| [[C161]]| x = 1
- } // TEXT: [[@LINE]]| [[C161]]| }
+ if (x) { // TEXT: [[@LINE]]| [[#C161]]| if (x)
+ x = 0; // TEXT: [[@LINE]]| 0| x = 0
+ } else { // TEXT: [[@LINE]]| [[#C161]]| } else
+ x = 1; // TEXT: [[@LINE]]| [[#C161]]| x = 1
+ } // TEXT: [[@LINE]]| [[#C161]]| }
- for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| [[C16K2:16\.2k|161]]| for (
- x = 1; // TEXT: [[@LINE]]| [[C16K1:16\.1k|161]]| x = 1
- } // TEXT: [[@LINE]]| [[C16K1]]| }
+ for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| [[C16K2]]| for (
+ x = 1; // TEXT: [[@LINE]]| [[C16K1]]| x = 1
+ } // TEXT: [[@LINE]]| [[C16K1]]| }
- x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| [[C161]]| x =
- x = x > 10 ? // TEXT: [[@LINE]]| [[C161]]| x =
- x - 1: // TEXT: [[@LINE]]| 0| x
- x + 1; // TEXT: [[@LINE]]| [[C161]]| x
+ x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| [[#C161]]| x =
+ x = x > 10 ? // TEXT: [[@LINE]]| [[#C161]]| x =
+ x - 1: // TEXT: [[@LINE]]| 0| x
+ x + 1; // TEXT: [[@LINE]]| [[#C161]]| x
- return 0; // TEXT: [[@LINE]]| [[C161]]| return
-} // TEXT: [[@LINE]]| [[C161]]|}
-// after coverage // WHOLE-FILE: [[@LINE]]| |// after
- // FILTER-NOT: [[@LINE-1]]| |// after
-// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-2]]' href='#L[[@LINE-2]]'><pre>[[@LINE-2]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
-// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-3]]' href='#L[[@LINE-3]]'><pre>[[@LINE-3]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
+ return 0; // TEXT: [[@LINE]]| [[#C161]]| return
+} // TEXT: [[@LINE]]| [[#C161]]|}
+// after coverage // WHOLE-FILE: [[@LINE]]| |// after
+ // FILTER-NOT: [[@LINE-1]]| |// after
+// HTML-BINARY-NOT: <td class='covered-line'><pre>16
+// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-3]]' href='#L[[@LINE-3]]'><pre>[[@LINE-3]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
+// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-4]]' href='#L[[@LINE-4]]'><pre>[[@LINE-4]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
diff --git a/llvm/test/tools/llvm-cov/branch-c-general.test b/llvm/test/tools/llvm-cov/branch-c-general.test
index 3d0b7ee563222d..3c163bf6de45cc 100644
--- a/llvm/test/tools/llvm-cov/branch-c-general.test
+++ b/llvm/test/tools/llvm-cov/branch-c-general.test
@@ -167,4 +167,4 @@
// RUN: yaml2obj %S/Inputs/branch-c-general-single.yaml -o %t.o
// RUN: llvm-profdata merge %S/Inputs/branch-c-general-single.proftext -o %t.profdata
-// RUN: llvm-cov show --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs %S/Inputs/branch-c-general.c | FileCheck %S/Inputs/branch-c-general.c
+// RUN: llvm-cov show --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs %S/Inputs/branch-c-general.c | FileCheck %S/Inputs/branch-c-general.c -D#C=1
diff --git a/llvm/test/tools/llvm-cov/branch-logical-mixed.test b/llvm/test/tools/llvm-cov/branch-logical-mixed.test
index b03cabeb01855b..2dfbbc53b93cf4 100644
--- a/llvm/test/tools/llvm-cov/branch-logical-mixed.test
+++ b/llvm/test/tools/llvm-cov/branch-logical-mixed.test
@@ -1,11 +1,11 @@
// RUN: llvm-profdata merge %S/Inputs/branch-logical-mixed.proftext -o %t.profdata
-// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp -check-prefixes=CHECK,BRCOV
+// RUN: llvm-cov show --show-branches=count %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp -D#C=999
// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-logical-mixed.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-logical-mixed.cpp
| FileCheck %s -check-prefix=REPORT
// RUN: yaml2obj %S/Inputs/branch-logical-mixed-single.yaml -o %t.o
// RUN: llvm-profdata merge %S/Inputs/branch-logical-mixed-single.proftext -o %t.profdata
-// RUN: llvm-cov show --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp
+// RUN: llvm-cov show --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-logical-mixed.cpp -D#C=1
// RUN: llvm-cov report --show-branch-summary %t.o -instr-profile %t.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/branch-logical-mixed.cpp
| FileCheck %s -check-prefix=REPORT
diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test
index a4790afc534228..0a94e636082271 100644
--- a/llvm/test/tools/llvm-cov/branch-macros.test
+++ b/llvm/test/tools/llvm-cov/branch-macros.test
@@ -1,10 +1,10 @@
// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
-// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -check-prefixes=CHECK,BRCOV
+// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -check-prefixes=CHECK,BRCOV -D#C=999
// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s -check-prefix=REPORT
// RUN: yaml2obj %S/Inputs/branch-macros-single.yaml -o %t.o
// RUN: llvm-profdata merge %S/Inputs/branch-macros-single.proftext -o %t.profdata
-// RUN: llvm-cov show --show-expansions --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp
+// RUN: llvm-cov show --show-expansions --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -D#C=999
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
index 1c1e894922827f..63a49341e6c171 100644
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
@@ -2,14 +2,14 @@
// RUN: rm -rf %t.dir
// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE %S/Inputs/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=999 -DC16K2=16.2k -DC16K1=16.1k %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER -D#C=999 -DC16K2=16.2k -DC16K1=16.1k %S/Inputs/showLineExecutionCounts.cpp
// Test -output-dir.
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir/show -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir/show.filtered -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
-// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -input-file %t.dir/show/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
-// RUN: FileCheck -check-prefixes=TEXT,FILTER -input-file %t.dir/show.filtered/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=999 -DC16K2=16.2k -DC16K1=16.1k -input-file %t.dir/show/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=TEXT,FILTER -D#C=999 -DC16K2=16.2k -DC16K1=16.1k -input-file %t.dir/show.filtered/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
//
// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
// RUN: not grep '"name":"main"' %t.export-summary.json
@@ -46,5 +46,5 @@
// RUN: yaml2obj %S/Inputs/showLineExecutionCounts-single.yaml -o %t.o
// RUN: llvm-profdata merge %S/Inputs/showLineExecutionCounts-single.proftext -o %t.profdata
-// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE %S/Inputs/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=161 -DC16K2=161 -DC16K1=161 %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER -D#C=161 -DC16K2=161 -DC16K1=161 %S/Inputs/showLineExecutionCounts.cpp
>From 805e9a93093121a3cde6c569b0247be6f68601fb Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 21 Dec 2024 17:32:28 +0900
Subject: [PATCH 13/30] llvm-cov: Introduce `--binary-counters`
---
.../tools/llvm-cov/Inputs/branch-macros.cpp | 52 +++++++++++++
.../Inputs/showLineExecutionCounts.cpp | 30 ++++++++
llvm/test/tools/llvm-cov/branch-macros.cpp | 60 ---------------
llvm/test/tools/llvm-cov/branch-macros.test | 12 +++
.../llvm-cov/showLineExecutionCounts.cpp | 73 -------------------
.../llvm-cov/showLineExecutionCounts.test | 46 ++++++++++++
llvm/tools/llvm-cov/CodeCoverage.cpp | 6 ++
llvm/tools/llvm-cov/CoverageViewOptions.h | 1 +
llvm/tools/llvm-cov/SourceCoverageView.h | 9 ++-
.../tools/llvm-cov/SourceCoverageViewHTML.cpp | 15 ++--
.../tools/llvm-cov/SourceCoverageViewText.cpp | 6 +-
11 files changed, 167 insertions(+), 143 deletions(-)
create mode 100644 llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
create mode 100644 llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
delete mode 100644 llvm/test/tools/llvm-cov/branch-macros.cpp
create mode 100644 llvm/test/tools/llvm-cov/branch-macros.test
delete mode 100644 llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
create mode 100644 llvm/test/tools/llvm-cov/showLineExecutionCounts.test
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
new file mode 100644
index 00000000000000..ad627106f32bd5
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-macros.cpp
@@ -0,0 +1,52 @@
+
+
+
+
+#define COND1 (a == b)
+#define COND2 (a != b)
+#define COND3 (COND1 && COND2)
+#define COND4 (COND3 ? COND2 : COND1) // BRCOV: | Branch ([[@LINE]]:15): [True: 1, False: [[#min(C,2)]]]
+#define MACRO1 COND3
+#define MACRO2 MACRO1
+#define MACRO3 MACRO2
+
+#include <stdlib.h>
+
+// CHECK: |{{ +}}[[#min(C,3)]]|bool func(
+bool func(int a, int b) {
+ bool c = COND1 && COND2; // BRCOV: | | | Branch ([[@LINE-12]]:15): [True: 1, False: [[#min(C,2)]]]
+ // BRCOV: | | | Branch ([[@LINE-12]]:15): [True: 0, False: 1]
+ bool d = COND3; // BRCOV: | | | | | Branch ([[@LINE-14]]:15): [True: 1, False: [[#min(C,2)]]]
+ // BRCOV: | | | | | Branch ([[@LINE-14]]:15): [True: 0, False: 1]
+ bool e = MACRO1; // BRCOV: | | | | | | | Branch ([[@LINE-16]]:15): [True: 1, False: [[#min(C,2)]]]
+ // BRCOV: | | | | | | | Branch ([[@LINE-16]]:15): [True: 0, False: 1]
+ bool f = MACRO2; // BRCOV: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 1, False: [[#min(C,2)]]]
+ // BRCOV: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 0, False: 1]
+ bool g = MACRO3; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 1, False: [[#min(C,2)]]]
+ // BRCOV: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 0, False: 1]
+ return c && d && e && f && g;
+ // BRCOV: | Branch ([[@LINE-1]]:10): [True: 0, False: [[#min(C,3)]]]
+ // BRCOV: | Branch ([[@LINE-2]]:15): [True: 0, False: 0]
+ // BRCOV: | Branch ([[@LINE-3]]:20): [True: 0, False: 0]
+ // BRCOV: | Branch ([[@LINE-4]]:25): [True: 0, False: 0]
+ // BRCOV: | Branch ([[@LINE-5]]:30): [True: 0, False: 0]
+}
+
+
+bool func2(int a, int b) {
+ bool h = MACRO3 || COND4; // BRCOV: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 1, False: [[#min(C,2)]]]
+ // BRCOV: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 0, False: 1]
+ // BRCOV: | | | | | | | Branch ([[@LINE-34]]:15): [True: 1, False: [[#min(C,2)]]]
+ // BRCOV: | | | | | | | Branch ([[@LINE-34]]:15): [True: 0, False: 1]
+ // BRCOV: | | | Branch ([[@LINE-33]]:15): [True: 1, False: [[#min(C,2)]]]
+ return h;
+}
+
+
+int main(int argc, char *argv[])
+{
+ func(atoi(argv[1]), atoi(argv[2]));
+ func2(atoi(argv[1]), atoi(argv[2]));
+ (void)0;
+ return 0;
+}
diff --git a/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
new file mode 100644
index 00000000000000..be780b45f279c5
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/showLineExecutionCounts.cpp
@@ -0,0 +1,30 @@
+// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE+2]]' href='#L[[@LINE+2]]'><pre>[[@LINE+2]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
+// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE+1]]' href='#L[[@LINE+1]]'><pre>[[@LINE+1]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
+// before any coverage // WHOLE-FILE: [[@LINE]]| |// before
+ // FILTER-NOT: [[@LINE-1]]| |// before
+// HTML: <td class='line-number'><a name='L[[@LINE+1]]' href='#L[[@LINE+1]]'><pre>[[@LINE+1]]</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
+int main() { // TEXT: [[@LINE]]| [[#C161:min(C,161)]]|int main(
+ int x = 0; // TEXT: [[@LINE]]| [[#C161]]| int x
+
+ if (x) { // TEXT: [[@LINE]]| [[#C161]]| if (x)
+ x = 0; // TEXT: [[@LINE]]| 0| x = 0
+ } else { // TEXT: [[@LINE]]| [[#C161]]| } else
+ x = 1; // TEXT: [[@LINE]]| [[#C161]]| x = 1
+ } // TEXT: [[@LINE]]| [[#C161]]| }
+
+ for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| [[C16K2]]| for (
+ x = 1; // TEXT: [[@LINE]]| [[C16K1]]| x = 1
+ } // TEXT: [[@LINE]]| [[C16K1]]| }
+
+ x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| [[#C161]]| x =
+ x = x > 10 ? // TEXT: [[@LINE]]| [[#C161]]| x =
+ x - 1: // TEXT: [[@LINE]]| 0| x
+ x + 1; // TEXT: [[@LINE]]| [[#C161]]| x
+
+ return 0; // TEXT: [[@LINE]]| [[#C161]]| return
+} // TEXT: [[@LINE]]| [[#C161]]|}
+// after coverage // WHOLE-FILE: [[@LINE]]| |// after
+ // FILTER-NOT: [[@LINE-1]]| |// after
+// HTML-BINARY-NOT: <td class='covered-line'><pre>16
+// HTML-WHOLE-FILE: <td class='line-number'><a name='L[[@LINE-3]]' href='#L[[@LINE-3]]'><pre>[[@LINE-3]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
+// HTML-FILTER-NOT: <td class='line-number'><a name='L[[@LINE-4]]' href='#L[[@LINE-4]]'><pre>[[@LINE-4]]</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
diff --git a/llvm/test/tools/llvm-cov/branch-macros.cpp b/llvm/test/tools/llvm-cov/branch-macros.cpp
deleted file mode 100644
index 7f3d1e8bffb82a..00000000000000
--- a/llvm/test/tools/llvm-cov/branch-macros.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
-// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s
-// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S %s | FileCheck %s -check-prefix=REPORT
-
-#define COND1 (a == b)
-#define COND2 (a != b)
-#define COND3 (COND1 && COND2)
-#define COND4 (COND3 ? COND2 : COND1) // CHECK: | Branch ([[@LINE]]:15): [True: 1, False: 2]
-#define MACRO1 COND3
-#define MACRO2 MACRO1
-#define MACRO3 MACRO2
-
-#include <stdlib.h>
-
-
-bool func(int a, int b) {
- bool c = COND1 && COND2; // CHECK: | | | Branch ([[@LINE-12]]:15): [True: 1, False: 2]
- // CHECK: | | | Branch ([[@LINE-12]]:15): [True: 0, False: 1]
- bool d = COND3; // CHECK: | | | | | Branch ([[@LINE-14]]:15): [True: 1, False: 2]
- // CHECK: | | | | | Branch ([[@LINE-14]]:15): [True: 0, False: 1]
- bool e = MACRO1; // CHECK: | | | | | | | Branch ([[@LINE-16]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | Branch ([[@LINE-16]]:15): [True: 0, False: 1]
- bool f = MACRO2; // CHECK: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | | | Branch ([[@LINE-18]]:15): [True: 0, False: 1]
- bool g = MACRO3; // CHECK: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | | | | | Branch ([[@LINE-20]]:15): [True: 0, False: 1]
- return c && d && e && f && g;
- // CHECK: | Branch ([[@LINE-1]]:10): [True: 0, False: 3]
- // CHECK: | Branch ([[@LINE-2]]:15): [True: 0, False: 0]
- // CHECK: | Branch ([[@LINE-3]]:20): [True: 0, False: 0]
- // CHECK: | Branch ([[@LINE-4]]:25): [True: 0, False: 0]
- // CHECK: | Branch ([[@LINE-5]]:30): [True: 0, False: 0]
-}
-
-
-bool func2(int a, int b) {
- bool h = MACRO3 || COND4; // CHECK: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | | | | | Branch ([[@LINE-32]]:15): [True: 0, False: 1]
- // CHECK: | | | | | | | Branch ([[@LINE-34]]:15): [True: 1, False: 2]
- // CHECK: | | | | | | | Branch ([[@LINE-34]]:15): [True: 0, False: 1]
- // CHECK: | | | Branch ([[@LINE-33]]:15): [True: 1, False: 2]
- return h;
-}
-
-extern "C" { extern void __llvm_profile_write_file(void); }
-int main(int argc, char *argv[])
-{
- func(atoi(argv[1]), atoi(argv[2]));
- func2(atoi(argv[1]), atoi(argv[2]));
- __llvm_profile_write_file();
- return 0;
-}
-
-// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
-// REPORT-NEXT: ---
-// REPORT-NEXT: _Z4funcii 28 4 85.71% 18 0 100.00% 30 14 53.33%
-// REPORT-NEXT: _Z5func2ii 13 1 92.31% 8 0 100.00% 10 2 80.00%
-// REPORT-NEXT: main 1 0 100.00% 6 0 100.00% 0 0 0.00%
-// REPORT-NEXT: ---
-// REPORT-NEXT: TOTAL 42 5 88.10% 32 0 100.00% 40 16 60.00%
diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test
new file mode 100644
index 00000000000000..547a79ff941241
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/branch-macros.test
@@ -0,0 +1,12 @@
+// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
+// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -check-prefixes=CHECK,BRCOV -D#C=999
+// RUN: llvm-cov show --binary-counters=true --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -check-prefixes=CHECK,BRCOV -D#C=1
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s -check-prefix=REPORT
+
+// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
+// REPORT-NEXT: ---
+// REPORT-NEXT: _Z4funcii 28 4 85.71% 18 0 100.00% 30 14 53.33%
+// REPORT-NEXT: _Z5func2ii 13 1 92.31% 8 0 100.00% 10 2 80.00%
+// REPORT-NEXT: main 1 0 100.00% 6 0 100.00% 0 0 0.00%
+// REPORT-NEXT: ---
+// REPORT-NEXT: TOTAL 42 5 88.10% 32 0 100.00% 40 16 60.00%
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
deleted file mode 100644
index f72a9978b8a734..00000000000000
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-// Basic handling of line counts.
-// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
-
-// before any coverage // WHOLE-FILE: [[@LINE]]| |// before
- // FILTER-NOT: [[@LINE-1]]| |// before
-int main() { // TEXT: [[@LINE]]| 161|int main(
- int x = 0; // TEXT: [[@LINE]]| 161| int x
- // TEXT: [[@LINE]]| 161|
- if (x) { // TEXT: [[@LINE]]| 161| if (x)
- x = 0; // TEXT: [[@LINE]]| 0| x = 0
- } else { // TEXT: [[@LINE]]| 161| } else
- x = 1; // TEXT: [[@LINE]]| 161| x = 1
- } // TEXT: [[@LINE]]| 161| }
- // TEXT: [[@LINE]]| 161|
- for (int i = 0; i < 100; ++i) { // TEXT: [[@LINE]]| 16.2k| for (
- x = 1; // TEXT: [[@LINE]]| 16.1k| x = 1
- } // TEXT: [[@LINE]]| 16.1k| }
- // TEXT: [[@LINE]]| 161|
- x = x < 10 ? x + 1 : x - 1; // TEXT: [[@LINE]]| 161| x =
- x = x > 10 ? // TEXT: [[@LINE]]| 161| x =
- x - 1: // TEXT: [[@LINE]]| 0| x
- x + 1; // TEXT: [[@LINE]]| 161| x
- // TEXT: [[@LINE]]| 161|
- return 0; // TEXT: [[@LINE]]| 161| return
-} // TEXT: [[@LINE]]| 161|}
-// after coverage // WHOLE-FILE: [[@LINE]]| |// after
- // FILTER-NOT: [[@LINE-1]]| |// after
-
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck -check-prefixes=TEXT,WHOLE-FILE %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s | FileCheck -check-prefixes=TEXT,FILTER %s
-
-// Test -output-dir.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
-// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
-// RUN: FileCheck -check-prefixes=TEXT,FILTER -input-file %t.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
-//
-// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
-// RUN: not grep '"name":"main"' %t.export-summary.json
-//
-// Test html output.
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %s
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.html.filtered.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S -name=main %s
-// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.html.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
-// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.html.filtered.dir/coverage/tmp/showLineExecutionCounts.cpp.html %s
-//
-// HTML-WHOLE-FILE: <td class='line-number'><a name='L4' href='#L4'><pre>4</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
-// HTML-FILTER-NOT: <td class='line-number'><a name='L4' href='#L4'><pre>4</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// before
-// HTML: <td class='line-number'><a name='L6' href='#L6'><pre>6</pre></a></td><td class='covered-line'><pre>161</pre></td><td class='code'><pre>int main() {
-// HTML-WHOLE-FILE: <td class='line-number'><a name='L26' href='#L26'><pre>26</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
-// HTML-FILTER-NOT: <td class='line-number'><a name='L26' href='#L26'><pre>26</pre></a></td><td class='skipped-line'></td><td class='code'><pre>// after
-//
-// Test index creation.
-// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/index.txt %s
-// TEXT-INDEX: Filename
-// TEXT-INDEX-NEXT: ---
-// TEXT-INDEX-NEXT: {{.*}}showLineExecutionCounts.cpp
-//
-// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
-// HTML-INDEX-LABEL: <table>
-// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
-// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
-// HTML-INDEX: <a href='coverage{{.*}}showLineExecutionCounts.cpp.html'{{.*}}showLineExecutionCounts.cpp</a>
-// HTML-INDEX: <td class='column-entry-green'>
-// HTML-INDEX: 100.00% (1/1)
-// HTML-INDEX: <td class='column-entry-yellow'>
-// HTML-INDEX: 90.00% (18/20)
-// HTML-INDEX: <td class='column-entry-red'>
-// HTML-INDEX: 72.73% (8/11)
-// HTML-INDEX: <tr class='light-row-bold'>
-// HTML-INDEX: Totals
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
new file mode 100644
index 00000000000000..3c24ec2094c974
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
@@ -0,0 +1,46 @@
+// Basic handling of line counts.
+// RUN: rm -rf %t.dir
+// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
+
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=999 -DC16K2=16.2k -DC16K1=16.1k %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -binary-counters=true -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=1 -DC16K2=1 -DC16K1=1 %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER -D#C=999 -DC16K2=16.2k -DC16K1=16.1k %S/Inputs/showLineExecutionCounts.cpp
+
+// Test -output-dir.
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir/show -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir/show.filtered -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
+// RUN: FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=999 -DC16K2=16.2k -DC16K1=16.1k -input-file %t.dir/show/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=TEXT,FILTER -D#C=999 -DC16K2=16.2k -DC16K1=16.1k -input-file %t.dir/show.filtered/coverage/tmp/showLineExecutionCounts.cpp.txt %S/Inputs/showLineExecutionCounts.cpp
+//
+// RUN: llvm-cov export %S/Inputs/lineExecutionCounts.covmapping -instr-profile %t.profdata 2>/dev/null -summary-only > %t.export-summary.json
+// RUN: not grep '"name":"main"' %t.export-summary.json
+//
+// Test html output.
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.dir/html -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.dir/html.binary -binary-counters=true -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -format html -o %t.dir/html.filtered -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs -name=main
+// RUN: FileCheck -check-prefixes=HTML,HTML-WHOLE-FILE -input-file %t.dir/html/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=HTML-BINARY,HTML-WHOLE-FILE -input-file %t.dir/html.binary/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
+// RUN: FileCheck -check-prefixes=HTML,HTML-FILTER -input-file %t.dir/html.filtered/coverage/tmp/showLineExecutionCounts.cpp.html %S/Inputs/showLineExecutionCounts.cpp
+//
+// Test index creation.
+// RUN: FileCheck -check-prefix=TEXT-INDEX -input-file %t.dir/show/index.txt %s
+// TEXT-INDEX: Filename
+// TEXT-INDEX-NEXT: ---
+// TEXT-INDEX-NEXT: {{.*}}showLineExecutionCounts.cpp
+//
+// RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.dir/html/index.html %s
+// HTML-INDEX-LABEL: <table>
+// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
+// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
+// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
+// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
+// HTML-INDEX: <a href='coverage{{.*}}showLineExecutionCounts.cpp.html'{{.*}}showLineExecutionCounts.cpp</a>
+// HTML-INDEX: <td class='column-entry-green'>
+// HTML-INDEX: 100.00% (1/1)
+// HTML-INDEX: <td class='column-entry-yellow'>
+// HTML-INDEX: 90.00% (18/20)
+// HTML-INDEX: <td class='column-entry-red'>
+// HTML-INDEX: 72.73% (8/11)
+// HTML-INDEX: <tr class='light-row-bold'>
+// HTML-INDEX: Totals
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 5db5c2e0235419..0e8360a4ac6ed9 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -1023,6 +1023,11 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"),
cl::aliasopt(ShowOutputDirectory));
+ cl::opt<bool> BinaryCounters(
+ "binary-counters", cl::Optional,
+ cl::desc("Show 1/0 instead of actual counter values."),
+ cl::cat(ViewCategory));
+
cl::opt<uint32_t> TabSize(
"tab-size", cl::init(2),
cl::desc(
@@ -1100,6 +1105,7 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
ViewOpts.ShowDirectoryCoverage = ShowDirectoryCoverage;
ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
+ ViewOpts.BinaryCounters = BinaryCounters;
ViewOpts.TabSize = TabSize;
ViewOpts.ProjectTitle = ProjectTitle;
diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h
index 6925cffd8246d2..b8d1a8b2d7c9b5 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -45,6 +45,7 @@ struct CoverageViewOptions {
bool SkipExpansions;
bool SkipFunctions;
bool SkipBranches;
+ bool BinaryCounters;
OutputFormat Format;
BranchOutputType ShowBranches;
std::string ShowOutputDirectory;
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h
index 2b1570d399dd0b..9b72ca03c6d7ff 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -180,6 +180,8 @@ class SourceCoverageView {
/// on display.
std::vector<InstantiationView> InstantiationSubViews;
+ bool BinaryCounters;
+
/// Get the first uncovered line number for the source file.
unsigned getFirstUncoveredLineNo();
@@ -266,6 +268,10 @@ class SourceCoverageView {
/// digits.
static std::string formatCount(uint64_t N);
+ uint64_t Count1(uint64_t N) const { return (N && BinaryCounters ? 1 : N); }
+
+ std::string formatCount1(uint64_t N) const { return formatCount(Count1(N)); }
+
/// Check if region marker output is expected for a line.
bool shouldRenderRegionMarkers(const LineCoverageStats &LCS) const;
@@ -276,7 +282,8 @@ class SourceCoverageView {
const CoverageViewOptions &Options,
CoverageData &&CoverageInfo)
: SourceName(SourceName), File(File), Options(Options),
- CoverageInfo(std::move(CoverageInfo)) {}
+ CoverageInfo(std::move(CoverageInfo)),
+ BinaryCounters(Options.BinaryCounters) {}
public:
static std::unique_ptr<SourceCoverageView>
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index e2be576b93cdaf..f3aa7e801597c9 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -1019,19 +1019,22 @@ void SourceCoverageViewHTML::renderLine(raw_ostream &OS, LineRef L,
// Just consider the segments which start *and* end on this line.
for (unsigned I = 0, E = Segments.size() - 1; I < E; ++I) {
const auto *CurSeg = Segments[I];
+ auto CurSegCount = Count1(CurSeg->Count);
+ auto LCSCount = Count1(LCS.getExecutionCount());
if (!CurSeg->IsRegionEntry)
continue;
- if (CurSeg->Count == LCS.getExecutionCount())
+ if (CurSegCount == LCSCount)
continue;
Snippets[I + 1] =
- tag("div", Snippets[I + 1] + tag("span", formatCount(CurSeg->Count),
- "tooltip-content"),
+ tag("div",
+ Snippets[I + 1] +
+ tag("span", formatCount(CurSegCount), "tooltip-content"),
"tooltip");
if (getOptions().Debug)
errs() << "Marker at " << CurSeg->Line << ":" << CurSeg->Col << " = "
- << formatCount(CurSeg->Count) << "\n";
+ << formatCount(CurSegCount) << "\n";
}
}
@@ -1051,7 +1054,7 @@ void SourceCoverageViewHTML::renderLineCoverageColumn(
raw_ostream &OS, const LineCoverageStats &Line) {
std::string Count;
if (Line.isMapped())
- Count = tag("pre", formatCount(Line.getExecutionCount()));
+ Count = tag("pre", formatCount1(Line.getExecutionCount()));
std::string CoverageClass =
(Line.getExecutionCount() > 0)
? "covered-line"
@@ -1106,7 +1109,7 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV,
OS << tag("span", Label, (Count ? "None" : "red branch")) << ": ";
if (getOptions().ShowBranchCounts)
- OS << tag("span", formatCount(Count),
+ OS << tag("span", formatCount1(Count),
(Count ? "covered-line" : "uncovered-line"));
else
OS << format("%0.2f", (Total != 0 ? 100.0 * Count / Total : 0.0)) << "%";
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index 63f8248e3387ba..f0c366e45c2c92 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -216,7 +216,7 @@ void SourceCoverageViewText::renderLineCoverageColumn(
OS.indent(LineCoverageColumnWidth) << '|';
return;
}
- std::string C = formatCount(Line.getExecutionCount());
+ std::string C = formatCount1(Line.getExecutionCount());
OS.indent(LineCoverageColumnWidth - C.size());
colored_ostream(OS, raw_ostream::MAGENTA,
Line.hasMultipleRegions() && getOptions().Colors)
@@ -263,7 +263,7 @@ void SourceCoverageViewText::renderRegionMarkers(raw_ostream &OS,
if (getOptions().Debug)
errs() << "Marker at " << S->Line << ":" << S->Col << " = "
- << formatCount(S->Count) << "\n";
+ << formatCount1(S->Count) << "\n";
}
OS << '\n';
}
@@ -307,7 +307,7 @@ void SourceCoverageViewText::renderBranchView(raw_ostream &OS, BranchView &BRV,
<< Label;
if (getOptions().ShowBranchCounts)
- OS << ": " << formatCount(Count);
+ OS << ": " << formatCount1(Count);
else
OS << ": " << format("%0.2f", (Total != 0 ? 100.0 * Count / Total : 0.0))
<< "%";
>From 5b6c0b02c00fb861877e8a35cdf9842b76e33f2c Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sat, 21 Dec 2024 17:53:19 +0900
Subject: [PATCH 14/30] LLVMCoverage: Unify getCoverageForFile and
getCoverageForFunction
---
.../ProfileData/Coverage/CoverageMapping.h | 3 +
.../ProfileData/Coverage/CoverageMapping.cpp | 77 ++++++++++---------
2 files changed, 43 insertions(+), 37 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 42da188fef34ee..be902a20efc47e 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -889,6 +889,7 @@ class InstantiationGroup {
class CoverageData {
friend class CoverageMapping;
+protected:
std::string Filename;
std::vector<CoverageSegment> Segments;
std::vector<ExpansionRecord> Expansions;
@@ -900,6 +901,8 @@ class CoverageData {
CoverageData(StringRef Filename) : Filename(Filename) {}
+ CoverageData(CoverageData &&RHS) = default;
+
/// Get the name of the file this data covers.
StringRef getFilename() const { return Filename; }
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index d51448567539f2..c6756fafb268a2 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -1343,6 +1343,36 @@ class SegmentBuilder {
}
};
+struct MergeableCoverageData : public CoverageData {
+ std::vector<CountedRegion> CodeRegions;
+
+ MergeableCoverageData(StringRef Filename) : CoverageData(Filename) {}
+
+ void addFunctionRegions(
+ const FunctionRecord &Function,
+ std::function<bool(const CounterMappingRegion &CR)> shouldProcess,
+ std::function<bool(const CountedRegion &CR)> shouldExpand) {
+ for (const auto &CR : Function.CountedRegions)
+ if (shouldProcess(CR)) {
+ CodeRegions.push_back(CR);
+ if (shouldExpand(CR))
+ Expansions.emplace_back(CR, Function);
+ }
+ // Capture branch regions specific to the function (excluding expansions).
+ for (const auto &CR : Function.CountedBranchRegions)
+ if (shouldProcess(CR))
+ BranchRegions.push_back(CR);
+ // Capture MCDC records specific to the function.
+ for (const auto &MR : Function.MCDCRecords)
+ if (shouldProcess(MR.getDecisionRegion()))
+ MCDCRecords.push_back(MR);
+ }
+
+ CoverageData buildSegments() {
+ Segments = SegmentBuilder::buildSegments(CodeRegions);
+ return CoverageData(std::move(*this));
+ }
+};
} // end anonymous namespace
std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const {
@@ -1393,8 +1423,7 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
}
CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
- CoverageData FileCoverage(Filename);
- std::vector<CountedRegion> Regions;
+ MergeableCoverageData FileCoverage(Filename);
// Look up the function records in the given file. Due to hash collisions on
// the filename, we may get back some records that are not in the file.
@@ -1404,26 +1433,14 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
const FunctionRecord &Function = Functions[RecordIndex];
auto MainFileID = findMainViewFileID(Filename, Function);
auto FileIDs = gatherFileIDs(Filename, Function);
- for (const auto &CR : Function.CountedRegions)
- if (FileIDs.test(CR.FileID)) {
- Regions.push_back(CR);
- if (MainFileID && isExpansion(CR, *MainFileID))
- FileCoverage.Expansions.emplace_back(CR, Function);
- }
- // Capture branch regions specific to the function (excluding expansions).
- for (const auto &CR : Function.CountedBranchRegions)
- if (FileIDs.test(CR.FileID))
- FileCoverage.BranchRegions.push_back(CR);
- // Capture MCDC records specific to the function.
- for (const auto &MR : Function.MCDCRecords)
- if (FileIDs.test(MR.getDecisionRegion().FileID))
- FileCoverage.MCDCRecords.push_back(MR);
+ FileCoverage.addFunctionRegions(
+ Function, [&](auto &CR) { return FileIDs.test(CR.FileID); },
+ [&](auto &CR) { return (MainFileID && isExpansion(CR, *MainFileID)); });
}
LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
- FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
- return FileCoverage;
+ return FileCoverage.buildSegments();
}
std::vector<InstantiationGroup>
@@ -1457,29 +1474,15 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
if (!MainFileID)
return CoverageData();
- CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
- std::vector<CountedRegion> Regions;
- for (const auto &CR : Function.CountedRegions)
- if (CR.FileID == *MainFileID) {
- Regions.push_back(CR);
- if (isExpansion(CR, *MainFileID))
- FunctionCoverage.Expansions.emplace_back(CR, Function);
- }
- // Capture branch regions specific to the function (excluding expansions).
- for (const auto &CR : Function.CountedBranchRegions)
- if (CR.FileID == *MainFileID)
- FunctionCoverage.BranchRegions.push_back(CR);
-
- // Capture MCDC records specific to the function.
- for (const auto &MR : Function.MCDCRecords)
- if (MR.getDecisionRegion().FileID == *MainFileID)
- FunctionCoverage.MCDCRecords.push_back(MR);
+ MergeableCoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
+ FunctionCoverage.addFunctionRegions(
+ Function, [&](auto &CR) { return (CR.FileID == *MainFileID); },
+ [&](auto &CR) { return isExpansion(CR, *MainFileID); });
LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
<< "\n");
- FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
- return FunctionCoverage;
+ return FunctionCoverage.buildSegments();
}
CoverageData CoverageMapping::getCoverageForExpansion(
>From 24457a7236f5dc76e49c78817b5a0de6ce4f7f93 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 22 Dec 2024 00:42:02 +0900
Subject: [PATCH 15/30] Update tests
---
llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp | 2 +-
llvm/test/tools/llvm-cov/branch-macros.test | 2 +-
llvm/test/tools/llvm-cov/showLineExecutionCounts.test | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
index 246b0389aa6008..cce61784f9c48c 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-logical-mixed.cpp
@@ -4,7 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
-// CHECK: |{{ +}}[[C4:4|1]]|void func(
+// CHECK: | [[#min(C,4)]]|void func(
void func(int a, int b) {
bool b0 = a <= b;
bool b1 = a == b;
diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test
index 0a94e636082271..e4bd14ec14f16c 100644
--- a/llvm/test/tools/llvm-cov/branch-macros.test
+++ b/llvm/test/tools/llvm-cov/branch-macros.test
@@ -4,7 +4,7 @@
// RUN: yaml2obj %S/Inputs/branch-macros-single.yaml -o %t.o
// RUN: llvm-profdata merge %S/Inputs/branch-macros-single.proftext -o %t.profdata
-// RUN: llvm-cov show --show-expansions --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -D#C=999
+// RUN: llvm-cov show --show-expansions --show-branches=count %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -D#C=1
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
index 63a49341e6c171..4f505f9648eb88 100644
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.test
@@ -46,5 +46,5 @@
// RUN: yaml2obj %S/Inputs/showLineExecutionCounts-single.yaml -o %t.o
// RUN: llvm-profdata merge %S/Inputs/showLineExecutionCounts-single.proftext -o %t.profdata
-// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=161 -DC16K2=161 -DC16K1=161 %S/Inputs/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER -D#C=161 -DC16K2=161 -DC16K1=161 %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck -check-prefixes=TEXT,WHOLE-FILE -D#C=1 -DC16K2=1 -DC16K1=1 %S/Inputs/showLineExecutionCounts.cpp
+// RUN: llvm-cov show %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs -name=main | FileCheck -check-prefixes=TEXT,FILTER -D#C=1 -DC16K2=1 -DC16K1=1 %S/Inputs/showLineExecutionCounts.cpp
>From f96b435e3c762fd6ae94eced63862289538b2a21 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 22 Dec 2024 00:48:52 +0900
Subject: [PATCH 16/30] New SingleByteCoverage
---
.../ProfileData/Coverage/CoverageMapping.h | 34 +++++++++++--------
.../ProfileData/Coverage/CoverageMapping.cpp | 31 +++++++----------
llvm/tools/llvm-cov/SourceCoverageView.h | 3 +-
3 files changed, 33 insertions(+), 35 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 42da188fef34ee..42aea623be1653 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -364,19 +364,16 @@ struct CountedRegion : public CounterMappingRegion {
uint64_t FalseExecutionCount;
bool TrueFolded;
bool FalseFolded;
- bool HasSingleByteCoverage;
- CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
- bool HasSingleByteCoverage)
+ CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
- FalseExecutionCount(0), TrueFolded(false), FalseFolded(true),
- HasSingleByteCoverage(HasSingleByteCoverage) {}
+ FalseExecutionCount(0), TrueFolded(false), FalseFolded(true) {}
CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
- uint64_t FalseExecutionCount, bool HasSingleByteCoverage)
+ uint64_t FalseExecutionCount)
: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
FalseExecutionCount(FalseExecutionCount), TrueFolded(false),
- FalseFolded(false), HasSingleByteCoverage(HasSingleByteCoverage) {}
+ FalseFolded(false) {}
};
/// MCDC Record grouping all information together.
@@ -719,10 +716,9 @@ struct FunctionRecord {
}
void pushRegion(CounterMappingRegion Region, uint64_t Count,
- uint64_t FalseCount, bool HasSingleByteCoverage) {
+ uint64_t FalseCount) {
if (Region.isBranch()) {
- CountedBranchRegions.emplace_back(Region, Count, FalseCount,
- HasSingleByteCoverage);
+ CountedBranchRegions.emplace_back(Region, Count, FalseCount);
// If either counter is hard-coded to zero, then this region represents a
// constant-folded branch.
CountedBranchRegions.back().TrueFolded = Region.Count.isZero();
@@ -731,8 +727,7 @@ struct FunctionRecord {
}
if (CountedRegions.empty())
ExecutionCount = Count;
- CountedRegions.emplace_back(Region, Count, FalseCount,
- HasSingleByteCoverage);
+ CountedRegions.emplace_back(Region, Count, FalseCount);
}
};
@@ -895,14 +890,19 @@ class CoverageData {
std::vector<CountedRegion> BranchRegions;
std::vector<MCDCRecord> MCDCRecords;
+ bool SingleByteCoverage;
+
public:
- CoverageData() = default;
+ CoverageData() = delete;
- CoverageData(StringRef Filename) : Filename(Filename) {}
+ CoverageData(bool Single, StringRef Filename = StringRef())
+ : Filename(Filename), SingleByteCoverage(Single) {}
/// Get the name of the file this data covers.
StringRef getFilename() const { return Filename; }
+ bool getSingleByteCoverage() const { return SingleByteCoverage; }
+
/// Get an iterator over the coverage segments for this object. The segments
/// are guaranteed to be uniqued and sorted by location.
std::vector<CoverageSegment>::const_iterator begin() const {
@@ -935,7 +935,9 @@ class CoverageMapping {
DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
- CoverageMapping() = default;
+ bool SingleByteCoverage;
+
+ CoverageMapping(bool Single) : SingleByteCoverage(Single) {}
// Load coverage records from readers.
static Error loadFromReaders(
@@ -979,6 +981,8 @@ class CoverageMapping {
const object::BuildIDFetcher *BIDFetcher = nullptr,
bool CheckBinaryIDs = false);
+ bool getSingleByteCoverage() const { return SingleByteCoverage; }
+
/// The number of functions that couldn't have their profiles mapped.
///
/// This is a count of functions whose profile is out of date or otherwise
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 87d8bb1bbb79c7..430e68ea94a02f 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -805,7 +805,6 @@ Error CoverageMapping::loadFunctionRecord(
else
OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
- bool SingleByteCoverage = ProfileReader.hasSingleByteCoverage();
CounterMappingContext Ctx(Record.Expressions);
std::vector<uint64_t> Counts;
@@ -871,10 +870,7 @@ Error CoverageMapping::loadFunctionRecord(
consumeError(std::move(E));
return Error::success();
}
- Function.pushRegion(
- Region, (SingleByteCoverage && *ExecutionCount ? 1 : *ExecutionCount),
- (SingleByteCoverage && *AltExecutionCount ? 1 : *AltExecutionCount),
- SingleByteCoverage);
+ Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
// Record ExpansionRegion.
if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
@@ -951,7 +947,8 @@ Error CoverageMapping::loadFromReaders(
Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
IndexedInstrProfReader &ProfileReader) {
- auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
+ auto Coverage = std::unique_ptr<CoverageMapping>(
+ new CoverageMapping(ProfileReader.hasSingleByteCoverage()));
if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
return std::move(E);
return std::move(Coverage);
@@ -1013,7 +1010,8 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
if (Error E = ProfileReaderOrErr.takeError())
return createFileError(ProfileFilename, std::move(E));
auto ProfileReader = std::move(ProfileReaderOrErr.get());
- auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
+ auto Coverage = std::unique_ptr<CoverageMapping>(
+ new CoverageMapping(ProfileReader->hasSingleByteCoverage()));
bool DataFound = false;
auto GetArch = [&](size_t Idx) {
@@ -1296,14 +1294,8 @@ class SegmentBuilder {
// value for that area.
// We add counts of the regions of the same kind as the active region
// to handle the both situations.
- if (I->Kind == Active->Kind) {
- assert(I->HasSingleByteCoverage == Active->HasSingleByteCoverage &&
- "Regions are generated in different coverage modes");
- if (I->HasSingleByteCoverage)
- Active->ExecutionCount = Active->ExecutionCount || I->ExecutionCount;
- else
- Active->ExecutionCount += I->ExecutionCount;
- }
+ if (I->Kind == Active->Kind)
+ Active->ExecutionCount += I->ExecutionCount;
}
return Regions.drop_back(std::distance(++Active, End));
}
@@ -1396,7 +1388,7 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
}
CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
- CoverageData FileCoverage(Filename);
+ CoverageData FileCoverage(SingleByteCoverage, Filename);
std::vector<CountedRegion> Regions;
// Look up the function records in the given file. Due to hash collisions on
@@ -1458,9 +1450,10 @@ CoverageData
CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
auto MainFileID = findMainViewFileID(Function);
if (!MainFileID)
- return CoverageData();
+ return CoverageData(SingleByteCoverage);
- CoverageData FunctionCoverage(Function.Filenames[*MainFileID]);
+ CoverageData FunctionCoverage(SingleByteCoverage,
+ Function.Filenames[*MainFileID]);
std::vector<CountedRegion> Regions;
for (const auto &CR : Function.CountedRegions)
if (CR.FileID == *MainFileID) {
@@ -1488,7 +1481,7 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
CoverageData CoverageMapping::getCoverageForExpansion(
const ExpansionRecord &Expansion) const {
CoverageData ExpansionCoverage(
- Expansion.Function.Filenames[Expansion.FileID]);
+ SingleByteCoverage, Expansion.Function.Filenames[Expansion.FileID]);
std::vector<CountedRegion> Regions;
for (const auto &CR : Expansion.Function.CountedRegions)
if (CR.FileID == Expansion.FileID) {
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h
index 9b72ca03c6d7ff..ed7e133d71e08a 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -283,7 +283,8 @@ class SourceCoverageView {
CoverageData &&CoverageInfo)
: SourceName(SourceName), File(File), Options(Options),
CoverageInfo(std::move(CoverageInfo)),
- BinaryCounters(Options.BinaryCounters) {}
+ BinaryCounters(Options.BinaryCounters ||
+ CoverageInfo.getSingleByteCoverage()) {}
public:
static std::unique_ptr<SourceCoverageView>
>From 47550d1cc07ba6407020d2a9417bb48bdc3a5156 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Sun, 22 Dec 2024 11:32:00 +0900
Subject: [PATCH 17/30] threads.c => threads.test (following #113114)
---
llvm/test/tools/llvm-cov/threads.c | 11 -----------
llvm/test/tools/llvm-cov/threads.test | 12 ++++++++++++
2 files changed, 12 insertions(+), 11 deletions(-)
delete mode 100644 llvm/test/tools/llvm-cov/threads.c
create mode 100644 llvm/test/tools/llvm-cov/threads.test
diff --git a/llvm/test/tools/llvm-cov/threads.c b/llvm/test/tools/llvm-cov/threads.c
deleted file mode 100644
index b162b6ac5a8011..00000000000000
--- a/llvm/test/tools/llvm-cov/threads.c
+++ /dev/null
@@ -1,11 +0,0 @@
-// Coverage/profile data recycled from the showLineExecutionCounts.cpp test.
-//
-// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t1.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t2.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
-// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t3.dir -instr-profile %t.profdata -path-equivalence=/tmp,%S %S/showLineExecutionCounts.cpp
-//
-// RUN: diff %t1.dir/index.txt %t2.dir/index.txt
-// RUN: diff %t1.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %t2.dir/coverage/tmp/showLineExecutionCounts.cpp.txt
-// RUN: diff %t1.dir/index.txt %t3.dir/index.txt
-// RUN: diff %t1.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %t3.dir/coverage/tmp/showLineExecutionCounts.cpp.txt
diff --git a/llvm/test/tools/llvm-cov/threads.test b/llvm/test/tools/llvm-cov/threads.test
new file mode 100644
index 00000000000000..a51406ca14efa9
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/threads.test
@@ -0,0 +1,12 @@
+// Coverage/profile data recycled from the showLineExecutionCounts.cpp test.
+//
+// RUN: rm -rf %t.dir
+// RUN: llvm-profdata merge %S/Inputs/lineExecutionCounts.proftext -o %t.profdata
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -j 1 -o %t.dir/1 -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -num-threads 2 -o %t.dir/2 -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+// RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -o %t.dir/3 -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs
+//
+// RUN: diff %t.dir/1/index.txt %t.dir/2/index.txt
+// RUN: diff %t.dir/1/coverage/tmp/showLineExecutionCounts.cpp.txt %t.dir/2/coverage/tmp/showLineExecutionCounts.cpp.txt
+// RUN: diff %t.dir/1/index.txt %t.dir/3/index.txt
+// RUN: diff %t.dir/1/coverage/tmp/showLineExecutionCounts.cpp.txt %t.dir/3/coverage/tmp/showLineExecutionCounts.cpp.txt
>From f4dc4ebfd585869455be0e9f37294b7037ca9a65 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 23 Dec 2024 15:57:36 +0900
Subject: [PATCH 18/30] s/Count1/BinaryCount/
---
llvm/tools/llvm-cov/SourceCoverageView.h | 8 ++++++--
llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp | 8 ++++----
llvm/tools/llvm-cov/SourceCoverageViewText.cpp | 6 +++---
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h
index 9b72ca03c6d7ff..0b4e3978a4ba9c 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -268,9 +268,13 @@ class SourceCoverageView {
/// digits.
static std::string formatCount(uint64_t N);
- uint64_t Count1(uint64_t N) const { return (N && BinaryCounters ? 1 : N); }
+ uint64_t BinaryCount(uint64_t N) const {
+ return (N && BinaryCounters ? 1 : N);
+ }
- std::string formatCount1(uint64_t N) const { return formatCount(Count1(N)); }
+ std::string formatBinaryCount(uint64_t N) const {
+ return formatCount(BinaryCount(N));
+ }
/// Check if region marker output is expected for a line.
bool shouldRenderRegionMarkers(const LineCoverageStats &LCS) const;
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index f3aa7e801597c9..c94d3853fc0143 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -1019,8 +1019,8 @@ void SourceCoverageViewHTML::renderLine(raw_ostream &OS, LineRef L,
// Just consider the segments which start *and* end on this line.
for (unsigned I = 0, E = Segments.size() - 1; I < E; ++I) {
const auto *CurSeg = Segments[I];
- auto CurSegCount = Count1(CurSeg->Count);
- auto LCSCount = Count1(LCS.getExecutionCount());
+ auto CurSegCount = BinaryCount(CurSeg->Count);
+ auto LCSCount = BinaryCount(LCS.getExecutionCount());
if (!CurSeg->IsRegionEntry)
continue;
if (CurSegCount == LCSCount)
@@ -1054,7 +1054,7 @@ void SourceCoverageViewHTML::renderLineCoverageColumn(
raw_ostream &OS, const LineCoverageStats &Line) {
std::string Count;
if (Line.isMapped())
- Count = tag("pre", formatCount1(Line.getExecutionCount()));
+ Count = tag("pre", formatBinaryCount(Line.getExecutionCount()));
std::string CoverageClass =
(Line.getExecutionCount() > 0)
? "covered-line"
@@ -1109,7 +1109,7 @@ void SourceCoverageViewHTML::renderBranchView(raw_ostream &OS, BranchView &BRV,
OS << tag("span", Label, (Count ? "None" : "red branch")) << ": ";
if (getOptions().ShowBranchCounts)
- OS << tag("span", formatCount1(Count),
+ OS << tag("span", formatBinaryCount(Count),
(Count ? "covered-line" : "uncovered-line"));
else
OS << format("%0.2f", (Total != 0 ? 100.0 * Count / Total : 0.0)) << "%";
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index f0c366e45c2c92..765f8bbbd8d1b5 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -216,7 +216,7 @@ void SourceCoverageViewText::renderLineCoverageColumn(
OS.indent(LineCoverageColumnWidth) << '|';
return;
}
- std::string C = formatCount1(Line.getExecutionCount());
+ std::string C = formatBinaryCount(Line.getExecutionCount());
OS.indent(LineCoverageColumnWidth - C.size());
colored_ostream(OS, raw_ostream::MAGENTA,
Line.hasMultipleRegions() && getOptions().Colors)
@@ -263,7 +263,7 @@ void SourceCoverageViewText::renderRegionMarkers(raw_ostream &OS,
if (getOptions().Debug)
errs() << "Marker at " << S->Line << ":" << S->Col << " = "
- << formatCount1(S->Count) << "\n";
+ << formatBinaryCount(S->Count) << "\n";
}
OS << '\n';
}
@@ -307,7 +307,7 @@ void SourceCoverageViewText::renderBranchView(raw_ostream &OS, BranchView &BRV,
<< Label;
if (getOptions().ShowBranchCounts)
- OS << ": " << formatCount1(Count);
+ OS << ": " << formatBinaryCount(Count);
else
OS << ": " << format("%0.2f", (Total != 0 ? 100.0 * Count / Total : 0.0))
<< "%";
>From 822620bea235792675202045b2b7d138aa069f0e Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Mon, 23 Dec 2024 15:55:49 +0900
Subject: [PATCH 19/30] Update desc
---
llvm/tools/llvm-cov/CodeCoverage.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 0e8360a4ac6ed9..2d6da7efc69798 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -1025,7 +1025,8 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
cl::opt<bool> BinaryCounters(
"binary-counters", cl::Optional,
- cl::desc("Show 1/0 instead of actual counter values."),
+ cl::desc("Show when lines/branches are covered (1) or uncovered (0) "
+ "instead of showing actual counter values."),
cl::cat(ViewCategory));
cl::opt<uint32_t> TabSize(
>From dfc99bad0fd0baa6e0d9a39554da041dd02d6568 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Tue, 24 Dec 2024 17:29:27 +0900
Subject: [PATCH 20/30] Fix wrong merge resolutions
---
llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 21a296d89d214f..430e68ea94a02f 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -805,7 +805,6 @@ Error CoverageMapping::loadFunctionRecord(
else
OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
- bool SingleByteCoverage = ProfileReader.hasSingleByteCoverage();
CounterMappingContext Ctx(Record.Expressions);
std::vector<uint64_t> Counts;
@@ -871,10 +870,7 @@ Error CoverageMapping::loadFunctionRecord(
consumeError(std::move(E));
return Error::success();
}
- Function.pushRegion(
- Region, (SingleByteCoverage && *ExecutionCount ? 1 : *ExecutionCount),
- (SingleByteCoverage && *AltExecutionCount ? 1 : *AltExecutionCount),
- SingleByteCoverage);
+ Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
// Record ExpansionRegion.
if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
>From f3c9593037e8dbc4a5c9c5e5a5d5801e801019c4 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 25 Dec 2024 08:40:39 +0900
Subject: [PATCH 21/30] Reorganize CoverageMapping::SingleByteCoverage
---
.../ProfileData/Coverage/CoverageMapping.h | 12 +++++------
.../ProfileData/Coverage/CoverageMapping.cpp | 20 +++++++++++--------
2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 42aea623be1653..705a9f28c12413 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -890,12 +890,12 @@ class CoverageData {
std::vector<CountedRegion> BranchRegions;
std::vector<MCDCRecord> MCDCRecords;
- bool SingleByteCoverage;
+ bool SingleByteCoverage = false;
public:
- CoverageData() = delete;
+ CoverageData() = default;
- CoverageData(bool Single, StringRef Filename = StringRef())
+ CoverageData(bool Single, StringRef Filename)
: Filename(Filename), SingleByteCoverage(Single) {}
/// Get the name of the file this data covers.
@@ -935,9 +935,9 @@ class CoverageMapping {
DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
- bool SingleByteCoverage;
+ std::optional<bool> SingleByteCoverage;
- CoverageMapping(bool Single) : SingleByteCoverage(Single) {}
+ CoverageMapping() = default;
// Load coverage records from readers.
static Error loadFromReaders(
@@ -981,7 +981,7 @@ class CoverageMapping {
const object::BuildIDFetcher *BIDFetcher = nullptr,
bool CheckBinaryIDs = false);
- bool getSingleByteCoverage() const { return SingleByteCoverage; }
+ // bool getSingleByteCoverage() const { return SingleByteCoverage; }
/// The number of functions that couldn't have their profiles mapped.
///
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 430e68ea94a02f..1bf2e8d627bc4d 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -932,6 +932,9 @@ Error CoverageMapping::loadFunctionRecord(
Error CoverageMapping::loadFromReaders(
ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage) {
+ assert(!Coverage.SingleByteCoverage ||
+ *Coverage.SingleByteCoverage == ProfileReader.hasSingleByteCoverage());
+ Coverage.SingleByteCoverage = ProfileReader.hasSingleByteCoverage();
for (const auto &CoverageReader : CoverageReaders) {
for (auto RecordOrErr : *CoverageReader) {
if (Error E = RecordOrErr.takeError())
@@ -947,8 +950,7 @@ Error CoverageMapping::loadFromReaders(
Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
IndexedInstrProfReader &ProfileReader) {
- auto Coverage = std::unique_ptr<CoverageMapping>(
- new CoverageMapping(ProfileReader.hasSingleByteCoverage()));
+ auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))
return std::move(E);
return std::move(Coverage);
@@ -1010,8 +1012,7 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
if (Error E = ProfileReaderOrErr.takeError())
return createFileError(ProfileFilename, std::move(E));
auto ProfileReader = std::move(ProfileReaderOrErr.get());
- auto Coverage = std::unique_ptr<CoverageMapping>(
- new CoverageMapping(ProfileReader->hasSingleByteCoverage()));
+ auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping());
bool DataFound = false;
auto GetArch = [&](size_t Idx) {
@@ -1388,7 +1389,8 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
}
CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
- CoverageData FileCoverage(SingleByteCoverage, Filename);
+ assert(SingleByteCoverage);
+ CoverageData FileCoverage(*SingleByteCoverage, Filename);
std::vector<CountedRegion> Regions;
// Look up the function records in the given file. Due to hash collisions on
@@ -1450,9 +1452,10 @@ CoverageData
CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
auto MainFileID = findMainViewFileID(Function);
if (!MainFileID)
- return CoverageData(SingleByteCoverage);
+ return CoverageData();
- CoverageData FunctionCoverage(SingleByteCoverage,
+ assert(SingleByteCoverage);
+ CoverageData FunctionCoverage(*SingleByteCoverage,
Function.Filenames[*MainFileID]);
std::vector<CountedRegion> Regions;
for (const auto &CR : Function.CountedRegions)
@@ -1480,8 +1483,9 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
CoverageData CoverageMapping::getCoverageForExpansion(
const ExpansionRecord &Expansion) const {
+ assert(SingleByteCoverage);
CoverageData ExpansionCoverage(
- SingleByteCoverage, Expansion.Function.Filenames[Expansion.FileID]);
+ *SingleByteCoverage, Expansion.Function.Filenames[Expansion.FileID]);
std::vector<CountedRegion> Regions;
for (const auto &CR : Expansion.Function.CountedRegions)
if (CR.FileID == Expansion.FileID) {
>From 3780e07c41b54c07e2cd61bee8a7c451e4f2cbf5 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Wed, 25 Dec 2024 08:43:24 +0900
Subject: [PATCH 22/30] Prune commented-out line
---
llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 705a9f28c12413..0ad6f07bde989b 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -981,8 +981,6 @@ class CoverageMapping {
const object::BuildIDFetcher *BIDFetcher = nullptr,
bool CheckBinaryIDs = false);
- // bool getSingleByteCoverage() const { return SingleByteCoverage; }
-
/// The number of functions that couldn't have their profiles mapped.
///
/// This is a count of functions whose profile is out of date or otherwise
>From 36b4aaf0248c85c3e3cf621f75b26e2734efafba Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 15:31:05 +0900
Subject: [PATCH 23/30] [Coverage] Make `MCDCRecord::Folded` as `[false/true]`
with BitVector. NFC.
---
.../llvm/ProfileData/Coverage/CoverageMapping.h | 6 ++++--
llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 11 ++++++-----
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 42da188fef34ee..5caba07f8ad43a 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -442,7 +442,7 @@ struct MCDCRecord {
};
using TestVectors = llvm::SmallVector<std::pair<TestVector, CondState>>;
- using BoolVector = llvm::SmallVector<bool>;
+ using BoolVector = std::array<BitVector, 2>;
using TVRowPair = std::pair<unsigned, unsigned>;
using TVPairMap = llvm::DenseMap<unsigned, TVRowPair>;
using CondIDMap = llvm::DenseMap<unsigned, unsigned>;
@@ -470,7 +470,9 @@ struct MCDCRecord {
return Region.getDecisionParams().NumConditions;
}
unsigned getNumTestVectors() const { return TV.size(); }
- bool isCondFolded(unsigned Condition) const { return Folded[Condition]; }
+ bool isCondFolded(unsigned Condition) const {
+ return Folded[false][Condition] || Folded[true][Condition];
+ }
/// Return the evaluation of a condition (indicated by Condition) in an
/// executed test vector (indicated by TestVectorIndex), which will be True,
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 87d8bb1bbb79c7..2eba1667306d15 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -392,8 +392,9 @@ 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),
- ExecVectors(ExecVectorsByCond[false]), IsVersion11(IsVersion11) {}
+ Folded{{BitVector(NumConditions), BitVector(NumConditions)}},
+ IndependencePairs(NumConditions), ExecVectors(ExecVectorsByCond[false]),
+ IsVersion11(IsVersion11) {}
private:
// Walk the binary decision diagram and try assigning both false and true to
@@ -485,7 +486,6 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
/// location is also tracked, as well as whether it is constant folded (in
/// which case it is excuded from the metric).
MCDCRecord processMCDCRecord() {
- unsigned I = 0;
MCDCRecord::CondIDMap PosToID;
MCDCRecord::LineColPairMap CondLoc;
@@ -499,11 +499,12 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
// visualize where the condition is.
// - Record whether the condition is constant folded so that we exclude it
// from being measured.
- for (const auto *B : Branches) {
+ for (auto [I, B] : enumerate(Branches)) {
const auto &BranchParams = B->getBranchParams();
PosToID[I] = BranchParams.ID;
CondLoc[I] = B->startLoc();
- Folded[I++] = (B->Count.isZero() || B->FalseCount.isZero());
+ Folded[false][I] = B->FalseCount.isZero();
+ Folded[true][I] = B->Count.isZero();
}
// Using Profile Bitmap from runtime, mark the executed test vectors.
>From 978070d6aca594a49dc2ef0558e1e28e883ac1b0 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 15:34:16 +0900
Subject: [PATCH 24/30] [Coverage] MCDC: Move `findIndependencePairs` into
`MCDCRecord`
---
.../ProfileData/Coverage/CoverageMapping.h | 27 +++++---
.../ProfileData/Coverage/CoverageMapping.cpp | 67 ++++++++++---------
2 files changed, 51 insertions(+), 43 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 42da188fef34ee..4f28f5da6cf81f 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -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");
+ 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);
+ return (*IndependencePairs)[PosToID[Condition]];
}
float getPercentCovered() const {
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 87d8bb1bbb79c7..2c7a77bac09328 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -221,6 +221,40 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
return LastPoppedValue;
}
+// 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 MCDCRecord::findIndependencePairs() {
+ if (IndependencePairs)
+ return;
+
+ IndependencePairs.emplace();
+
+ unsigned NumTVs = TV.size();
+ // Will be replaced to shorter expr.
+ unsigned TVTrueIdx = std::distance(
+ 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) {
+ 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));
}
};
>From 3abe2ac361822bf6513e5f3ef9fead37842af862 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 15:40:47 +0900
Subject: [PATCH 25/30] [Coverage] Sort `MCDCRecord::ExecVectors` order by
Bitmap index
---
.../ProfileData/Coverage/CoverageMapping.cpp | 40 +++++++++++++------
llvm/test/tools/llvm-cov/mcdc-const.test | 32 +++++++--------
llvm/test/tools/llvm-cov/mcdc-general.test | 8 ++--
3 files changed, 47 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 3bbee70be0fe93..53445b1030c9fd 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -401,13 +401,27 @@ 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;
+ /// Helper for sorting ExecVectors.
+ struct TVIdxTuple {
+ MCDCRecord::CondState MCDCCond; /// True/False
+ unsigned BIdx; /// Bitmap Index
+ unsigned Ord; /// Last position on ExecVectors
+
+ TVIdxTuple(MCDCRecord::CondState MCDCCond, unsigned BIdx, unsigned Ord)
+ : MCDCCond(MCDCCond), BIdx(BIdx), Ord(Ord) {}
+
+ bool operator<(const TVIdxTuple &RHS) const {
+ return (std::tie(this->MCDCCond, this->BIdx, this->Ord) <
+ std::tie(RHS.MCDCCond, RHS.BIdx, RHS.Ord));
+ }
+ };
+
+ // Indices for sorted TestVectors;
+ std::vector<TVIdxTuple> ExecVectorIdxs;
/// Actual executed Test Vectors for the boolean expression, based on
/// ExecutedTestVectorBitmap.
- MCDCRecord::TestVectors &ExecVectors;
+ MCDCRecord::TestVectors ExecVectors;
#ifndef NDEBUG
DenseSet<unsigned> TVIdxs;
@@ -424,8 +438,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
Region(Region), DecisionParams(Region.getDecisionParams()),
Branches(Branches), NumConditions(DecisionParams.NumConditions),
Folded{{BitVector(NumConditions), BitVector(NumConditions)}},
- IndependencePairs(NumConditions), ExecVectors(ExecVectorsByCond[false]),
- IsVersion11(IsVersion11) {}
+ IndependencePairs(NumConditions), IsVersion11(IsVersion11) {}
private:
// Walk the binary decision diagram and try assigning both false and true to
@@ -453,10 +466,12 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
: DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
continue;
+ ExecVectorIdxs.emplace_back(MCDCCond, NextTVIdx, ExecVectors.size());
+
// Copy the completed test vector to the vector of testvectors.
// The final value (T,F) is equal to the last non-dontcare state on the
// path (in a short-circuiting system).
- ExecVectorsByCond[MCDCCond].push_back({TV, MCDCCond});
+ ExecVectors.push_back({TV, MCDCCond});
}
// Reset back to DontCare.
@@ -475,12 +490,11 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
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.
- auto &ExecVectorsT = ExecVectorsByCond[true];
- ExecVectors.append(std::make_move_iterator(ExecVectorsT.begin()),
- std::make_move_iterator(ExecVectorsT.end()));
+ llvm::sort(ExecVectorIdxs);
+ MCDCRecord::TestVectors NewTestVectors;
+ for (const auto &IdxTuple : ExecVectorIdxs)
+ NewTestVectors.push_back(std::move(ExecVectors[IdxTuple.Ord]));
+ ExecVectors = std::move(NewTestVectors);
}
public:
diff --git a/llvm/test/tools/llvm-cov/mcdc-const.test b/llvm/test/tools/llvm-cov/mcdc-const.test
index 5424625cf6a6b5..76eb7cf706d737 100644
--- a/llvm/test/tools/llvm-cov/mcdc-const.test
+++ b/llvm/test/tools/llvm-cov/mcdc-const.test
@@ -61,8 +61,8 @@
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
-// CHECKFULLCASE: | 1 { F, C = T }
-// CHECKFULLCASE-NEXT: | 2 { T, C = T }
+// CHECKFULLCASE: | 1 { T, C = T }
+// CHECKFULLCASE-NEXT: | 2 { F, C = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
@@ -106,20 +106,20 @@
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
-// CHECKFULLCASE: | 1 { F, C, - = T }
-// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
+// CHECKFULLCASE: | 1 { T, C, - = T }
+// CHECKFULLCASE-NEXT: | 2 { F, C, - = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
-// CHECKFULLCASE: | 1 { C, F, T = T }
-// CHECKFULLCASE-NEXT: | 2 { C, T, - = T }
+// CHECKFULLCASE: | 1 { C, T, - = T }
+// CHECKFULLCASE-NEXT: | 2 { C, F, T = T }
// CHECKFULLCASE: | C1-Pair: constant folded
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
-// CHECKFULLCASE: | 1 { F, C, T = T }
-// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
+// CHECKFULLCASE: | 1 { T, C, - = T }
+// CHECKFULLCASE-NEXT: | 2 { F, C, T = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
@@ -151,26 +151,26 @@
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: covered: (2,3)
// CHECKFULLCASE: | MC/DC Coverage for Decision: 100.00%
-// CHECKFULLCASE: | 1 { F, T, C = T }
-// CHECKFULLCASE-NEXT: | 2 { T, -, C = T }
+// CHECKFULLCASE: | 1 { T, -, C = T }
+// CHECKFULLCASE-NEXT: | 2 { F, T, C = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
-// CHECKFULLCASE: | 1 { F, C, - = T }
-// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
+// CHECKFULLCASE: | 1 { T, C, - = T }
+// CHECKFULLCASE-NEXT: | 2 { F, C, - = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
-// CHECKFULLCASE: | 1 { F, T, C = T }
-// CHECKFULLCASE-NEXT: | 2 { T, -, C = T }
+// CHECKFULLCASE: | 1 { T, -, C = T }
+// CHECKFULLCASE-NEXT: | 2 { F, T, C = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: not covered
// CHECKFULLCASE-NEXT: | C3-Pair: constant folded
// CHECKFULLCASE: | MC/DC Coverage for Decision: 0.00%
-// CHECKFULLCASE: | 1 { F, C, T = T }
-// CHECKFULLCASE-NEXT: | 2 { T, C, - = T }
+// CHECKFULLCASE: | 1 { T, C, - = T }
+// CHECKFULLCASE-NEXT: | 2 { F, C, T = T }
// CHECKFULLCASE: | C1-Pair: not covered
// CHECKFULLCASE-NEXT: | C2-Pair: constant folded
// CHECKFULLCASE-NEXT: | C3-Pair: not covered
diff --git a/llvm/test/tools/llvm-cov/mcdc-general.test b/llvm/test/tools/llvm-cov/mcdc-general.test
index c1e95cb2bd92ac..1835af9a4c6b5c 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general.test
@@ -19,15 +19,15 @@
// CHECK-NEXT: |
// CHECK-NEXT: | C1, C2, C3, C4 Result
// CHECK-NEXT: | 1 { F, -, F, - = F }
-// CHECK-NEXT: | 2 { F, -, T, F = F }
-// CHECK-NEXT: | 3 { T, F, F, - = F }
+// CHECK-NEXT: | 2 { T, F, F, - = F }
+// CHECK-NEXT: | 3 { F, -, T, F = F }
// CHECK-NEXT: | 4 { T, F, T, F = F }
// CHECK-NEXT: | 5 { T, F, T, T = T }
// CHECK-NEXT: | 6 { T, T, -, - = T }
// CHECK-NEXT: |
// CHECK-NEXT: | C1-Pair: covered: (1,6)
-// CHECK-NEXT: | C2-Pair: covered: (3,6)
-// CHECK-NEXT: | C3-Pair: covered: (3,5)
+// CHECK-NEXT: | C2-Pair: covered: (2,6)
+// CHECK-NEXT: | C3-Pair: covered: (2,5)
// CHECK-NEXT: | C4-Pair: covered: (4,5)
// CHECK-NEXT: | MC/DC Coverage for Decision: 100.00%
// CHECK-NEXT: |
>From f86c537e2c9224cddf10d0b05333e35bdc169361 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 15:42:07 +0900
Subject: [PATCH 26/30] llvm-cov: Refactor CoverageSummaryInfo. NFC.
---
llvm/tools/llvm-cov/CoverageSummaryInfo.cpp | 51 +++++++++++----------
llvm/tools/llvm-cov/CoverageSummaryInfo.h | 45 +++++++++---------
2 files changed, 50 insertions(+), 46 deletions(-)
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index ad7561d3dc62c0..5c002a694f66ae 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -16,8 +16,9 @@
using namespace llvm;
using namespace coverage;
-static void sumBranches(size_t &NumBranches, size_t &CoveredBranches,
- const ArrayRef<CountedRegion> &Branches) {
+static auto sumBranches(const ArrayRef<CountedRegion> &Branches) {
+ size_t NumBranches = 0;
+ size_t CoveredBranches = 0;
for (const auto &BR : Branches) {
if (!BR.TrueFolded) {
// "True" Condition Branches.
@@ -32,20 +33,22 @@ static void sumBranches(size_t &NumBranches, size_t &CoveredBranches,
++CoveredBranches;
}
}
+ return BranchCoverageInfo(CoveredBranches, NumBranches);
}
-static void sumBranchExpansions(size_t &NumBranches, size_t &CoveredBranches,
- const CoverageMapping &CM,
- ArrayRef<ExpansionRecord> Expansions) {
+static BranchCoverageInfo
+sumBranchExpansions(const CoverageMapping &CM,
+ ArrayRef<ExpansionRecord> Expansions) {
+ BranchCoverageInfo BranchCoverage;
for (const auto &Expansion : Expansions) {
auto CE = CM.getCoverageForExpansion(Expansion);
- sumBranches(NumBranches, CoveredBranches, CE.getBranches());
- sumBranchExpansions(NumBranches, CoveredBranches, CM, CE.getExpansions());
+ BranchCoverage += sumBranches(CE.getBranches());
+ BranchCoverage += sumBranchExpansions(CM, CE.getExpansions());
}
+ return BranchCoverage;
}
-static std::pair<size_t, size_t>
-sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) {
+auto sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) {
size_t NumPairs = 0, CoveredPairs = 0;
for (const auto &Record : Records) {
const auto NumConditions = Record.getNumConditions();
@@ -56,7 +59,7 @@ sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) {
++CoveredPairs;
}
}
- return {NumPairs, CoveredPairs};
+ return MCDCCoverageInfo(CoveredPairs, NumPairs);
}
static std::pair<RegionCoverageInfo, LineCoverageInfo>
@@ -85,24 +88,27 @@ sumRegions(ArrayRef<CountedRegion> CodeRegions, const CoverageData &CD) {
LineCoverageInfo(CoveredLines, NumLines)};
}
+CoverageDataSummary::CoverageDataSummary(const CoverageData &CD,
+ ArrayRef<CountedRegion> CodeRegions) {
+ std::tie(RegionCoverage, LineCoverage) = sumRegions(CodeRegions, CD);
+ BranchCoverage = sumBranches(CD.getBranches());
+ MCDCCoverage = sumMCDCPairs(CD.getMCDCRecords());
+}
+
FunctionCoverageSummary
FunctionCoverageSummary::get(const CoverageMapping &CM,
const coverage::FunctionRecord &Function) {
CoverageData CD = CM.getCoverageForFunction(Function);
- auto [RegionCoverage, LineCoverage] = sumRegions(Function.CountedRegions, CD);
- // Compute the branch coverage, including branches from expansions.
- size_t NumBranches = 0, CoveredBranches = 0;
- sumBranches(NumBranches, CoveredBranches, CD.getBranches());
- sumBranchExpansions(NumBranches, CoveredBranches, CM, CD.getExpansions());
+ auto Summary =
+ FunctionCoverageSummary(Function.Name, Function.ExecutionCount);
- size_t NumPairs = 0, CoveredPairs = 0;
- std::tie(NumPairs, CoveredPairs) = sumMCDCPairs(CD.getMCDCRecords());
+ Summary += CoverageDataSummary(CD, Function.CountedRegions);
- return FunctionCoverageSummary(
- Function.Name, Function.ExecutionCount, RegionCoverage, LineCoverage,
- BranchCoverageInfo(CoveredBranches, NumBranches),
- MCDCCoverageInfo(CoveredPairs, NumPairs));
+ // Compute the branch coverage, including branches from expansions.
+ Summary.BranchCoverage += sumBranchExpansions(CM, CD.getExpansions());
+
+ return Summary;
}
FunctionCoverageSummary
@@ -117,8 +123,7 @@ FunctionCoverageSummary::get(const InstantiationGroup &Group,
<< Group.getColumn();
}
- FunctionCoverageSummary Summary(Name);
- Summary.ExecutionCount = Group.getTotalExecutionCount();
+ FunctionCoverageSummary Summary(Name, Group.getTotalExecutionCount());
Summary.RegionCoverage = Summaries[0].RegionCoverage;
Summary.LineCoverage = Summaries[0].LineCoverage;
Summary.BranchCoverage = Summaries[0].BranchCoverage;
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index 64c2c8406cf3eb..d9210676c41bf3 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -223,26 +223,32 @@ class FunctionCoverageInfo {
}
};
-/// A summary of function's code coverage.
-struct FunctionCoverageSummary {
- std::string Name;
- uint64_t ExecutionCount;
+struct CoverageDataSummary {
RegionCoverageInfo RegionCoverage;
LineCoverageInfo LineCoverage;
BranchCoverageInfo BranchCoverage;
MCDCCoverageInfo MCDCCoverage;
- FunctionCoverageSummary(const std::string &Name)
- : Name(Name), ExecutionCount(0) {}
+ CoverageDataSummary() = default;
+ CoverageDataSummary(const coverage::CoverageData &CD,
+ ArrayRef<coverage::CountedRegion> CodeRegions);
- FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount,
- const RegionCoverageInfo &RegionCoverage,
- const LineCoverageInfo &LineCoverage,
- const BranchCoverageInfo &BranchCoverage,
- const MCDCCoverageInfo &MCDCCoverage)
- : Name(Name), ExecutionCount(ExecutionCount),
- RegionCoverage(RegionCoverage), LineCoverage(LineCoverage),
- BranchCoverage(BranchCoverage), MCDCCoverage(MCDCCoverage) {}
+ auto &operator+=(const CoverageDataSummary &RHS) {
+ RegionCoverage += RHS.RegionCoverage;
+ LineCoverage += RHS.LineCoverage;
+ BranchCoverage += RHS.BranchCoverage;
+ MCDCCoverage += RHS.MCDCCoverage;
+ return *this;
+ }
+};
+
+/// A summary of function's code coverage.
+struct FunctionCoverageSummary : CoverageDataSummary {
+ std::string Name;
+ uint64_t ExecutionCount;
+
+ FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount = 0)
+ : Name(Name), ExecutionCount(ExecutionCount) {}
/// Compute the code coverage summary for the given function coverage
/// mapping record.
@@ -257,12 +263,8 @@ struct FunctionCoverageSummary {
};
/// A summary of file's code coverage.
-struct FileCoverageSummary {
+struct FileCoverageSummary : CoverageDataSummary {
StringRef Name;
- RegionCoverageInfo RegionCoverage;
- LineCoverageInfo LineCoverage;
- BranchCoverageInfo BranchCoverage;
- MCDCCoverageInfo MCDCCoverage;
FunctionCoverageInfo FunctionCoverage;
FunctionCoverageInfo InstantiationCoverage;
@@ -270,11 +272,8 @@ struct FileCoverageSummary {
FileCoverageSummary(StringRef Name) : Name(Name) {}
FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
- RegionCoverage += RHS.RegionCoverage;
- LineCoverage += RHS.LineCoverage;
+ *static_cast<CoverageDataSummary *>(this) += RHS;
FunctionCoverage += RHS.FunctionCoverage;
- BranchCoverage += RHS.BranchCoverage;
- MCDCCoverage += RHS.MCDCCoverage;
InstantiationCoverage += RHS.InstantiationCoverage;
return *this;
}
>From 92bf1c1eeaa79a1f9a6d410744d38dd5bf342040 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 15:44:28 +0900
Subject: [PATCH 27/30] llvm-cov: Emit RegionCoverage based on
`CoverageData::Segments`
---
llvm/test/tools/llvm-cov/branch-c-general.test | 12 ++++++------
llvm/test/tools/llvm-cov/branch-export-json.test | 2 +-
llvm/test/tools/llvm-cov/branch-macros.test | 6 +++---
.../test/tools/llvm-cov/branch-noShowBranch.test | 12 ++++++------
llvm/test/tools/llvm-cov/mcdc-general-none.test | 6 +++---
llvm/test/tools/llvm-cov/mcdc-general.test | 6 +++---
llvm/tools/llvm-cov/CoverageSummaryInfo.cpp | 16 ++++++++--------
llvm/tools/llvm-cov/CoverageSummaryInfo.h | 3 +--
8 files changed, 31 insertions(+), 32 deletions(-)
diff --git a/llvm/test/tools/llvm-cov/branch-c-general.test b/llvm/test/tools/llvm-cov/branch-c-general.test
index 3c163bf6de45cc..9ee15ec75428e5 100644
--- a/llvm/test/tools/llvm-cov/branch-c-general.test
+++ b/llvm/test/tools/llvm-cov/branch-c-general.test
@@ -117,19 +117,19 @@
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
// REPORT-NEXT: simple_loops 8 0 100.00% 9 0 100.00% 6 0 100.00%
-// REPORT-NEXT: conditionals 24 0 100.00% 15 0 100.00% 16 2 87.50%
+// REPORT-NEXT: conditionals 22 0 100.00% 15 0 100.00% 16 2 87.50%
// REPORT-NEXT: early_exits 20 4 80.00% 25 2 92.00% 16 6 62.50%
// REPORT-NEXT: jumps 39 12 69.23% 48 2 95.83% 26 9 65.38%
-// REPORT-NEXT: switches 28 5 82.14% 38 4 89.47% 28 7 75.00%
+// REPORT-NEXT: switches 27 4 85.19% 38 4 89.47% 28 7 75.00%
// REPORT-NEXT: big_switch 25 1 96.00% 32 0 100.00% 30 6 80.00%
-// REPORT-NEXT: boolean_operators 16 0 100.00% 13 0 100.00% 22 2 90.91%
-// REPORT-NEXT: boolop_loops 19 0 100.00% 14 0 100.00% 16 2 87.50%
+// REPORT-NEXT: boolean_operators 14 0 100.00% 13 0 100.00% 22 2 90.91%
+// REPORT-NEXT: boolop_loops 15 0 100.00% 14 0 100.00% 16 2 87.50%
// REPORT-NEXT: conditional_operator 4 2 50.00% 8 0 100.00% 4 2 50.00%
// REPORT-NEXT: do_fallthrough 9 0 100.00% 12 0 100.00% 6 0 100.00%
// REPORT-NEXT: main 1 0 100.00% 16 0 100.00% 0 0 0.00%
// REPORT-NEXT: c-general.c:static_func 4 0 100.00% 4 0 100.00% 2 0 100.00%
// REPORT-NEXT: ---
-// REPORT-NEXT: TOTAL 197 24 87.82% 234 8 96.58% 172 36 79.07%
+// REPORT-NEXT: TOTAL 188 23 87.77% 234 8 96.58% 172 36 79.07%
// Test file-level report.
// RUN: llvm-profdata merge %S/Inputs/branch-c-general.proftext -o %t.profdata
@@ -159,7 +159,7 @@
// HTML-INDEX: <td class='column-entry-yellow'>
// HTML-INDEX: 96.58% (226/234)
// HTML-INDEX: <td class='column-entry-yellow'>
-// HTML-INDEX: 87.82% (173/197)
+// HTML-INDEX: 87.77% (165/188)
// HTML-INDEX: <td class='column-entry-red'>
// HTML-INDEX: 79.07% (136/172)
// HTML-INDEX: <tr class='light-row-bold'>
diff --git a/llvm/test/tools/llvm-cov/branch-export-json.test b/llvm/test/tools/llvm-cov/branch-export-json.test
index 7cf42860879827..4278482c6d870e 100644
--- a/llvm/test/tools/llvm-cov/branch-export-json.test
+++ b/llvm/test/tools/llvm-cov/branch-export-json.test
@@ -18,7 +18,7 @@
// CHECK: 45,5,45,11,0,5,0,0,4
// CHECK: 47,5,47,12,3,2,0,0,4
// CHECK: 53,12,53,20,50,5,0,0,4
-// CHECK: {"count":30,"covered":26,"notcovered":4,"percent":86.666666666666671}
+// CHECK: {"count":30,"covered":26,"notcovered":4,"percent":86.6[[#]]}
// Check recursive macro-expansions.
// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test
index e4bd14ec14f16c..b3b163f5457b03 100644
--- a/llvm/test/tools/llvm-cov/branch-macros.test
+++ b/llvm/test/tools/llvm-cov/branch-macros.test
@@ -8,8 +8,8 @@
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT-NEXT: ---
-// REPORT-NEXT: _Z4funcii 28 4 85.71% 18 0 100.00% 30 14 53.33%
-// REPORT-NEXT: _Z5func2ii 13 1 92.31% 8 0 100.00% 10 2 80.00%
+// REPORT-NEXT: _Z4funcii 12 4 66.67% 18 0 100.00% 30 14 53.33%
+// REPORT-NEXT: _Z5func2ii 3 0 100.00% 8 0 100.00% 10 2 80.00%
// REPORT-NEXT: main 1 0 100.00% 6 0 100.00% 0 0 0.00%
// REPORT-NEXT: ---
-// REPORT-NEXT: TOTAL 42 5 88.10% 32 0 100.00% 40 16 60.00%
+// REPORT-NEXT: TOTAL 16 4 75.00% 32 0 100.00% 40 16 60.00%
diff --git a/llvm/test/tools/llvm-cov/branch-noShowBranch.test b/llvm/test/tools/llvm-cov/branch-noShowBranch.test
index 9f3cfd55f029b5..11a9a5a665b70e 100644
--- a/llvm/test/tools/llvm-cov/branch-noShowBranch.test
+++ b/llvm/test/tools/llvm-cov/branch-noShowBranch.test
@@ -9,16 +9,16 @@
// REPORT-NOT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover
// REPORT: ---
// REPORT-NOT: simple_loops 8 0 100.00% 9 0 100.00% 6 0 100.00%
-// REPORT-NOT: conditionals 24 0 100.00% 15 0 100.00% 16 2 87.50%
+// REPORT-NOT: conditionals 22 0 100.00% 15 0 100.00% 16 2 87.50%
// REPORT-NOT: early_exits 20 4 80.00% 25 2 92.00% 16 6 62.50%
// REPORT-NOT: jumps 39 12 69.23% 48 2 95.83% 26 9 65.38%
-// REPORT-NOT: switches 28 5 82.14% 38 4 89.47% 28 7 75.00%
+// REPORT-NOT: switches 27 4 85.19% 38 4 89.47% 28 7 75.00%
// REPORT-NOT: big_switch 25 1 96.00% 32 0 100.00% 30 6 80.00%
-// REPORT-NOT: boolean_operators 16 0 100.00% 13 0 100.00% 22 2 90.91%
-// REPORT-NOT: boolop_loops 19 0 100.00% 14 0 100.00% 16 2 87.50%
+// REPORT-NOT: boolean_operators 14 0 100.00% 13 0 100.00% 22 2 90.91%
+// REPORT-NOT: boolop_loops 15 0 100.00% 14 0 100.00% 16 2 87.50%
// REPORT-NOT: conditional_operator 4 2 50.00% 8 0 100.00% 4 2 50.00%
// REPORT-NOT: do_fallthrough 9 0 100.00% 12 0 100.00% 6 0 100.00%
// REPORT-NOT: main 1 0 100.00% 16 0 100.00% 0 0 0.00%
// REPORT-NOT: c-general.c:static_func 4 0 100.00% 4 0 100.00% 2 0 100.00%
-// REPORT: TOTAL 197 24 87.82% 234 8 96.58%
-// REPORT-NOT: TOTAL 197 24 87.82% 234 8 96.58% 172 36 79.07%
+// REPORT: TOTAL 188 23 87.77% 234 8 96.58%
+// REPORT-NOT: TOTAL 188 23 87.77% 234 8 96.58% 172 36 79.07%
diff --git a/llvm/test/tools/llvm-cov/mcdc-general-none.test b/llvm/test/tools/llvm-cov/mcdc-general-none.test
index b57b35d49c8c11..db95314ac950ab 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general-none.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general-none.test
@@ -34,10 +34,10 @@
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover MC/DC Conditions Miss Cover
// REPORT-NEXT: -------------------------------------------------------------------------------------------------------------------------------------------
-// REPORT-NEXT: _Z4testbbbb 25 0 100.00% 9 0 100.00% 24 2 91.67% 12 12 0.00%
+// REPORT-NEXT: _Z4testbbbb 21 0 100.00% 9 0 100.00% 24 2 91.67% 12 12 0.00%
// REPORT-NEXT: main 1 0 100.00% 11 0 100.00% 0 0 0.00% 0 0 0.00%
// REPORT-NEXT: ---
-// REPORT-NEXT: TOTAL 26 0 100.00% 20 0 100.00% 24 2 91.67% 12 12 0.00%
+// REPORT-NEXT: TOTAL 22 0 100.00% 20 0 100.00% 24 2 91.67% 12 12 0.00%
// Turn off MC/DC summary.
// RUN: llvm-cov report %S/Inputs/mcdc-general.o -instr-profile %t.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %s -check-prefix=REPORT_NOMCDC
@@ -67,7 +67,7 @@
// HTML-INDEX: <td class='column-entry-green'>
// HTML-INDEX: 100.00% (2/2)
// HTML-INDEX: 100.00% (20/20)
-// HTML-INDEX: 100.00% (26/26)
+// HTML-INDEX: 100.00% (22/22)
// HTML-INDEX: 91.67% (22/24)
// HTML-INDEX: 0.00% (0/12)
// HTML-INDEX: Totals
diff --git a/llvm/test/tools/llvm-cov/mcdc-general.test b/llvm/test/tools/llvm-cov/mcdc-general.test
index c1e95cb2bd92ac..7ae9e180c00c29 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general.test
@@ -100,10 +100,10 @@
// REPORT: Name Regions Miss Cover Lines Miss Cover Branches Miss Cover MC/DC Conditions Miss Cover
// REPORT-NEXT: -------------------------------------------------------------------------------------------------------------------------------------------
-// REPORT-NEXT: _Z4testbbbb 25 0 100.00% 9 0 100.00% 24 2 91.67% 12 2 83.33%
+// REPORT-NEXT: _Z4testbbbb 21 0 100.00% 9 0 100.00% 24 2 91.67% 12 2 83.33%
// REPORT-NEXT: main 1 0 100.00% 11 0 100.00% 0 0 0.00% 0 0 0.00%
// REPORT-NEXT: ---
-// REPORT-NEXT: TOTAL 26 0 100.00% 20 0 100.00% 24 2 91.67% 12 2 83.33%
+// REPORT-NEXT: TOTAL 22 0 100.00% 20 0 100.00% 24 2 91.67% 12 2 83.33%
// Turn off MC/DC summary.
// RUN: llvm-cov report %S/Inputs/mcdc-general.o -instr-profile %t.profdata -show-functions -path-equivalence=.,%S/Inputs %S/Inputs/mcdc-general.cpp | FileCheck %s -check-prefix=REPORT_NOMCDC
@@ -133,7 +133,7 @@
// HTML-INDEX: <td class='column-entry-green'>
// HTML-INDEX: 100.00% (2/2)
// HTML-INDEX: 100.00% (20/20)
-// HTML-INDEX: 100.00% (26/26)
+// HTML-INDEX: 100.00% (22/22)
// HTML-INDEX: 91.67% (22/24)
// HTML-INDEX: 83.33% (10/12)
// HTML-INDEX: Totals
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index 5c002a694f66ae..86d11266ecdd7c 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -63,14 +63,15 @@ auto sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) {
}
static std::pair<RegionCoverageInfo, LineCoverageInfo>
-sumRegions(ArrayRef<CountedRegion> CodeRegions, const CoverageData &CD) {
+sumRegions(const CoverageData &CD) {
// Compute the region coverage.
size_t NumCodeRegions = 0, CoveredRegions = 0;
- for (auto &CR : CodeRegions) {
- if (CR.Kind != CounterMappingRegion::CodeRegion)
+ for (auto I = CD.begin(), E = CD.end(); I != E; ++I) {
+ if (!I->IsRegionEntry || !I->HasCount || I->IsGapRegion)
continue;
+
++NumCodeRegions;
- if (CR.ExecutionCount != 0)
+ if (I->Count)
++CoveredRegions;
}
@@ -88,9 +89,8 @@ sumRegions(ArrayRef<CountedRegion> CodeRegions, const CoverageData &CD) {
LineCoverageInfo(CoveredLines, NumLines)};
}
-CoverageDataSummary::CoverageDataSummary(const CoverageData &CD,
- ArrayRef<CountedRegion> CodeRegions) {
- std::tie(RegionCoverage, LineCoverage) = sumRegions(CodeRegions, CD);
+CoverageDataSummary::CoverageDataSummary(const CoverageData &CD) {
+ std::tie(RegionCoverage, LineCoverage) = sumRegions(CD);
BranchCoverage = sumBranches(CD.getBranches());
MCDCCoverage = sumMCDCPairs(CD.getMCDCRecords());
}
@@ -103,7 +103,7 @@ FunctionCoverageSummary::get(const CoverageMapping &CM,
auto Summary =
FunctionCoverageSummary(Function.Name, Function.ExecutionCount);
- Summary += CoverageDataSummary(CD, Function.CountedRegions);
+ Summary += CoverageDataSummary(CD);
// Compute the branch coverage, including branches from expansions.
Summary.BranchCoverage += sumBranchExpansions(CM, CD.getExpansions());
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index d9210676c41bf3..42398ee06100e2 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -230,8 +230,7 @@ struct CoverageDataSummary {
MCDCCoverageInfo MCDCCoverage;
CoverageDataSummary() = default;
- CoverageDataSummary(const coverage::CoverageData &CD,
- ArrayRef<coverage::CountedRegion> CodeRegions);
+ CoverageDataSummary(const coverage::CoverageData &CD);
auto &operator+=(const CoverageDataSummary &RHS) {
RegionCoverage += RHS.RegionCoverage;
>From c1678ea160892c7b0912d9521866073a6b2ff839 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 16:11:10 +0900
Subject: [PATCH 28/30] llvm-cov: Use `getCoverageForFile()`
---
.../ProfileData/Coverage/CoverageMapping.h | 4 +-
.../ProfileData/Coverage/CoverageMapping.cpp | 6 ++-
.../test/tools/llvm-cov/branch-templates.test | 4 +-
.../tools/llvm-cov/coverage_watermark.test | 22 ++++----
llvm/test/tools/llvm-cov/zeroFunctionFile.c | 3 +-
llvm/tools/llvm-cov/CoverageReport.cpp | 42 +++++++++++----
llvm/tools/llvm-cov/CoverageSummaryInfo.cpp | 26 ----------
llvm/tools/llvm-cov/CoverageSummaryInfo.h | 51 +++++--------------
.../tools/llvm-cov/SourceCoverageViewHTML.cpp | 16 ++++--
9 files changed, 79 insertions(+), 95 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index c51733b46a1894..64416fdba1b247 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -1012,7 +1012,9 @@ class CoverageMapping {
/// The given filename must be the name as recorded in the coverage
/// information. That is, only names returned from getUniqueSourceFiles will
/// yield a result.
- CoverageData getCoverageForFile(StringRef Filename) const;
+ CoverageData getCoverageForFile(
+ StringRef Filename,
+ const DenseSet<const FunctionRecord *> &FilteredOutFunctions = {}) const;
/// Get the coverage for a particular function.
CoverageData getCoverageForFunction(const FunctionRecord &Function) const;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index feededcd7d1eb5..e7780b465186df 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -1422,7 +1422,9 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
}
-CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
+CoverageData CoverageMapping::getCoverageForFile(
+ StringRef Filename,
+ const DenseSet<const FunctionRecord *> &FilteredOutFunctions) const {
assert(SingleByteCoverage);
MergeableCoverageData FileCoverage(*SingleByteCoverage, Filename);
@@ -1432,6 +1434,8 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
getImpreciseRecordIndicesForFilename(Filename);
for (unsigned RecordIndex : RecordIndices) {
const FunctionRecord &Function = Functions[RecordIndex];
+ if (FilteredOutFunctions.count(&Function))
+ continue;
auto MainFileID = findMainViewFileID(Filename, Function);
auto FileIDs = gatherFileIDs(Filename, Function);
FileCoverage.addFunctionRegions(
diff --git a/llvm/test/tools/llvm-cov/branch-templates.test b/llvm/test/tools/llvm-cov/branch-templates.test
index d5535022239f5f..594a3ca533678b 100644
--- a/llvm/test/tools/llvm-cov/branch-templates.test
+++ b/llvm/test/tools/llvm-cov/branch-templates.test
@@ -26,6 +26,6 @@
// REPORTFILE: Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover
// REPORTFILE-NEXT: ---
-// REPORTFILE-NEXT: branch-templates.cpp 12 3 75.00% 2 0 100.00% 17 4 76.47% 8 4 50.00%
+// REPORTFILE-NEXT: branch-templates.cpp 12 2 83.33% 2 0 100.00% 17 3 82.35% 12 6 50.00%
// REPORTFILE-NEXT: ---
-// REPORTFILE-NEXT: TOTAL 12 3 75.00% 2 0 100.00% 17 4 76.47% 8 4 50.00%
+// REPORTFILE-NEXT: TOTAL 12 2 83.33% 2 0 100.00% 17 3 82.35% 12 6 50.00%
diff --git a/llvm/test/tools/llvm-cov/coverage_watermark.test b/llvm/test/tools/llvm-cov/coverage_watermark.test
index 5c48b4f0fb4bf4..818baa470bc38d 100644
--- a/llvm/test/tools/llvm-cov/coverage_watermark.test
+++ b/llvm/test/tools/llvm-cov/coverage_watermark.test
@@ -18,15 +18,15 @@ ORIGIN: <td class='column-entry-green'>
ORIGIN: 100.00% (2/2)
ORIGIN: <td class='column-entry-green'>
ORIGIN: 100.00% (3/3)
-ORIGIN: <td class='column-entry-red'>
-ORIGIN: 75.00% (9/12)
-ORIGIN: <td class='column-entry-red'>
-ORIGIN: 66.67% (4/6)
+ORIGIN: <td class='column-entry-yellow'>
+ORIGIN: 83.33% (10/12)
+ORIGIN: <td class='column-entry-yellow'>
+ORIGIN: 83.33% (5/6)
ORIGIN: <td class='column-entry-gray'>
ORIGIN: - (0/0)
ORIGIN: </tr>
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 80,70 %S/showTemplateInstantiations.cpp
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 90,70 %S/showTemplateInstantiations.cpp
RUN: FileCheck -check-prefix=DOWNGRADE1 %s -input-file %t.html.dir/index.html
DOWNGRADE:1 Totals
@@ -35,9 +35,9 @@ DOWNGRADE1: 100.00% (2/2)
DOWNGRADE1: <td class='column-entry-green'>
DOWNGRADE1: 100.00% (3/3)
DOWNGRADE1: <td class='column-entry-yellow'>
-DOWNGRADE1: 75.00% (9/12)
-DOWNGRADE1: <td class='column-entry-red'>
-DOWNGRADE1: 66.67% (4/6)
+DOWNGRADE1: 83.33% (10/12)
+DOWNGRADE1: <td class='column-entry-yellow'>
+DOWNGRADE1: 83.33% (5/6)
DOWNGRADE1: <td class='column-entry-gray'>
DOWNGRADE1: - (0/0)
DOWNGRADE1: </tr>
@@ -51,9 +51,9 @@ DOWNGRADE2: 100.00% (2/2)
DOWNGRADE2: <td class='column-entry-green'>
DOWNGRADE2: 100.00% (3/3)
DOWNGRADE2: <td class='column-entry-green'>
-DOWNGRADE2: 75.00% (9/12)
-DOWNGRADE2: <td class='column-entry-yellow'>
-DOWNGRADE2: 66.67% (4/6)
+DOWNGRADE2: 83.33% (10/12)
+DOWNGRADE2: <td class='column-entry-green'>
+DOWNGRADE2: 83.33% (5/6)
DOWNGRADE1: <td class='column-entry-gray'>
DOWNGRADE1: - (0/0)
DOWNGRADE1: </tr>
diff --git a/llvm/test/tools/llvm-cov/zeroFunctionFile.c b/llvm/test/tools/llvm-cov/zeroFunctionFile.c
index f463007fe7f60f..28caa5ac241650 100644
--- a/llvm/test/tools/llvm-cov/zeroFunctionFile.c
+++ b/llvm/test/tools/llvm-cov/zeroFunctionFile.c
@@ -16,5 +16,4 @@ int main() {
// RUN: llvm-cov show -j 1 %S/Inputs/zeroFunctionFile.covmapping -format html -instr-profile %t.profdata -o %t.dir
// RUN: FileCheck %s -input-file=%t.dir/index.html -check-prefix=HTML
// HTML-NO: 0.00% (0/0)
-// HTML: Files which contain no functions
-// HTML: zeroFunctionFile.h
+// HTML-NOT: Files which contain no functions
diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp
index 00aea4039bfdeb..0046b968756dd0 100644
--- a/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -446,27 +446,47 @@ void CoverageReport::prepareSingleFileReport(const StringRef Filename,
const coverage::CoverageMapping *Coverage,
const CoverageViewOptions &Options, const unsigned LCP,
FileCoverageSummary *FileReport, const CoverageFilter *Filters) {
+ DenseSet<const coverage::FunctionRecord *> FilteredOutFunctions;
+ assert(FileReport->empty());
for (const auto &Group : Coverage->getInstantiationGroups(Filename)) {
- std::vector<FunctionCoverageSummary> InstantiationSummaries;
+ bool Updated = false;
for (const coverage::FunctionRecord *F : Group.getInstantiations()) {
- if (!Filters->matches(*Coverage, *F))
+ if (!Filters->matches(*Coverage, *F)) {
+ FilteredOutFunctions.insert(F);
continue;
- auto InstantiationSummary = FunctionCoverageSummary::get(*Coverage, *F);
- FileReport->addInstantiation(InstantiationSummary);
- InstantiationSummaries.push_back(InstantiationSummary);
+ }
+ FileReport->InstantiationCoverage.addFunction(
+ /*Covered=*/F->ExecutionCount > 0);
+ Updated = true;
}
- if (InstantiationSummaries.empty())
+ if (!Updated)
continue;
- auto GroupSummary =
- FunctionCoverageSummary::get(Group, InstantiationSummaries);
+ if (Options.Debug) {
+ std::string Name;
+ if (Group.hasName()) {
+ Name = std::string(Group.getName());
+ } else {
+ llvm::raw_string_ostream OS(Name);
+ OS << "Definition at line " << Group.getLine() << ", column "
+ << Group.getColumn();
+ }
- if (Options.Debug)
- outs() << "InstantiationGroup: " << GroupSummary.Name << " with "
+ outs() << "InstantiationGroup: " << Name << " with "
<< "size = " << Group.size() << "\n";
+ }
- FileReport->addFunction(GroupSummary);
+ FileReport->FunctionCoverage.addFunction(
+ /*Covered=*/Group.getTotalExecutionCount() > 0);
}
+
+ auto FileCoverage =
+ Coverage->getCoverageForFile(Filename, FilteredOutFunctions);
+ if (FileCoverage.empty())
+ return;
+
+ *static_cast<CoverageDataSummary *>(FileReport) +=
+ CoverageDataSummary(FileCoverage);
}
std::vector<FileCoverageSummary> CoverageReport::prepareFileReports(
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index 86d11266ecdd7c..745a92103bccc9 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -110,29 +110,3 @@ FunctionCoverageSummary::get(const CoverageMapping &CM,
return Summary;
}
-
-FunctionCoverageSummary
-FunctionCoverageSummary::get(const InstantiationGroup &Group,
- ArrayRef<FunctionCoverageSummary> Summaries) {
- std::string Name;
- if (Group.hasName()) {
- Name = std::string(Group.getName());
- } else {
- llvm::raw_string_ostream OS(Name);
- OS << "Definition at line " << Group.getLine() << ", column "
- << Group.getColumn();
- }
-
- FunctionCoverageSummary Summary(Name, Group.getTotalExecutionCount());
- Summary.RegionCoverage = Summaries[0].RegionCoverage;
- Summary.LineCoverage = Summaries[0].LineCoverage;
- Summary.BranchCoverage = Summaries[0].BranchCoverage;
- Summary.MCDCCoverage = Summaries[0].MCDCCoverage;
- for (const auto &FCS : Summaries.drop_front()) {
- Summary.RegionCoverage.merge(FCS.RegionCoverage);
- Summary.LineCoverage.merge(FCS.LineCoverage);
- Summary.BranchCoverage.merge(FCS.BranchCoverage);
- Summary.MCDCCoverage.merge(FCS.MCDCCoverage);
- }
- return Summary;
-}
diff --git a/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index 42398ee06100e2..09ceba5de72719 100644
--- a/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -41,11 +41,6 @@ class RegionCoverageInfo {
return *this;
}
- void merge(const RegionCoverageInfo &RHS) {
- Covered = std::max(Covered, RHS.Covered);
- NumRegions = std::max(NumRegions, RHS.NumRegions);
- }
-
size_t getCovered() const { return Covered; }
size_t getNumRegions() const { return NumRegions; }
@@ -82,11 +77,6 @@ class LineCoverageInfo {
return *this;
}
- void merge(const LineCoverageInfo &RHS) {
- Covered = std::max(Covered, RHS.Covered);
- NumLines = std::max(NumLines, RHS.NumLines);
- }
-
size_t getCovered() const { return Covered; }
size_t getNumLines() const { return NumLines; }
@@ -123,11 +113,6 @@ class BranchCoverageInfo {
return *this;
}
- void merge(const BranchCoverageInfo &RHS) {
- Covered = std::max(Covered, RHS.Covered);
- NumBranches = std::max(NumBranches, RHS.NumBranches);
- }
-
size_t getCovered() const { return Covered; }
size_t getNumBranches() const { return NumBranches; }
@@ -164,11 +149,6 @@ class MCDCCoverageInfo {
return *this;
}
- void merge(const MCDCCoverageInfo &RHS) {
- CoveredPairs = std::max(CoveredPairs, RHS.CoveredPairs);
- NumPairs = std::max(NumPairs, RHS.NumPairs);
- }
-
size_t getCoveredPairs() const { return CoveredPairs; }
size_t getNumPairs() const { return NumPairs; }
@@ -232,6 +212,13 @@ struct CoverageDataSummary {
CoverageDataSummary() = default;
CoverageDataSummary(const coverage::CoverageData &CD);
+ bool empty() const {
+ return (RegionCoverage.getNumRegions() == 0 &&
+ LineCoverage.getNumLines() == 0 &&
+ BranchCoverage.getNumBranches() == 0 &&
+ MCDCCoverage.getNumPairs() == 0);
+ }
+
auto &operator+=(const CoverageDataSummary &RHS) {
RegionCoverage += RHS.RegionCoverage;
LineCoverage += RHS.LineCoverage;
@@ -253,12 +240,6 @@ struct FunctionCoverageSummary : CoverageDataSummary {
/// mapping record.
static FunctionCoverageSummary get(const coverage::CoverageMapping &CM,
const coverage::FunctionRecord &Function);
-
- /// Compute the code coverage summary for an instantiation group \p Group,
- /// given a list of summaries for each instantiation in \p Summaries.
- static FunctionCoverageSummary
- get(const coverage::InstantiationGroup &Group,
- ArrayRef<FunctionCoverageSummary> Summaries);
};
/// A summary of file's code coverage.
@@ -270,24 +251,18 @@ struct FileCoverageSummary : CoverageDataSummary {
FileCoverageSummary() = default;
FileCoverageSummary(StringRef Name) : Name(Name) {}
+ bool empty() const {
+ return (CoverageDataSummary::empty() &&
+ FunctionCoverage.getNumFunctions() == 0 &&
+ InstantiationCoverage.getNumFunctions() == 0);
+ }
+
FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
*static_cast<CoverageDataSummary *>(this) += RHS;
FunctionCoverage += RHS.FunctionCoverage;
InstantiationCoverage += RHS.InstantiationCoverage;
return *this;
}
-
- void addFunction(const FunctionCoverageSummary &Function) {
- RegionCoverage += Function.RegionCoverage;
- LineCoverage += Function.LineCoverage;
- BranchCoverage += Function.BranchCoverage;
- MCDCCoverage += Function.MCDCCoverage;
- FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
- }
-
- void addInstantiation(const FunctionCoverageSummary &Function) {
- InstantiationCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
- }
};
/// A cache for demangled symbols.
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index c94d3853fc0143..cb0ea6e0cdafc3 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -23,6 +23,16 @@ using namespace llvm;
namespace {
+template <class SummaryTy>
+bool IsSummaryEmpty(const SummaryTy &Report, const CoverageViewOptions &Opts) {
+ return !(Report.FunctionCoverage.getNumFunctions() ||
+ (Opts.ShowInstantiationSummary &&
+ Report.InstantiationCoverage.getNumFunctions()) ||
+ (Opts.ShowRegionSummary && Report.RegionCoverage.getNumRegions()) ||
+ (Opts.ShowBranchSummary && Report.BranchCoverage.getNumBranches()) ||
+ (Opts.ShowMCDCSummary && Report.MCDCCoverage.getNumPairs()));
+}
+
// Return a string with the special characters in \p Str escaped.
std::string escape(StringRef Str, const CoverageViewOptions &Opts) {
std::string TabExpandedResult;
@@ -666,7 +676,7 @@ Error CoveragePrinterHTML::createIndexFile(
Coverage, Totals, SourceFiles, Opts, Filters);
bool EmptyFiles = false;
for (unsigned I = 0, E = FileReports.size(); I < E; ++I) {
- if (FileReports[I].FunctionCoverage.getNumFunctions())
+ if (!IsSummaryEmpty(FileReports[I], Opts))
emitFileSummary(OSRef, SourceFiles[I], FileReports[I]);
else
EmptyFiles = true;
@@ -734,7 +744,7 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport {
// Make directories at the top of the table.
for (auto &&SubDir : SubDirs) {
auto &Report = SubDir.second.first;
- if (!Report.FunctionCoverage.getNumFunctions())
+ if (IsSummaryEmpty(Report, Printer.Opts))
EmptyFiles.push_back(&Report);
else
emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,
@@ -743,7 +753,7 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport {
for (auto &&SubFile : SubFiles) {
auto &Report = SubFile.second;
- if (!Report.FunctionCoverage.getNumFunctions())
+ if (IsSummaryEmpty(Report, Printer.Opts))
EmptyFiles.push_back(&Report);
else
emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,
>From 273eea73c158acbf7140bd599554b2ba02d88097 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 16:14:24 +0900
Subject: [PATCH 29/30] llvm-cov: Introduce
`--merge-instantiations=<MergeStrategy>`
---
.../ProfileData/Coverage/CoverageMapping.h | 82 ++++++++-
.../ProfileData/Coverage/CoverageMapping.cpp | 170 ++++++++++++++++--
.../llvm-cov/Inputs/branch-templates.cpp | 6 +-
.../llvm-cov/Inputs/mcdc-templates-merge.cpp | 54 ++++++
.../Inputs/mcdc-templates-merge.proftext | 73 ++++++++
.../llvm-cov/Inputs/mcdc-templates-merge.yaml | 105 +++++++++++
.../tools/llvm-cov/branch-export-json.test | 2 +-
.../tools/llvm-cov/branch-export-lcov.test | 4 +-
llvm/test/tools/llvm-cov/branch-macros.test | 9 +
.../test/tools/llvm-cov/branch-templates.test | 4 +-
.../tools/llvm-cov/mcdc-templates-merge.test | 41 +++++
llvm/tools/llvm-cov/CodeCoverage.cpp | 12 +-
llvm/tools/llvm-cov/CoverageReport.cpp | 4 +-
llvm/tools/llvm-cov/CoverageViewOptions.h | 2 +
llvm/tools/llvm-cov/SourceCoverageView.cpp | 4 +-
15 files changed, 540 insertions(+), 32 deletions(-)
create mode 100644 llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp
create mode 100644 llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.proftext
create mode 100644 llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.yaml
create mode 100644 llvm/test/tools/llvm-cov/mcdc-templates-merge.test
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 64416fdba1b247..d6df8403a2cd1c 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -59,6 +59,12 @@ namespace coverage {
class CoverageMappingReader;
struct CoverageMappingRecord;
+enum class MergeStrategy {
+ Merge,
+ Any,
+ All,
+};
+
enum class coveragemap_error {
success = 0,
eof,
@@ -375,6 +381,32 @@ struct CountedRegion : public CounterMappingRegion {
: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
FalseExecutionCount(FalseExecutionCount), TrueFolded(false),
FalseFolded(false) {}
+
+ LineColPair viewLoc() const { return startLoc(); }
+
+ bool isMergeable(const CountedRegion &RHS) const {
+ return (this->viewLoc() == RHS.viewLoc());
+ }
+
+ void merge(const CountedRegion &RHS, MergeStrategy Strategy);
+
+ /// Returns comparable rank value in selecting a better Record for merging.
+ auto getMergeRank(MergeStrategy Strategy) const {
+ assert(isBranch() && "Dedicated to Branch");
+ assert(Strategy == MergeStrategy::Any && "Dedicated to Any");
+ unsigned m = 0;
+ // Prefer both Counts have values.
+ m = (m << 1) | (ExecutionCount != 0 && FalseExecutionCount != 0);
+ // Prefer both are unfolded.
+ m = (m << 1) | (!TrueFolded && !FalseFolded);
+ // Prefer either Count has value.
+ m = (m << 1) | (ExecutionCount != 0 || FalseExecutionCount != 0);
+ // Prefer either is unfolded.
+ m = (m << 1) | (!TrueFolded || !FalseFolded);
+ return std::make_pair(m, ExecutionCount + FalseExecutionCount);
+ }
+
+ void commit() const {}
};
/// MCDC Record grouping all information together.
@@ -462,6 +494,19 @@ struct MCDCRecord {
findIndependencePairs();
}
+ inline LineColPair viewLoc() const { return Region.endLoc(); }
+
+ bool isMergeable(const MCDCRecord &RHS) const {
+ return (this->viewLoc() == RHS.viewLoc() && this->PosToID == RHS.PosToID &&
+ this->CondLoc == RHS.CondLoc);
+ }
+
+ // This may invalidate IndependencePairs
+ // MCDCRecord &operator+=(const MCDCRecord &RHS);
+ void merge(MCDCRecord &&RHS, MergeStrategy Strategy);
+
+ void commit() { findIndependencePairs(); }
+
// Compare executed test vectors against each other to find an independence
// pairs for each condition. This processing takes the most time.
void findIndependencePairs();
@@ -512,15 +557,42 @@ struct MCDCRecord {
return (*IndependencePairs)[PosToID[Condition]];
}
- float getPercentCovered() const {
- unsigned Folded = 0;
+ std::pair<unsigned, unsigned> getCoveredCount() const {
unsigned Covered = 0;
+ unsigned Folded = 0;
for (unsigned C = 0; C < getNumConditions(); C++) {
if (isCondFolded(C))
Folded++;
else if (isConditionIndependencePairCovered(C))
Covered++;
}
+ return {Covered, Folded};
+ }
+
+ /// Returns comparable rank value in selecting a better Record for merging.
+ std::tuple<unsigned, unsigned, unsigned>
+ getMergeRank(MergeStrategy Strategy) const {
+ auto [Covered, Folded] = getCoveredCount();
+ auto NumTVs = getNumTestVectors();
+ switch (Strategy) {
+ case MergeStrategy::Merge:
+ case MergeStrategy::Any:
+ return {
+ Covered, // The largest covered number
+ ~Folded, // Less folded is better
+ NumTVs, // Show more test vectors
+ };
+ case MergeStrategy::All:
+ return {
+ ~Covered, // The smallest covered number
+ ~Folded, // Less folded is better
+ NumTVs, // Show more test vectors
+ };
+ }
+ }
+
+ float getPercentCovered() const {
+ auto [Covered, Folded] = getCoveredCount();
unsigned Total = getNumConditions() - Folded;
if (Total == 0)
@@ -1013,11 +1085,13 @@ class CoverageMapping {
/// information. That is, only names returned from getUniqueSourceFiles will
/// yield a result.
CoverageData getCoverageForFile(
- StringRef Filename,
+ StringRef Filename, MergeStrategy Strategy = MergeStrategy::Merge,
const DenseSet<const FunctionRecord *> &FilteredOutFunctions = {}) const;
/// Get the coverage for a particular function.
- CoverageData getCoverageForFunction(const FunctionRecord &Function) const;
+ CoverageData
+ getCoverageForFunction(const FunctionRecord &Function,
+ MergeStrategy Strategy = MergeStrategy::Merge) const;
/// Get the coverage for an expansion within a coverage set.
CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index e7780b465186df..dbbf5b03d0205e 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -221,6 +221,58 @@ Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const {
return LastPoppedValue;
}
+void CountedRegion::merge(const CountedRegion &RHS, MergeStrategy Strategy) {
+ assert(this->isBranch() && RHS.isBranch());
+ auto MergeCounts = [Strategy](uint64_t &LHSCount, bool &LHSFolded,
+ uint64_t RHSCount, bool RHSFolded) {
+ switch (Strategy) {
+ default:
+ llvm_unreachable("Don't perform by-parameter merging");
+ case MergeStrategy::Merge:
+ LHSCount += RHSCount;
+ LHSFolded = (LHSFolded && !LHSCount && RHSFolded);
+ break;
+ case MergeStrategy::All:
+ LHSCount = (LHSFolded ? RHSCount
+ : RHSFolded ? LHSCount
+ : std::min(LHSCount, RHSCount));
+ LHSFolded = (LHSFolded && RHSFolded);
+ break;
+ }
+ };
+
+ switch (Strategy) {
+ case MergeStrategy::Any:
+ // Take either better (more satisfied) hand side.
+ // FIXME: Really needed? Better just to merge?
+ if (this->getMergeRank(Strategy) < RHS.getMergeRank(Strategy))
+ *this = RHS;
+ break;
+ case MergeStrategy::Merge:
+ case MergeStrategy::All:
+ // Able to merge by parameter.
+ MergeCounts(this->ExecutionCount, this->TrueFolded, RHS.ExecutionCount,
+ RHS.TrueFolded);
+ MergeCounts(this->FalseExecutionCount, this->FalseFolded,
+ RHS.FalseExecutionCount, RHS.FalseFolded);
+ break;
+ }
+}
+
+void MCDCRecord::merge(MCDCRecord &&RHS, MergeStrategy Strategy) {
+ assert(this->PosToID == RHS.PosToID);
+ assert(this->CondLoc == RHS.CondLoc);
+
+ switch (Strategy) {
+ case MergeStrategy::Merge:
+ case MergeStrategy::Any:
+ case MergeStrategy::All:
+ if (this->getMergeRank(Strategy) < RHS.getMergeRank(Strategy))
+ *this = std::move(RHS);
+ return;
+ }
+}
+
// 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.
@@ -1272,7 +1324,8 @@ class SegmentBuilder {
/// Combine counts of regions which cover the same area.
static ArrayRef<CountedRegion>
- combineRegions(MutableArrayRef<CountedRegion> Regions) {
+ combineRegions(MutableArrayRef<CountedRegion> Regions,
+ MergeStrategy Strategy) {
if (Regions.empty())
return Regions;
auto Active = Regions.begin();
@@ -1298,8 +1351,22 @@ class SegmentBuilder {
// value for that area.
// We add counts of the regions of the same kind as the active region
// to handle the both situations.
- if (I->Kind == Active->Kind)
+ if (I->Kind != Active->Kind)
+ continue;
+
+ switch (Strategy) {
+ case MergeStrategy::Merge:
Active->ExecutionCount += I->ExecutionCount;
+ break;
+ case MergeStrategy::Any:
+ Active->ExecutionCount =
+ std::max(Active->ExecutionCount, I->ExecutionCount);
+ break;
+ case MergeStrategy::All:
+ Active->ExecutionCount =
+ std::min(Active->ExecutionCount, I->ExecutionCount);
+ break;
+ }
}
return Regions.drop_back(std::distance(++Active, End));
}
@@ -1307,12 +1374,13 @@ class SegmentBuilder {
public:
/// Build a sorted list of CoverageSegments from a list of Regions.
static std::vector<CoverageSegment>
- buildSegments(MutableArrayRef<CountedRegion> Regions) {
+ buildSegments(MutableArrayRef<CountedRegion> Regions,
+ MergeStrategy Strategy) {
std::vector<CoverageSegment> Segments;
SegmentBuilder Builder(Segments);
sortNestedRegions(Regions);
- ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
+ ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions, Strategy);
LLVM_DEBUG({
dbgs() << "Combined regions:\n";
@@ -1342,11 +1410,78 @@ class SegmentBuilder {
}
};
+template <class RecTy>
+static void mergeRecords(std::vector<RecTy> &Records, MergeStrategy Strategy) {
+ if (Records.empty())
+ return;
+
+ std::vector<RecTy> NewRecords;
+
+ assert(Records.size() <= std::numeric_limits<unsigned>::max());
+
+ // Build up sorted indices (rather than pointers) of Records.
+ SmallVector<unsigned, 1> BIdxs(Records.size());
+ std::iota(BIdxs.begin(), BIdxs.end(), 0);
+ llvm::stable_sort(BIdxs, [&](auto A, auto B) {
+ auto StartA = Records[A].viewLoc();
+ auto StartB = Records[B].viewLoc();
+ return (std::tie(StartA, A) < std::tie(StartB, B));
+ });
+
+ // 1st element should be stored into SubView.
+ auto I = BIdxs.begin(), E = BIdxs.end();
+ SmallVector<RecTy, 1> ViewRecords{Records[*I++]};
+
+ auto findMergeableInViewRecords = [&](const RecTy &Branch) {
+ auto I = ViewRecords.rbegin(), E = ViewRecords.rend();
+ for (; I != E; ++I)
+ if (I->isMergeable(Branch))
+ return I;
+
+ // Not mergeable.
+ return E;
+ };
+
+ auto addRecordToSubView = [&] {
+ assert(!ViewRecords.empty() && "Should have the back");
+ for (auto &Acc : ViewRecords) {
+ Acc.commit();
+ NewRecords.push_back(std::move(Acc));
+ }
+ };
+
+ for (; I != E; ++I) {
+ assert(!ViewRecords.empty() && "Should have the back in the loop");
+ auto &AccB = ViewRecords.back();
+ auto &Branch = Records[*I];
+
+ // Flush current and create the next SubView at the different line.
+ if (AccB.viewLoc().first != Branch.viewLoc().first) {
+ addRecordToSubView();
+ ViewRecords = {Branch};
+ } else if (auto AccI = findMergeableInViewRecords(Branch);
+ AccI != ViewRecords.rend()) {
+ // Merge the current Branch into the back of SubView.
+ AccI->merge(std::move(Branch), Strategy);
+ } else {
+ // Not mergeable.
+ ViewRecords.push_back(Branch);
+ }
+ }
+
+ // Flush the last SubView.
+ addRecordToSubView();
+
+ // Replace
+ Records = std::move(NewRecords);
+}
+
struct MergeableCoverageData : public CoverageData {
std::vector<CountedRegion> CodeRegions;
+ MergeStrategy Strategy;
- MergeableCoverageData(bool Single, StringRef Filename)
- : CoverageData(Single, Filename) {}
+ MergeableCoverageData(MergeStrategy Strategy, bool Single, StringRef Filename)
+ : CoverageData(Single, Filename), Strategy(Strategy) {}
void addFunctionRegions(
const FunctionRecord &Function,
@@ -1368,8 +1503,11 @@ struct MergeableCoverageData : public CoverageData {
MCDCRecords.push_back(MR);
}
- CoverageData buildSegments() {
- Segments = SegmentBuilder::buildSegments(CodeRegions);
+ CoverageData merge(MergeStrategy Strategy) {
+ mergeRecords(BranchRegions, Strategy);
+ mergeRecords(MCDCRecords, Strategy);
+
+ Segments = SegmentBuilder::buildSegments(CodeRegions, Strategy);
return CoverageData(std::move(*this));
}
};
@@ -1423,10 +1561,10 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
}
CoverageData CoverageMapping::getCoverageForFile(
- StringRef Filename,
+ StringRef Filename, MergeStrategy Strategy,
const DenseSet<const FunctionRecord *> &FilteredOutFunctions) const {
assert(SingleByteCoverage);
- MergeableCoverageData FileCoverage(*SingleByteCoverage, Filename);
+ MergeableCoverageData FileCoverage(Strategy, *SingleByteCoverage, Filename);
// Look up the function records in the given file. Due to hash collisions on
// the filename, we may get back some records that are not in the file.
@@ -1445,7 +1583,7 @@ CoverageData CoverageMapping::getCoverageForFile(
LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
- return FileCoverage.buildSegments();
+ return FileCoverage.merge(Strategy);
}
std::vector<InstantiationGroup>
@@ -1474,13 +1612,14 @@ CoverageMapping::getInstantiationGroups(StringRef Filename) const {
}
CoverageData
-CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
+CoverageMapping::getCoverageForFunction(const FunctionRecord &Function,
+ MergeStrategy Strategy) const {
auto MainFileID = findMainViewFileID(Function);
if (!MainFileID)
return CoverageData();
assert(SingleByteCoverage);
- MergeableCoverageData FunctionCoverage(*SingleByteCoverage,
+ MergeableCoverageData FunctionCoverage(Strategy, *SingleByteCoverage,
Function.Filenames[*MainFileID]);
FunctionCoverage.addFunctionRegions(
Function, [&](auto &CR) { return (CR.FileID == *MainFileID); },
@@ -1489,7 +1628,7 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const {
LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name
<< "\n");
- return FunctionCoverage.buildSegments();
+ return FunctionCoverage.merge(Strategy);
}
CoverageData CoverageMapping::getCoverageForExpansion(
@@ -1511,7 +1650,8 @@ CoverageData CoverageMapping::getCoverageForExpansion(
LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "
<< Expansion.FileID << "\n");
- ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);
+ ExpansionCoverage.Segments =
+ SegmentBuilder::buildSegments(Regions, MergeStrategy::Merge);
return ExpansionCoverage;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp b/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
index 4d932eaf5944a8..d8a7c056f36779 100644
--- a/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/branch-templates.cpp
@@ -11,9 +11,9 @@ void unused(T x) {
template<typename T>
int func(T x) {
- if(x) // BRCOV: | Branch ([[@LINE]]:6): [True: 0, False: 1]
- return 0; // BRCOV: | Branch ([[@LINE-1]]:6): [True: 1, False: 0]
- else // BRCOV: | Branch ([[@LINE-2]]:6): [True: 0, False: 1]
+ if(x) // BRCOV: | Branch ([[@LINE]]:6): [True: 1, False: {{2|1}}]
+ return 0;
+ else
return 1;
int j = 1;
}
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp
new file mode 100644
index 00000000000000..09c2e0980cca85
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp
@@ -0,0 +1,54 @@
+#include <cstdio>
+
+template <typename Ty>
+bool ab(Ty a, Ty b) {
+ return (a && b);
+}
+// MERGE: [[@LINE-2]]| 4| return
+// ANY: [[@LINE-3]]| 2| return
+// ALL: [[@LINE-4]]| 0| return
+
+// MERGE: MC/DC Coverage for Decision{{[:]}} 50.00%
+// ANY: MC/DC Coverage for Decision{{[:]}} 50.00%
+// ALL: MC/DC Coverage for Decision{{[:]}} 0.00%
+
+// CHECK: _Z2abIbEbT_S0_{{[:]}}
+// CHECK: MC/DC Coverage for Decision{{[:]}} 50.00%
+
+// CHECK: _Z2abIxEbT_S0_{{[:]}}
+// CHECK: MC/DC Coverage for Decision{{[:]}} 50.00%
+
+// CHECK: Unexecuted instantiation{{[:]}} _Z2abIdEbT_S0_
+
+template <bool C>
+bool Cab(bool a, bool b) {
+ return (a && b && C);
+}
+// MERGE: [[@LINE-2]]| 4| return
+// ANY: [[@LINE-3]]| 2| return
+// ALL: [[@LINE-4]]| 2| return
+
+// MERGE: MC/DC Coverage for Decision{{[:]}} 50.00%
+// ANY: MC/DC Coverage for Decision{{[:]}} 50.00%
+// ALL: MC/DC Coverage for Decision{{[:]}} 0.00%
+
+// CHECK: _Z3CabILb0EEbbb{{[:]}}
+// CHECK: MC/DC Coverage for Decision{{[:]}} 0.00%
+
+// CHECK: _Z3CabILb1EEbbb{{[:]}}
+// CHECK: MC/DC Coverage for Decision{{[:]}} 50.00%
+
+// CHECK: [[@LINE+1]]| 1|int main
+int main(int argc, char **argv) {
+ printf("%d\n", Cab<false>(false, false));
+ printf("%d\n", Cab<false>(true, true));
+ printf("%d\n", Cab<true>(true, false));
+ printf("%d\n", Cab<true>(true, true));
+ printf("%d\n", ab(false, false));
+ printf("%d\n", ab(true, true));
+ printf("%d\n", ab(1LL, 0LL));
+ printf("%d\n", ab(1LL, 1LL));
+ if (argc == 2)
+ printf("%d\n", ab(0.0, 0.0));
+ return 0;
+}
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.proftext b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.proftext
new file mode 100644
index 00000000000000..61369462b2fd46
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.proftext
@@ -0,0 +1,73 @@
+_Z2abIbEbT_S0_
+# Func Hash:
+1550
+# Num Counters:
+3
+# Counter Values:
+2
+1
+1
+# Num Bitmap Bytes:
+$1
+# Bitmap Byte Values:
+0x5
+
+
+_Z2abIxEbT_S0_
+# Func Hash:
+1550
+# Num Counters:
+3
+# Counter Values:
+2
+2
+1
+# Num Bitmap Bytes:
+$1
+# Bitmap Byte Values:
+0x6
+
+
+_Z3CabILb0EEbbb
+# Func Hash:
+99214
+# Num Counters:
+5
+# Counter Values:
+2
+1
+0
+1
+1
+# Num Bitmap Bytes:
+$1
+# Bitmap Byte Values:
+0x5
+
+
+_Z3CabILb1EEbbb
+# Func Hash:
+99214
+# Num Counters:
+5
+# Counter Values:
+2
+1
+1
+2
+1
+# Num Bitmap Bytes:
+$1
+# Bitmap Byte Values:
+0xa
+
+
+main
+# Func Hash:
+175973464
+# Num Counters:
+2
+# Counter Values:
+1
+0
+
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.yaml b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.yaml
new file mode 100644
index 00000000000000..91d701a2172f82
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.yaml
@@ -0,0 +1,105 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_X86_64
+ SectionHeaderStringTable: .strtab
+Sections:
+ - Name: __llvm_covfun
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: FAD58DE7366495DB2500000058247D0A00000000249EC986A505B62F010101010505012A210C020109070010200502000700100500110185808080080501050021
+ - Name: '__llvm_covfun (1)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 9CC3B348501DBFE8480000008E83010000000000249EC986A505B62F010103010D0D1105090901181A020201010B000C01000B0011280403000B0016300D02010300000B000C0D0010001130110603020000100011050015001630000A02000000150016
+ - Name: '__llvm_covfun (2)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 9873627177A03F8E460000008E83010000000000249EC986A505B62F010102010D0D110901181A020201010B000C01000B0011280403000B0016300D02010300000B000C0D0010001130110603020000100011050015001630090002000000150016
+ - Name: '__llvm_covfun (3)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: BF407A207503B266320000000E06000000000000249EC986A505B62F0101020105050906010415020201010B000C280302000B0011300502010200000B000C050010001130090602000000100011
+ - Name: '__llvm_covfun (4)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 8A05A22CB467C37D320000000E06000000000000249EC986A505B62F0101020105050906010415020201010B000C280302000B0011300502010200000B000C050010001130090602000000100011
+ - Name: '__llvm_covfun (5)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 1700192CAC8F3F26320000000E06000000000000249EC986A505B62F0101020105050906010415020201010B000C280302000B0011300502010200000B000C050010001130090602000000100011
+ - Name: __llvm_covmap
+ Type: SHT_PROGBITS
+ Flags: [ SHF_GNU_RETAIN ]
+ AddressAlign: 0x8
+ Content: 000000001D0000000000000006000000021A0000186D6364632D74656D706C617465732D6D657267652E637070000000
+ - Name: __llvm_prf_names
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_GNU_RETAIN ]
+ AddressAlign: 0x1
+ Content: 51006D61696E015F5A33436162494C62304545626262015F5A33436162494C62314545626262015F5A32616249624562545F53305F015F5A32616249784562545F53305F015F5A32616249644562545F53305F
+ - Type: SectionHeaderTable
+ Sections:
+ - Name: .strtab
+ - Name: __llvm_covfun
+ - Name: '__llvm_covfun (1)'
+ - Name: '__llvm_covfun (2)'
+ - Name: '__llvm_covfun (3)'
+ - Name: '__llvm_covfun (4)'
+ - Name: '__llvm_covfun (5)'
+ - Name: __llvm_covmap
+ - Name: __llvm_prf_names
+ - Name: .symtab
+Symbols:
+ - Name: __llvm_covmap
+ Type: STT_SECTION
+ Section: __llvm_covmap
+ - Name: __llvm_prf_names
+ Type: STT_SECTION
+ Section: __llvm_prf_names
+ - Name: __covrec_DB956436E78DD5FAu
+ Type: STT_OBJECT
+ Section: __llvm_covfun
+ Binding: STB_WEAK
+ Size: 0x41
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_E8BF1D5048B3C39Cu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (1)'
+ Binding: STB_WEAK
+ Size: 0x64
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_8E3FA07771627398u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (2)'
+ Binding: STB_WEAK
+ Size: 0x62
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_66B20375207A40BFu
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (3)'
+ Binding: STB_WEAK
+ Size: 0x4E
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_7DC367B42CA2058Au
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (4)'
+ Binding: STB_WEAK
+ Size: 0x4E
+ Other: [ STV_HIDDEN ]
+ - Name: __covrec_263F8FAC2C190017u
+ Type: STT_OBJECT
+ Section: '__llvm_covfun (5)'
+ Binding: STB_WEAK
+ Size: 0x4E
+ Other: [ STV_HIDDEN ]
+...
diff --git a/llvm/test/tools/llvm-cov/branch-export-json.test b/llvm/test/tools/llvm-cov/branch-export-json.test
index 4278482c6d870e..77e2bab7d9eb33 100644
--- a/llvm/test/tools/llvm-cov/branch-export-json.test
+++ b/llvm/test/tools/llvm-cov/branch-export-json.test
@@ -46,4 +46,4 @@
// MACROS: 5,15,5,23,1,2,8,0,4
// MACROS: 6,15,6,23,0,1,9,0,4
// MACROS: 8,15,8,38,1,2,2,0,4
-// MACROS: {"count":40,"covered":24,"notcovered":16,"percent":60}
+// MACROS: {"count":16,"covered":6,"notcovered":10,"percent":37.5}
diff --git a/llvm/test/tools/llvm-cov/branch-export-lcov.test b/llvm/test/tools/llvm-cov/branch-export-lcov.test
index fe43dd66de8d04..444277435d60d6 100644
--- a/llvm/test/tools/llvm-cov/branch-export-lcov.test
+++ b/llvm/test/tools/llvm-cov/branch-export-lcov.test
@@ -71,8 +71,8 @@
// MACROS-COUNT-10: BRDA:37
// MACROS-NOT: BRDA:37
// MACROS-NOT: BRDA
-// MACROS: BRF:40
-// MACROS: BRH:24
+// MACROS: BRF:16
+// MACROS: BRH:6
// NOBRANCH-NOT: BRDA
// NOBRANCH-NOT: BRF
diff --git a/llvm/test/tools/llvm-cov/branch-macros.test b/llvm/test/tools/llvm-cov/branch-macros.test
index b892aba0a044a3..1023d7cc47d4d9 100644
--- a/llvm/test/tools/llvm-cov/branch-macros.test
+++ b/llvm/test/tools/llvm-cov/branch-macros.test
@@ -1,5 +1,8 @@
// RUN: llvm-profdata merge %S/Inputs/branch-macros.proftext -o %t.profdata
// RUN: llvm-cov show --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -check-prefixes=CHECK,BRCOV -D#C=999
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s -check-prefix=REPORT
+// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s -check-prefix=FILE
+
// RUN: llvm-cov show --binary-counters=true --show-expansions --show-branches=count %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -path-equivalence=/tmp,%S/Inputs | FileCheck %S/Inputs/branch-macros.cpp -check-prefixes=CHECK,BRCOV -D#C=1
// RUN: llvm-cov report --show-branch-summary %S/Inputs/branch-macros.o32l -instr-profile %t.profdata -show-functions -path-equivalence=/tmp,%S/Inputs %S/Inputs/branch-macros.cpp | FileCheck %s -check-prefix=REPORT
@@ -14,3 +17,9 @@
// REPORT-NEXT: main 1 0 100.00% 6 0 100.00% 0 0 0.00%
// REPORT-NEXT: ---
// REPORT-NEXT: TOTAL 16 4 75.00% 32 0 100.00% 40 16 60.00%
+
+// FILE: Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover
+// FILE-NEXT: ---
+// FILE-NEXT: branch-macros.cpp 28 5 82.14% 3 0 100.00% 39 0 100.00% 16 10 37.50%
+// FILE-NEXT: ---
+// FILE-NEXT: TOTAL 28 5 82.14% 3 0 100.00% 39 0 100.00% 16 10 37.50%
diff --git a/llvm/test/tools/llvm-cov/branch-templates.test b/llvm/test/tools/llvm-cov/branch-templates.test
index 594a3ca533678b..c4fc9cafbfd80e 100644
--- a/llvm/test/tools/llvm-cov/branch-templates.test
+++ b/llvm/test/tools/llvm-cov/branch-templates.test
@@ -26,6 +26,6 @@
// REPORTFILE: Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover
// REPORTFILE-NEXT: ---
-// REPORTFILE-NEXT: branch-templates.cpp 12 2 83.33% 2 0 100.00% 17 3 82.35% 12 6 50.00%
+// REPORTFILE-NEXT: branch-templates.cpp 12 2 83.33% 2 0 100.00% 17 3 82.35% 8 3 62.50%
// REPORTFILE-NEXT: ---
-// REPORTFILE-NEXT: TOTAL 12 2 83.33% 2 0 100.00% 17 3 82.35% 12 6 50.00%
+// REPORTFILE-NEXT: TOTAL 12 2 83.33% 2 0 100.00% 17 3 82.35% 8 3 62.50%
diff --git a/llvm/test/tools/llvm-cov/mcdc-templates-merge.test b/llvm/test/tools/llvm-cov/mcdc-templates-merge.test
new file mode 100644
index 00000000000000..21c5458edfa846
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/mcdc-templates-merge.test
@@ -0,0 +1,41 @@
+# Test `merge-instantiations=merge/any/all`
+
+RUN: yaml2obj %S/Inputs/mcdc-templates-merge.yaml -o %t.o
+RUN: llvm-profdata merge %S/Inputs/mcdc-templates-merge.proftext -o %t.profdata
+
+RUN: llvm-cov show -merge-instantiations=merge --show-mcdc -show-instantiations=true %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/mcdc-templates-merge.cpp --check-prefixes=CHECK,MERGE
+RUN: llvm-cov show -merge-instantiations=any --show-mcdc -show-instantiations=true %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/mcdc-templates-merge.cpp --check-prefixes=CHECK,ANY
+RUN: llvm-cov show -merge-instantiations=all --show-mcdc -show-instantiations=true %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %S/Inputs/mcdc-templates-merge.cpp --check-prefixes=CHECK,ALL
+
+RUN: llvm-cov report -merge-instantiations=merge --show-mcdc-summary %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefixes=REPORT,MERGE
+RUN: llvm-cov report -merge-instantiations=any --show-mcdc-summary %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefixes=REPORT,ANY
+RUN: llvm-cov report -merge-instantiations=all --show-mcdc-summary %t.o -instr-profile %t.profdata -path-equivalence=.,%S/Inputs | FileCheck %s -check-prefixes=REPORT,ALL
+
+REPORT: mcdc-templates-merge.cpp
+
+# Regions
+MERGE: 10 1 90.00%
+ANY: 10 1 90.00%
+ALL: 10 4 60.00%
+
+# Functions
+MERGE: 3 0 100.00%
+ANY: 3 0 100.00%
+ALL: 3 0 100.00%
+
+# Lines
+MERGE: 19 1 94.74%
+ANY: 19 1 94.74%
+ALL: 19 4 78.95%
+
+# Branches
+MERGE: 12 1 91.67%
+ANY: 11 1 90.91%
+ALL: 12 7 41.67%
+
+# MC/DC Conditions
+MERGE: 4 2 50.00%
+ANY: 4 2 50.00%
+ALL: 4 4 0.00%
+
+REPORT: TOTAL
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 2d6da7efc69798..4ae4fff64ad4bc 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -395,7 +395,8 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
auto SourceBuffer = getSourceFile(SourceFile);
if (!SourceBuffer)
return nullptr;
- auto FileCoverage = Coverage.getCoverageForFile(SourceFile);
+ auto FileCoverage =
+ Coverage.getCoverageForFile(SourceFile, ViewOpts.MergeStrategyOpts);
if (FileCoverage.empty())
return nullptr;
@@ -795,6 +796,14 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
"check-binary-ids", cl::desc("Fail if an object couldn't be found for a "
"binary ID in the profile"));
+ cl::opt<MergeStrategy> MergeStrategyOpts(
+ "merge-instantiations", cl::desc("Merge instantiations"),
+ cl::values(
+ clEnumValN(MergeStrategy::Merge, "merge", "Merge entries by adding"),
+ clEnumValN(MergeStrategy::Any, "any", "Pick up any better entries"),
+ clEnumValN(MergeStrategy::All, "all", "Pick up the worst entries")),
+ cl::init(MergeStrategy::Merge));
+
auto commandLineParser = [&, this](int argc, const char **argv) -> int {
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
ViewOpts.Debug = DebugDump;
@@ -951,6 +960,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
ViewOpts.ExportSummaryOnly = SummaryOnly;
ViewOpts.NumThreads = NumThreads;
ViewOpts.CompilationDirectory = CompilationDirectory;
+ ViewOpts.MergeStrategyOpts = MergeStrategyOpts;
return 0;
};
diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp
index 0046b968756dd0..9215e2421f5145 100644
--- a/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -480,8 +480,8 @@ void CoverageReport::prepareSingleFileReport(const StringRef Filename,
/*Covered=*/Group.getTotalExecutionCount() > 0);
}
- auto FileCoverage =
- Coverage->getCoverageForFile(Filename, FilteredOutFunctions);
+ auto FileCoverage = Coverage->getCoverageForFile(
+ Filename, Options.MergeStrategyOpts, FilteredOutFunctions);
if (FileCoverage.empty())
return;
diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h
index 81e69c3814e306..d2135a19e11f69 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -11,6 +11,7 @@
#include "RenderingSupport.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include <vector>
namespace llvm {
@@ -48,6 +49,7 @@ struct CoverageViewOptions {
bool BinaryCounters;
OutputFormat Format;
BranchOutputType ShowBranches;
+ coverage::MergeStrategy MergeStrategyOpts;
std::string ShowOutputDirectory;
std::vector<std::string> DemanglerOpts;
uint32_t TabSize;
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.cpp b/llvm/tools/llvm-cov/SourceCoverageView.cpp
index dfecddfaf4143f..1ef1952e691c9a 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageView.cpp
@@ -207,8 +207,8 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
// through them while we iterate lines.
llvm::stable_sort(ExpansionSubViews);
llvm::stable_sort(InstantiationSubViews);
- llvm::stable_sort(BranchSubViews);
- llvm::stable_sort(MCDCSubViews);
+ // BranchSubViews is sorted.
+ // MCDCSubViews is sorted.
auto NextESV = ExpansionSubViews.begin();
auto EndESV = ExpansionSubViews.end();
auto NextISV = InstantiationSubViews.begin();
>From dc0ef8f682f704422ec52b484248cdfee1a6e804 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 27 Dec 2024 16:19:01 +0900
Subject: [PATCH 30/30] llvm-cov: [MCDC] Merge and recalculate independence
pairs on template instantiations.
---
.../ProfileData/Coverage/CoverageMapping.h | 16 ++++--
.../ProfileData/Coverage/CoverageMapping.cpp | 57 ++++++++++++++++---
.../llvm-cov/Inputs/mcdc-templates-merge.cpp | 4 +-
.../tools/llvm-cov/mcdc-templates-merge.test | 2 +-
4 files changed, 62 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index cfaee395655295..5d7d555a10bd3a 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -471,6 +471,7 @@ struct MCDCRecord {
}
};
+ using BitmapByCondTy = std::array<BitVector, 2>;
using TestVectors = llvm::SmallVector<std::pair<TestVector, CondState>>;
using BoolVector = std::array<BitVector, 2>;
using TVRowPair = std::pair<unsigned, unsigned>;
@@ -481,6 +482,7 @@ struct MCDCRecord {
private:
CounterMappingRegion Region;
TestVectors TV;
+ BitmapByCondTy BitmapByCond;
std::optional<TVPairMap> IndependencePairs;
BoolVector Folded;
CondIDMap PosToID;
@@ -488,8 +490,10 @@ struct MCDCRecord {
public:
MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV,
- BoolVector &&Folded, CondIDMap &&PosToID, LineColPairMap &&CondLoc)
- : Region(Region), TV(std::move(TV)), Folded(std::move(Folded)),
+ BitmapByCondTy &&BitmapByCond, BoolVector &&Folded,
+ CondIDMap &&PosToID, LineColPairMap &&CondLoc)
+ : Region(Region), TV(std::move(TV)),
+ BitmapByCond(std::move(BitmapByCond)), Folded(std::move(Folded)),
PosToID(std::move(PosToID)), CondLoc(std::move(CondLoc)) {
findIndependencePairs();
}
@@ -497,8 +501,9 @@ struct MCDCRecord {
inline LineColPair viewLoc() const { return Region.endLoc(); }
bool isMergeable(const MCDCRecord &RHS) const {
- return (this->viewLoc() == RHS.viewLoc() && this->PosToID == RHS.PosToID &&
- this->CondLoc == RHS.CondLoc);
+ return (this->viewLoc() == RHS.viewLoc() &&
+ this->BitmapByCond[false].size() == RHS.BitmapByCond[true].size() &&
+ this->PosToID == RHS.PosToID && this->CondLoc == RHS.CondLoc);
}
// This may invalidate IndependencePairs
@@ -577,7 +582,8 @@ struct MCDCRecord {
auto [Covered, Folded] = getCoveredCount();
auto NumTVs = getNumTestVectors();
switch (Strategy) {
- case MergeStrategy::Merge:
+ default:
+ llvm_unreachable("Not supported");
case MergeStrategy::Any:
return {
Covered, // The largest covered number
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 76aa008886291e..8dd354f5122253 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -260,17 +260,55 @@ void CountedRegion::merge(const CountedRegion &RHS, MergeStrategy Strategy) {
}
void MCDCRecord::merge(MCDCRecord &&RHS, MergeStrategy Strategy) {
+ assert(this->TV.size() ==
+ this->BitmapByCond[false].count() + this->BitmapByCond[true].count());
+ assert(RHS.TV.size() ==
+ RHS.BitmapByCond[false].count() + RHS.BitmapByCond[true].count());
assert(this->PosToID == RHS.PosToID);
assert(this->CondLoc == RHS.CondLoc);
switch (Strategy) {
case MergeStrategy::Merge:
+ break;
case MergeStrategy::Any:
case MergeStrategy::All:
if (this->getMergeRank(Strategy) < RHS.getMergeRank(Strategy))
*this = std::move(RHS);
return;
}
+
+ std::array<TestVectors, 2> LHSTV;
+ auto LHSI = this->TV.begin();
+ auto RHSI = RHS.TV.begin();
+ bool Merged = false;
+ for (auto MCDCCond : {MCDCRecord::MCDC_False, MCDCRecord::MCDC_True}) {
+ auto &LHSBitmap = this->BitmapByCond[MCDCCond];
+ auto &RHSBitmap = RHS.BitmapByCond[MCDCCond];
+ for (unsigned I = 0, E = LHSBitmap.size(); I != E; ++I) {
+ if (LHSBitmap[I]) {
+ if (RHSBitmap[I])
+ ++RHSI;
+ LHSTV[LHSI->second].push_back(std::move(*LHSI++));
+ } else if (RHSBitmap[I]) {
+ LHSTV[RHSI->second].push_back(std::move(*RHSI++));
+ LHSBitmap[I] = true;
+ Merged = true;
+ }
+ }
+
+ this->Folded[MCDCCond] &= RHS.Folded[MCDCCond];
+ }
+
+ if (Merged)
+ IndependencePairs.reset();
+
+ assert(LHSI == this->TV.end());
+ assert(RHSI == RHS.TV.end());
+ this->TV = std::move(LHSTV[false]);
+ this->TV.append(std::make_move_iterator(LHSTV[true].begin()),
+ std::make_move_iterator(LHSTV[true].end()));
+ assert(this->TV.size() ==
+ this->BitmapByCond[false].count() + this->BitmapByCond[true].count());
}
// Find an independence pair for each condition:
@@ -284,13 +322,7 @@ void MCDCRecord::findIndependencePairs() {
IndependencePairs.emplace();
unsigned NumTVs = TV.size();
- // Will be replaced to shorter expr.
- unsigned TVTrueIdx = std::distance(
- TV.begin(),
- std::find_if(TV.begin(), TV.end(),
- [&](auto I) { return (I.second == MCDCRecord::MCDC_True); })
-
- );
+ unsigned TVTrueIdx = BitmapByCond[false].count();
for (unsigned I = TVTrueIdx; I < NumTVs; ++I) {
const auto &[A, ACond] = TV[I];
assert(ACond == MCDCRecord::MCDC_True);
@@ -435,6 +467,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
/// with a bit value of '1' indicates that the corresponding Test Vector
/// identified by that index was executed.
const BitVector &Bitmap;
+ MCDCRecord::BitmapByCondTy BitmapByCond;
/// Decision Region to which the ExecutedTestVectorBitmap applies.
const CounterMappingRegion &Region;
@@ -487,6 +520,7 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
ArrayRef<const CounterMappingRegion *> Branches,
bool IsVersion11)
: NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),
+ BitmapByCond{{BitVector(NumTestVectors), BitVector(NumTestVectors)}},
Region(Region), DecisionParams(Region.getDecisionParams()),
Branches(Branches), NumConditions(DecisionParams.NumConditions),
Folded{{BitVector(NumConditions), BitVector(NumConditions)}},
@@ -518,6 +552,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
: DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])
continue;
+ assert(!BitmapByCond[MCDCCond][NextTVIdx]);
+ BitmapByCond[MCDCCond][NextTVIdx] = true;
ExecVectorIdxs.emplace_back(MCDCCond, NextTVIdx, ExecVectors.size());
// Copy the completed test vector to the vector of testvectors.
@@ -547,6 +583,8 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
for (const auto &IdxTuple : ExecVectorIdxs)
NewTestVectors.push_back(std::move(ExecVectors[IdxTuple.Ord]));
ExecVectors = std::move(NewTestVectors);
+
+ assert(!BitmapByCond[false].anyCommon(BitmapByCond[true]));
}
public:
@@ -585,8 +623,9 @@ class MCDCRecordProcessor : NextIDsBuilder, mcdc::TVIdxBuilder {
findExecutedTestVectors();
// Record Test vectors, executed vectors, and independence pairs.
- return MCDCRecord(Region, std::move(ExecVectors), std::move(Folded),
- std::move(PosToID), std::move(CondLoc));
+ return MCDCRecord(Region, std::move(ExecVectors), std::move(BitmapByCond),
+ std::move(Folded), std::move(PosToID),
+ std::move(CondLoc));
}
};
diff --git a/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp
index 09c2e0980cca85..46d1260d122747 100644
--- a/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp
+++ b/llvm/test/tools/llvm-cov/Inputs/mcdc-templates-merge.cpp
@@ -8,7 +8,7 @@ bool ab(Ty a, Ty b) {
// ANY: [[@LINE-3]]| 2| return
// ALL: [[@LINE-4]]| 0| return
-// MERGE: MC/DC Coverage for Decision{{[:]}} 50.00%
+// MERGE: MC/DC Coverage for Decision{{[:]}} 100.00%
// ANY: MC/DC Coverage for Decision{{[:]}} 50.00%
// ALL: MC/DC Coverage for Decision{{[:]}} 0.00%
@@ -28,7 +28,7 @@ bool Cab(bool a, bool b) {
// ANY: [[@LINE-3]]| 2| return
// ALL: [[@LINE-4]]| 2| return
-// MERGE: MC/DC Coverage for Decision{{[:]}} 50.00%
+// MERGE: MC/DC Coverage for Decision{{[:]}} 100.00%
// ANY: MC/DC Coverage for Decision{{[:]}} 50.00%
// ALL: MC/DC Coverage for Decision{{[:]}} 0.00%
diff --git a/llvm/test/tools/llvm-cov/mcdc-templates-merge.test b/llvm/test/tools/llvm-cov/mcdc-templates-merge.test
index 21c5458edfa846..d4369dc2db2930 100644
--- a/llvm/test/tools/llvm-cov/mcdc-templates-merge.test
+++ b/llvm/test/tools/llvm-cov/mcdc-templates-merge.test
@@ -34,7 +34,7 @@ ANY: 11 1 90.91%
ALL: 12 7 41.67%
# MC/DC Conditions
-MERGE: 4 2 50.00%
+MERGE: 5 0 100.00%
ANY: 4 2 50.00%
ALL: 4 4 0.00%
More information about the llvm-commits
mailing list