diff options
author | Igor Kudrin <ikudrin.dev@gmail.com> | 2016-04-25 09:43:37 +0000 |
---|---|---|
committer | Igor Kudrin <ikudrin.dev@gmail.com> | 2016-04-25 09:43:37 +0000 |
commit | ed99a96f06d29c7bf3e4a8b5054e6c8fa08410ab (patch) | |
tree | 8d19f7177da2bd6b05d21bd521998557a575bdc2 /llvm/lib/ProfileData/CoverageMapping.cpp | |
parent | 795c629ec93cfa4da558df3231c1309fbe6883be (diff) | |
download | bcm5719-llvm-ed99a96f06d29c7bf3e4a8b5054e6c8fa08410ab.tar.gz bcm5719-llvm-ed99a96f06d29c7bf3e4a8b5054e6c8fa08410ab.zip |
[Coverage] Restore the correct count value after processing a nested region in case of combined regions.
If several regions cover the same area of code, we have to restore
the combined value for that area when return from a nested region.
This patch achieves that by combining regions before calling buildSegments.
Differential Revision: http://reviews.llvm.org/D18610
llvm-svn: 267390
Diffstat (limited to 'llvm/lib/ProfileData/CoverageMapping.cpp')
-rw-r--r-- | llvm/lib/ProfileData/CoverageMapping.cpp | 95 |
1 files changed, 58 insertions, 37 deletions
diff --git a/llvm/lib/ProfileData/CoverageMapping.cpp b/llvm/lib/ProfileData/CoverageMapping.cpp index 334de3c3b06..8e6ca42c4b8 100644 --- a/llvm/lib/ProfileData/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/CoverageMapping.cpp @@ -286,20 +286,17 @@ class SegmentBuilder { /// Start a segment with the given Region's count. void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry, const CountedRegion &Region) { - if (Segments.empty()) - Segments.emplace_back(Line, Col, IsRegionEntry); - CoverageSegment S = Segments.back(); // Avoid creating empty regions. - if (S.Line != Line || S.Col != Col) { - Segments.emplace_back(Line, Col, IsRegionEntry); - S = Segments.back(); - } + if (!Segments.empty() && Segments.back().Line == Line && + Segments.back().Col == Col) + Segments.pop_back(); DEBUG(dbgs() << "Segment at " << Line << ":" << Col); // Set this region's count. if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) { DEBUG(dbgs() << " with count " << Region.ExecutionCount); - Segments.back().setCount(Region.ExecutionCount); - } + Segments.emplace_back(Line, Col, Region.ExecutionCount, IsRegionEntry); + } else + Segments.emplace_back(Line, Col, IsRegionEntry); DEBUG(dbgs() << "\n"); } @@ -321,35 +318,73 @@ class SegmentBuilder { } void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) { - const CountedRegion *PrevRegion = nullptr; for (const auto &Region : Regions) { // Pop any regions that end before this one starts. while (!ActiveRegions.empty() && ActiveRegions.back()->endLoc() <= Region.startLoc()) popRegion(); - if (PrevRegion && PrevRegion->startLoc() == Region.startLoc() && - PrevRegion->endLoc() == Region.endLoc()) { - if (Region.Kind == coverage::CounterMappingRegion::CodeRegion) - Segments.back().addCount(Region.ExecutionCount); - } else { - // Add this region to the stack. - ActiveRegions.push_back(&Region); - startSegment(Region); - } - PrevRegion = &Region; + // Add this region to the stack. + ActiveRegions.push_back(&Region); + startSegment(Region); } // Pop any regions that are left in the stack. while (!ActiveRegions.empty()) popRegion(); } + /// Sort a nested sequence of regions from a single file. + static void sortNestedRegions(MutableArrayRef<CountedRegion> 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(); + }); + } + + /// Combine counts of regions which cover the same area. + static ArrayRef<CountedRegion> + combineRegions(MutableArrayRef<CountedRegion> Regions) { + if (Regions.empty()) + return Regions; + auto Active = Regions.begin(); + auto End = Regions.end(); + for (auto I = Regions.begin() + 1; I != End; ++I) { + if (Active->startLoc() != I->startLoc() || + Active->endLoc() != I->endLoc()) { + // Shift to the next region. + ++Active; + if (Active != I) + *Active = *I; + 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. + Active->ExecutionCount += I->ExecutionCount; + } + return Regions.drop_back(std::distance(++Active, End)); + } + public: - /// Build a list of CoverageSegments from a sorted list of Regions. + /// Build a list of CoverageSegments from a list of Regions. static std::vector<CoverageSegment> - buildSegments(ArrayRef<CountedRegion> Regions) { + buildSegments(MutableArrayRef<CountedRegion> Regions) { std::vector<CoverageSegment> Segments; SegmentBuilder Builder(Segments); - Builder.buildSegmentsImpl(Regions); + + sortNestedRegions(Regions); + ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions); + + Builder.buildSegmentsImpl(CombinedRegions); return Segments; } }; @@ -397,17 +432,6 @@ static Optional<unsigned> findMainViewFileID(StringRef SourceFile, return None; } -/// Sort a nested sequence of regions from a single file. -template <class It> static void sortNestedRegions(It First, It Last) { - std::sort(First, Last, - [](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(); - }); -} - static bool isExpansion(const CountedRegion &R, unsigned FileID) { return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID; } @@ -427,7 +451,6 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) { } } - sortNestedRegions(Regions.begin(), Regions.end()); DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n"); FileCoverage.Segments = SegmentBuilder::buildSegments(Regions); @@ -469,7 +492,6 @@ CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) { FunctionCoverage.Expansions.emplace_back(CR, Function); } - sortNestedRegions(Regions.begin(), Regions.end()); DEBUG(dbgs() << "Emitting segments for function: " << Function.Name << "\n"); FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions); @@ -488,7 +510,6 @@ CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) { ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function); } - sortNestedRegions(Regions.begin(), Regions.end()); DEBUG(dbgs() << "Emitting segments for expansion of file " << Expansion.FileID << "\n"); ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions); |