Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 68065ba

Browse files
author
Igor Kudrin
committed
[Coverage] Combine counts of expansion regions if there are no code regions for the same area.
Differential Revision: http://reviews.llvm.org/D18831 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268620 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 408b811 commit 68065ba

File tree

5 files changed

+90
-16
lines changed

5 files changed

+90
-16
lines changed

lib/ProfileData/Coverage/CoverageMapping.cpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,25 @@ class SegmentBuilder {
334334

335335
/// Sort a nested sequence of regions from a single file.
336336
static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) {
337-
std::sort(Regions.begin(), Regions.end(),
338-
[](const CountedRegion &LHS, const CountedRegion &RHS) {
339-
if (LHS.startLoc() == RHS.startLoc())
340-
// When LHS completely contains RHS, we sort LHS first.
341-
return RHS.endLoc() < LHS.endLoc();
342-
return LHS.startLoc() < RHS.startLoc();
343-
});
337+
std::sort(Regions.begin(), Regions.end(), [](const CountedRegion &LHS,
338+
const CountedRegion &RHS) {
339+
if (LHS.startLoc() != RHS.startLoc())
340+
return LHS.startLoc() < RHS.startLoc();
341+
if (LHS.endLoc() != RHS.endLoc())
342+
// When LHS completely contains RHS, we sort LHS first.
343+
return RHS.endLoc() < LHS.endLoc();
344+
// If LHS and RHS cover the same area, we need to sort them according
345+
// to their kinds so that the most suitable region will become "active"
346+
// in combineRegions(). Because we accumulate counter values only from
347+
// regions of the same kind as the first region of the area, prefer
348+
// CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion.
349+
static_assert(coverage::CounterMappingRegion::CodeRegion <
350+
coverage::CounterMappingRegion::ExpansionRegion &&
351+
coverage::CounterMappingRegion::ExpansionRegion <
352+
coverage::CounterMappingRegion::SkippedRegion,
353+
"Unexpected order of region kind values");
354+
return LHS.Kind < RHS.Kind;
355+
});
344356
}
345357

346358
/// Combine counts of regions which cover the same area.
@@ -360,15 +372,18 @@ class SegmentBuilder {
360372
continue;
361373
}
362374
// Merge duplicate region.
363-
if (I->Kind != coverage::CounterMappingRegion::CodeRegion)
364-
// Add counts only from CodeRegions.
365-
continue;
366-
if (Active->Kind == coverage::CounterMappingRegion::SkippedRegion)
367-
// We have to overwrite SkippedRegions because of special handling
368-
// of them in startSegment().
369-
*Active = *I;
370-
else
371-
// Otherwise, just append the count.
375+
// If CodeRegions and ExpansionRegions cover the same area, it's probably
376+
// a macro which is fully expanded to another macro. In that case, we need
377+
// to accumulate counts only from CodeRegions, or else the area will be
378+
// counted twice.
379+
// On the other hand, a macro may have a nested macro in its body. If the
380+
// outer macro is used several times, the ExpansionRegion for the nested
381+
// macro will also be added several times. These ExpansionRegions cover
382+
// the same source locations and have to be combined to reach the correct
383+
// value for that area.
384+
// We add counts of the regions of the same kind as the active region
385+
// to handle the both situations.
386+
if (I->Kind == Active->Kind)
372387
Active->ExecutionCount += I->ExecutionCount;
373388
}
374389
return Regions.drop_back(std::distance(++Active, End));
161 Bytes
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
main
2+
# Func Hash:
3+
0
4+
# Num Counters:
5+
1
6+
# Counter Values:
7+
1
8+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Check that we combine expansion regions.
2+
3+
// RUN: llvm-profdata merge %S/Inputs/combine_expansions.proftext -o %t.profdata
4+
// RUN: llvm-cov show %S/Inputs/combine_expansions.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
5+
6+
#define SIMPLE_OP \
7+
++x
8+
// CHECK: | [[@LINE-2]]|#define SIMPLE_OP
9+
// CHECK-NEXT: 2| [[@LINE-2]]| ++x
10+
11+
#define DO_SOMETHING \
12+
{ \
13+
int x = 0; \
14+
SIMPLE_OP; \
15+
}
16+
// CHECK: | [[@LINE-5]]|#define DO_SOMETHING
17+
// CHECK-NEXT: 2| [[@LINE-5]]| {
18+
// CHECK-NEXT: 2| [[@LINE-5]]| int x = 0;
19+
// CHECK-NEXT: 2| [[@LINE-5]]| SIMPLE_OP;
20+
// CHECK-NEXT: 2| [[@LINE-5]]| }
21+
22+
int main() { // CHECK: 1| [[@LINE]]|int main() {
23+
DO_SOMETHING; // CHECK-NEXT: 1| [[@LINE]]| DO_SOMETHING;
24+
DO_SOMETHING; // CHECK-NEXT: 1| [[@LINE]]| DO_SOMETHING;
25+
return 0; // CHECK-NEXT: 1| [[@LINE]]| return 0;
26+
} // CHECK-NEXT: 1| [[@LINE]]|}

unittests/ProfileData/CoverageMappingTest.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ TEST_P(MaybeSparseCoverageMappingTest,
422422
EXPECT_EQ(CoverageSegment(9, 9, false), Segments[3]);
423423
}
424424

425+
// If CodeRegions and ExpansionRegions cover the same area,
426+
// only counts of CodeRegions should be used.
425427
TEST_P(MaybeSparseCoverageMappingTest, dont_combine_expansions) {
426428
InstrProfRecord Record1("func", 0x1234, {10, 20});
427429
InstrProfRecord Record2("func", 0x1234, {0, 0});
@@ -444,6 +446,29 @@ TEST_P(MaybeSparseCoverageMappingTest, dont_combine_expansions) {
444446
ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
445447
}
446448

449+
// If an area is covered only by ExpansionRegions, they should be combinated.
450+
TEST_P(MaybeSparseCoverageMappingTest, combine_expansions) {
451+
InstrProfRecord Record("func", 0x1234, {2, 3, 7});
452+
NoError(ProfileWriter.addRecord(std::move(Record)));
453+
454+
startFunction("func", 0x1234);
455+
addCMR(Counter::getCounter(1), "include1", 1, 1, 1, 10);
456+
addCMR(Counter::getCounter(2), "include2", 1, 1, 1, 10);
457+
addCMR(Counter::getCounter(0), "file", 1, 1, 5, 5);
458+
addExpansionCMR("file", "include1", 3, 1, 3, 5);
459+
addExpansionCMR("file", "include2", 3, 1, 3, 5);
460+
461+
loadCoverageMapping();
462+
463+
CoverageData Data = LoadedCoverage->getCoverageForFile("file");
464+
std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
465+
ASSERT_EQ(4U, Segments.size());
466+
EXPECT_EQ(CoverageSegment(1, 1, 2, true), Segments[0]);
467+
EXPECT_EQ(CoverageSegment(3, 1, 10, true), Segments[1]);
468+
EXPECT_EQ(CoverageSegment(3, 5, 2, false), Segments[2]);
469+
EXPECT_EQ(CoverageSegment(5, 5, false), Segments[3]);
470+
}
471+
447472
TEST_P(MaybeSparseCoverageMappingTest, strip_filename_prefix) {
448473
InstrProfRecord Record("file1:func", 0x1234, {0});
449474
NoError(ProfileWriter.addRecord(std::move(Record)));

0 commit comments

Comments
 (0)