[llvm] r267390 - [Coverage] Restore the correct count value after processing a nested region in case of combined regions.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 25 02:43:38 PDT 2016


Author: ikudrin
Date: Mon Apr 25 04:43:37 2016
New Revision: 267390

URL: http://llvm.org/viewvc/llvm-project?rev=267390&view=rev
Log:
[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

Modified:
    llvm/trunk/include/llvm/ProfileData/CoverageMapping.h
    llvm/trunk/lib/ProfileData/CoverageMapping.cpp
    llvm/trunk/test/tools/llvm-cov/showTemplateInstantiations.cpp
    llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp

Modified: llvm/trunk/include/llvm/ProfileData/CoverageMapping.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/CoverageMapping.h?rev=267390&r1=267389&r2=267390&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/CoverageMapping.h (original)
+++ llvm/trunk/include/llvm/ProfileData/CoverageMapping.h Mon Apr 25 04:43:37 2016
@@ -370,13 +370,6 @@ struct CoverageSegment {
     return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry) ==
            std::tie(R.Line, R.Col, R.Count, R.HasCount, R.IsRegionEntry);
   }
-
-  void setCount(uint64_t NewCount) {
-    Count = NewCount;
-    HasCount = true;
-  }
-
-  void addCount(uint64_t NewCount) { setCount(Count + NewCount); }
 };
 
 /// \brief Coverage information to be processed or displayed.

Modified: llvm/trunk/lib/ProfileData/CoverageMapping.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/CoverageMapping.cpp?rev=267390&r1=267389&r2=267390&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/CoverageMapping.cpp (original)
+++ llvm/trunk/lib/ProfileData/CoverageMapping.cpp Mon Apr 25 04:43:37 2016
@@ -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> findMainViewFi
   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::getCoverag
       }
   }
 
-  sortNestedRegions(Regions.begin(), Regions.end());
   DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
 
@@ -469,7 +492,6 @@ CoverageMapping::getCoverageForFunction(
         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
         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);

Modified: llvm/trunk/test/tools/llvm-cov/showTemplateInstantiations.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/showTemplateInstantiations.cpp?rev=267390&r1=267389&r2=267390&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/showTemplateInstantiations.cpp (original)
+++ llvm/trunk/test/tools/llvm-cov/showTemplateInstantiations.cpp Mon Apr 25 04:43:37 2016
@@ -7,10 +7,10 @@ template<typename T> // ALL:          |
 int func(T x) {      // ALL-NEXT:    2| [[@LINE]]|int func(T x) {
   if(x)              // ALL-NEXT:    2| [[@LINE]]|  if(x)
     return 0;        // ALL-NEXT:    1| [[@LINE]]|    return 0;
-  else               // ALL-NEXT:    1| [[@LINE]]|  else
+  else               // ALL-NEXT:    2| [[@LINE]]|  else
     return 1;        // ALL-NEXT:    1| [[@LINE]]|    return 1;
   int j = 1;         // ALL-NEXT:    0| [[@LINE]]|  int j = 1;
-}                    // ALL-NEXT:    1| [[@LINE]]|}
+}                    // ALL-NEXT:    2| [[@LINE]]|}
 
                      // CHECK:       {{^ *(\| )?}}_Z4funcIbEiT_:
                      // CHECK-NEXT:  1| [[@LINE-9]]|int func(T x) {

Modified: llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp?rev=267390&r1=267389&r2=267390&view=diff
==============================================================================
--- llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp (original)
+++ llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp Mon Apr 25 04:43:37 2016
@@ -402,6 +402,26 @@ TEST_P(MaybeSparseCoverageMappingTest, c
   ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
 }
 
+TEST_P(MaybeSparseCoverageMappingTest,
+       restore_combined_counter_after_nested_region) {
+  InstrProfRecord Record("func", 0x1234, {10, 20, 40});
+  ProfileWriter.addRecord(std::move(Record));
+
+  startFunction("func", 0x1234);
+  addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+  addCMR(Counter::getCounter(1), "file1", 1, 1, 9, 9);
+  addCMR(Counter::getCounter(2), "file1", 3, 3, 5, 5);
+  loadCoverageMapping();
+
+  CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
+  std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+  ASSERT_EQ(4U, Segments.size());
+  EXPECT_EQ(CoverageSegment(1, 1, 30, true), Segments[0]);
+  EXPECT_EQ(CoverageSegment(3, 3, 40, true), Segments[1]);
+  EXPECT_EQ(CoverageSegment(5, 5, 30, false), Segments[2]);
+  EXPECT_EQ(CoverageSegment(9, 9, false), Segments[3]);
+}
+
 TEST_P(MaybeSparseCoverageMappingTest, dont_combine_expansions) {
   InstrProfRecord Record1("func", 0x1234, {10, 20});
   InstrProfRecord Record2("func", 0x1234, {0, 0});




More information about the llvm-commits mailing list