[llvm] r268620 - [Coverage] Combine counts of expansion regions if there are no code regions for the same area.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Thu May 5 02:39:46 PDT 2016


Author: ikudrin
Date: Thu May  5 04:39:45 2016
New Revision: 268620

URL: http://llvm.org/viewvc/llvm-project?rev=268620&view=rev
Log:
[Coverage] Combine counts of expansion regions if there are no code regions for the same area.

Differential Revision: http://reviews.llvm.org/D18831

Added:
    llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.covmapping
    llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.proftext
    llvm/trunk/test/tools/llvm-cov/combine_expansions.cpp
Modified:
    llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp
    llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp

Modified: llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp?rev=268620&r1=268619&r2=268620&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp (original)
+++ llvm/trunk/lib/ProfileData/Coverage/CoverageMapping.cpp Thu May  5 04:39:45 2016
@@ -334,13 +334,25 @@ class SegmentBuilder {
 
   /// 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();
-              });
+    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));

Added: llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.covmapping
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.covmapping?rev=268620&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.covmapping (added) and llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.covmapping Thu May  5 04:39:45 2016 differ

Added: llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.proftext?rev=268620&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.proftext (added)
+++ llvm/trunk/test/tools/llvm-cov/Inputs/combine_expansions.proftext Thu May  5 04:39:45 2016
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+

Added: llvm/trunk/test/tools/llvm-cov/combine_expansions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/combine_expansions.cpp?rev=268620&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/combine_expansions.cpp (added)
+++ llvm/trunk/test/tools/llvm-cov/combine_expansions.cpp Thu May  5 04:39:45 2016
@@ -0,0 +1,26 @@
+// Check that we combine expansion regions.
+
+// RUN: llvm-profdata merge %S/Inputs/combine_expansions.proftext -o %t.profdata
+// RUN: llvm-cov show %S/Inputs/combine_expansions.covmapping -instr-profile %t.profdata -filename-equivalence %s | FileCheck %s
+
+#define SIMPLE_OP \
+  ++x
+// CHECK:       | [[@LINE-2]]|#define SIMPLE_OP
+// CHECK-NEXT: 2| [[@LINE-2]]|  ++x
+
+#define DO_SOMETHING \
+  {                  \
+    int x = 0;       \
+    SIMPLE_OP;       \
+  }
+// CHECK:       | [[@LINE-5]]|#define DO_SOMETHING
+// CHECK-NEXT: 2| [[@LINE-5]]|  {
+// CHECK-NEXT: 2| [[@LINE-5]]|    int x = 0;
+// CHECK-NEXT: 2| [[@LINE-5]]|    SIMPLE_OP;
+// CHECK-NEXT: 2| [[@LINE-5]]|  }
+
+int main() {    // CHECK:      1| [[@LINE]]|int main() {
+  DO_SOMETHING; // CHECK-NEXT: 1| [[@LINE]]|  DO_SOMETHING;
+  DO_SOMETHING; // CHECK-NEXT: 1| [[@LINE]]|  DO_SOMETHING;
+  return 0;     // CHECK-NEXT: 1| [[@LINE]]|  return 0;
+}               // CHECK-NEXT: 1| [[@LINE]]|}

Modified: llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp?rev=268620&r1=268619&r2=268620&view=diff
==============================================================================
--- llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp (original)
+++ llvm/trunk/unittests/ProfileData/CoverageMappingTest.cpp Thu May  5 04:39:45 2016
@@ -422,6 +422,8 @@ TEST_P(MaybeSparseCoverageMappingTest,
   EXPECT_EQ(CoverageSegment(9, 9, false), Segments[3]);
 }
 
+// If CodeRegions and ExpansionRegions cover the same area,
+// only counts of CodeRegions should be used.
 TEST_P(MaybeSparseCoverageMappingTest, dont_combine_expansions) {
   InstrProfRecord Record1("func", 0x1234, {10, 20});
   InstrProfRecord Record2("func", 0x1234, {0, 0});
@@ -444,6 +446,29 @@ TEST_P(MaybeSparseCoverageMappingTest, d
   ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
 }
 
+// If an area is covered only by ExpansionRegions, they should be combinated.
+TEST_P(MaybeSparseCoverageMappingTest, combine_expansions) {
+  InstrProfRecord Record("func", 0x1234, {2, 3, 7});
+  NoError(ProfileWriter.addRecord(std::move(Record)));
+
+  startFunction("func", 0x1234);
+  addCMR(Counter::getCounter(1), "include1", 1, 1, 1, 10);
+  addCMR(Counter::getCounter(2), "include2", 1, 1, 1, 10);
+  addCMR(Counter::getCounter(0), "file", 1, 1, 5, 5);
+  addExpansionCMR("file", "include1", 3, 1, 3, 5);
+  addExpansionCMR("file", "include2", 3, 1, 3, 5);
+
+  loadCoverageMapping();
+
+  CoverageData Data = LoadedCoverage->getCoverageForFile("file");
+  std::vector<CoverageSegment> 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)));




More information about the llvm-commits mailing list