From 68065ba0432738172a882616b111ebda912a0466 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Thu, 5 May 2016 09:39:45 +0000 Subject: [PATCH] [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 --- lib/ProfileData/Coverage/CoverageMapping.cpp | 47 ++++++++++++------ .../Inputs/combine_expansions.covmapping | Bin 0 -> 161 bytes .../Inputs/combine_expansions.proftext | 8 +++ test/tools/llvm-cov/combine_expansions.cpp | 26 ++++++++++ unittests/ProfileData/CoverageMappingTest.cpp | 25 ++++++++++ 5 files changed, 90 insertions(+), 16 deletions(-) create mode 100644 test/tools/llvm-cov/Inputs/combine_expansions.covmapping create mode 100644 test/tools/llvm-cov/Inputs/combine_expansions.proftext create mode 100644 test/tools/llvm-cov/combine_expansions.cpp diff --git a/lib/ProfileData/Coverage/CoverageMapping.cpp b/lib/ProfileData/Coverage/CoverageMapping.cpp index 5d86f1de3ad..9fdd37081c9 100644 --- a/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -334,13 +334,25 @@ class SegmentBuilder { /// Sort a nested sequence of regions from a single file. static void sortNestedRegions(MutableArrayRef Regions) { - std::sort(Regions.begin(), Regions.end(), - [](const CountedRegion &LHS, const CountedRegion &RHS) { - if (LHS.startLoc() == RHS.startLoc()) - // When LHS completely contains RHS, we sort LHS first. - return RHS.endLoc() < LHS.endLoc(); - return LHS.startLoc() < RHS.startLoc(); - }); + std::sort(Regions.begin(), Regions.end(), [](const CountedRegion &LHS, + const CountedRegion &RHS) { + if (LHS.startLoc() != RHS.startLoc()) + return LHS.startLoc() < RHS.startLoc(); + if (LHS.endLoc() != RHS.endLoc()) + // When LHS completely contains RHS, we sort LHS first. + return RHS.endLoc() < LHS.endLoc(); + // If LHS and RHS cover the same area, we need to sort them according + // to their kinds so that the most suitable region will become "active" + // in combineRegions(). Because we accumulate counter values only from + // regions of the same kind as the first region of the area, prefer + // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion. + static_assert(coverage::CounterMappingRegion::CodeRegion < + coverage::CounterMappingRegion::ExpansionRegion && + coverage::CounterMappingRegion::ExpansionRegion < + coverage::CounterMappingRegion::SkippedRegion, + "Unexpected order of region kind values"); + return LHS.Kind < RHS.Kind; + }); } /// Combine counts of regions which cover the same area. @@ -360,15 +372,18 @@ class SegmentBuilder { continue; } // Merge duplicate region. - if (I->Kind != coverage::CounterMappingRegion::CodeRegion) - // Add counts only from CodeRegions. - continue; - if (Active->Kind == coverage::CounterMappingRegion::SkippedRegion) - // We have to overwrite SkippedRegions because of special handling - // of them in startSegment(). - *Active = *I; - else - // Otherwise, just append the count. + // If CodeRegions and ExpansionRegions cover the same area, it's probably + // a macro which is fully expanded to another macro. In that case, we need + // to accumulate counts only from CodeRegions, or else the area will be + // counted twice. + // On the other hand, a macro may have a nested macro in its body. If the + // outer macro is used several times, the ExpansionRegion for the nested + // macro will also be added several times. These ExpansionRegions cover + // the same source locations and have to be combined to reach the correct + // 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) Active->ExecutionCount += I->ExecutionCount; } return Regions.drop_back(std::distance(++Active, End)); diff --git a/test/tools/llvm-cov/Inputs/combine_expansions.covmapping b/test/tools/llvm-cov/Inputs/combine_expansions.covmapping new file mode 100644 index 0000000000000000000000000000000000000000..3acc1cd90a98002b47dfb8d8ab95ca1c70589e47 GIT binary patch literal 161 zcmd1FDa%dHFUu`SEiOq(EJ;g788f384+|3yBQpcP2#8=}getCoverageForFile("file"); + std::vector Segments(Data.begin(), Data.end()); + ASSERT_EQ(4U, Segments.size()); + EXPECT_EQ(CoverageSegment(1, 1, 2, true), Segments[0]); + EXPECT_EQ(CoverageSegment(3, 1, 10, true), Segments[1]); + EXPECT_EQ(CoverageSegment(3, 5, 2, false), Segments[2]); + EXPECT_EQ(CoverageSegment(5, 5, false), Segments[3]); +} + TEST_P(MaybeSparseCoverageMappingTest, strip_filename_prefix) { InstrProfRecord Record("file1:func", 0x1234, {0}); NoError(ProfileWriter.addRecord(std::move(Record))); -- 2.50.1