[llvm] e68fafa - [CSSPGO] llvm-profdata support for CS profile.

Hongtao Yu via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 8 09:04:51 PST 2021


Author: Hongtao Yu
Date: 2021-03-08T09:04:40-08:00
New Revision: e68fafa49f91c5e775605cbbde0815fc4809bf46

URL: https://github.com/llvm/llvm-project/commit/e68fafa49f91c5e775605cbbde0815fc4809bf46
DIFF: https://github.com/llvm/llvm-project/commit/e68fafa49f91c5e775605cbbde0815fc4809bf46.diff

LOG: [CSSPGO] llvm-profdata support for CS profile.

Context-sensitive AutoFDO profile has a different name scheme where full calling contexts are encoded as function names. When processing CS proifle, llvm-profdata should use full contexts instead of leaf function names.

Reviewed By: wmi, wenlei, wlei

Differential Revision: https://reviews.llvm.org/D97998

Added: 
    

Modified: 
    llvm/test/tools/llvm-profdata/sample-hot-func-list.test
    llvm/test/tools/llvm-profdata/sample-overlap.test
    llvm/tools/llvm-profdata/llvm-profdata.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-profdata/sample-hot-func-list.test b/llvm/test/tools/llvm-profdata/sample-hot-func-list.test
index 2ea81363d49c..7f319e6dc0bb 100644
--- a/llvm/test/tools/llvm-profdata/sample-hot-func-list.test
+++ b/llvm/test/tools/llvm-profdata/sample-hot-func-list.test
@@ -11,3 +11,12 @@
 ; CHECK-NEXT: 7711 (2.17%)           610               610             _Z3fooi
 ; CHECK-NEXT: 6948 (1.95%)           3507              470             Func5
 ; CHECK-NEXT: 1523 (0.43%)           563               169             Func1
+
+
+; RUN: llvm-profdata show --sample --hot-func-list %S/Inputs/cs-sample.proftext | FileCheck %s --match-full-lines --strict-whitespace --check-prefix=CS
+
+;      CS:2 out of 8 functions with profile (25.00%) are considered hot functions (max sample >= 23324).
+; CS-NEXT:1968152 out of 1968919 profile counts (99.96%) are from hot functions.
+; CS-NEXT: Total sample (%)       Max sample        Entry sample    Function name
+; CS-NEXT: 1467299 (74.52%)       287884            11              main:3 @ _Z5funcAi:1 @ _Z8funcLeafi
+; CS-NEXT: 500853 (25.44%)        74946             20              main:3.1 @ _Z5funcBi:1 @ _Z8funcLeafi

diff  --git a/llvm/test/tools/llvm-profdata/sample-overlap.test b/llvm/test/tools/llvm-profdata/sample-overlap.test
index 02609d8f98b0..859b705e5f3b 100644
--- a/llvm/test/tools/llvm-profdata/sample-overlap.test
+++ b/llvm/test/tools/llvm-profdata/sample-overlap.test
@@ -116,3 +116,25 @@
 
 ; RUN: llvm-profdata overlap --sample %S/Inputs/sample-overlap-0.proftext %S/Inputs/sample-overlap-5.proftext | FileCheck %s --check-prefix=OVERLAP5  --match-full-lines --strict-whitespace
 ; OVERLAP5:Sum of sample counts for profile {{.*}}/Inputs/sample-overlap-5.proftext is 0.
+
+
+; RUN: llvm-profdata overlap --sample %S/Inputs/cs-sample.proftext %S/Inputs/cs-sample.proftext | FileCheck %s --check-prefix=CS  --match-full-lines --strict-whitespace
+; CS:Program level:
+; CS:  Whole program profile similarity: 100.000%
+; CS:  Whole program sample overlap: 100.000%
+; CS:    percentage of samples unique in base profile: 0.000%
+; CS:    percentage of samples unique in test profile: 0.000%
+; CS:    total samples in base profile: 772562
+; CS:    total samples in test profile: 772562
+; CS:  Function overlap: 100.000%
+; CS:    overlap functions: 8
+; CS:    functions unique in base profile: 0
+; CS:    functions unique in test profile: 0
+; CS:  Hot-function overlap: 100.000%
+; CS:    overlap hot functions: 2
+; CS:    hot functions unique in base profile: 0
+; CS:    hot functions unique in test profile: 0
+; CS:  Hot-block overlap: 100.000%
+; CS:    overlap hot blocks: 6
+; CS:    hot blocks unique in base profile: 0
+; CS:    hot blocks unique in test profile: 0

diff  --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 0066765106db..558d3e6ffd78 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -672,6 +672,7 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
   LLVMContext Context;
   sampleprof::ProfileSymbolList WriterList;
   Optional<bool> ProfileIsProbeBased;
+  Optional<bool> ProfileIsCS;
   for (const auto &Input : Inputs) {
     auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context);
     if (std::error_code EC = ReaderOrErr.getError()) {
@@ -692,11 +693,14 @@ mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
     }
 
     StringMap<FunctionSamples> &Profiles = Reader->getProfiles();
-    if (ProfileIsProbeBased &&
+    if (ProfileIsProbeBased.hasValue() &&
         ProfileIsProbeBased != FunctionSamples::ProfileIsProbeBased)
       exitWithError(
           "cannot merge probe-based profile with non-probe-based profile");
     ProfileIsProbeBased = FunctionSamples::ProfileIsProbeBased;
+    if (ProfileIsCS.hasValue() && ProfileIsCS != FunctionSamples::ProfileIsCS)
+      exitWithError("cannot merge CS profile with non-CS profile");
+    ProfileIsCS = FunctionSamples::ProfileIsCS;
     for (StringMap<FunctionSamples>::iterator I = Profiles.begin(),
                                               E = Profiles.end();
          I != E; ++I) {
@@ -1557,14 +1561,15 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) {
   StringMap<const FunctionSamples *> BaseFuncProf;
   const auto &BaseProfiles = BaseReader->getProfiles();
   for (const auto &BaseFunc : BaseProfiles) {
-    BaseFuncProf.try_emplace(BaseFunc.second.getName(), &(BaseFunc.second));
+    BaseFuncProf.try_emplace(BaseFunc.second.getNameWithContext(),
+                             &(BaseFunc.second));
   }
   ProfOverlap.UnionCount = BaseFuncProf.size();
 
   const auto &TestProfiles = TestReader->getProfiles();
   for (const auto &TestFunc : TestProfiles) {
     SampleOverlapStats FuncOverlap;
-    FuncOverlap.TestName = TestFunc.second.getName();
+    FuncOverlap.TestName = TestFunc.second.getNameWithContext();
     assert(TestStats.count(FuncOverlap.TestName) &&
            "TestStats should have records for all functions in test profile "
            "except inlinees");
@@ -1591,7 +1596,7 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) {
 
       // Two functions match with each other. Compute function-level overlap and
       // aggregate them into profile-level overlap.
-      FuncOverlap.BaseName = Match->second->getName();
+      FuncOverlap.BaseName = Match->second->getNameWithContext();
       assert(BaseStats.count(FuncOverlap.BaseName) &&
              "BaseStats should have records for all functions in base profile "
              "except inlinees");
@@ -1640,10 +1645,11 @@ void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) {
 
   // Traverse through functions in base profile but not in test profile.
   for (const auto &F : BaseFuncProf) {
-    assert(BaseStats.count(F.second->getName()) &&
+    assert(BaseStats.count(F.second->getNameWithContext()) &&
            "BaseStats should have records for all functions in base profile "
            "except inlinees");
-    const FuncSampleStats &FuncStats = BaseStats[F.second->getName()];
+    const FuncSampleStats &FuncStats =
+        BaseStats[F.second->getNameWithContext()];
     ++ProfOverlap.BaseUniqueCount;
     ProfOverlap.BaseUniqueSample += FuncStats.SampleSum;
 
@@ -1674,7 +1680,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() {
     FuncSampleStats FuncStats;
     getFuncSampleStats(I.second, FuncStats, BaseHotThreshold);
     ProfOverlap.BaseSample += FuncStats.SampleSum;
-    BaseStats.try_emplace(I.second.getName(), FuncStats);
+    BaseStats.try_emplace(I.second.getNameWithContext(), FuncStats);
   }
 
   const auto &TestProf = TestReader->getProfiles();
@@ -1683,7 +1689,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() {
     FuncSampleStats FuncStats;
     getFuncSampleStats(I.second, FuncStats, TestHotThreshold);
     ProfOverlap.TestSample += FuncStats.SampleSum;
-    TestStats.try_emplace(I.second.getName(), FuncStats);
+    TestStats.try_emplace(I.second.getNameWithContext(), FuncStats);
   }
 
   ProfOverlap.BaseName = StringRef(BaseFilename);
@@ -1842,6 +1848,8 @@ std::error_code SampleOverlapAggregator::loadProfiles() {
   if (BaseReader->profileIsProbeBased() != TestReader->profileIsProbeBased())
     exitWithError(
         "cannot compare probe-based profile with non-probe-based profile");
+  if (BaseReader->profileIsCS() != TestReader->profileIsCS())
+    exitWithError("cannot compare CS profile with non-CS profile");
 
   // Load BaseHotThreshold and TestHotThreshold as 99-percentile threshold in
   // profile summary.
@@ -1897,21 +1905,24 @@ static int overlap_main(int argc, const char *argv[]) {
   cl::opt<std::string> Output("output", cl::value_desc("output"), cl::init("-"),
                               cl::desc("Output file"));
   cl::alias OutputA("o", cl::desc("Alias for --output"), cl::aliasopt(Output));
-  cl::opt<bool> IsCS("cs", cl::init(false),
-                     cl::desc("For context sensitive counts"));
+  cl::opt<bool> IsCS(
+      "cs", cl::init(false),
+      cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."));
   cl::opt<unsigned long long> ValueCutoff(
       "value-cutoff", cl::init(-1),
       cl::desc(
-          "Function level overlap information for every function in test "
+          "Function level overlap information for every function (with calling "
+          "context for csspgo) in test "
           "profile with max count value greater then the parameter value"));
   cl::opt<std::string> FuncNameFilter(
       "function",
-      cl::desc("Function level overlap information for matching functions"));
+      cl::desc("Function level overlap information for matching functions. For "
+               "CSSPGO this takes a a function name with calling context"));
   cl::opt<unsigned long long> SimilarityCutoff(
       "similarity-cutoff", cl::init(0),
-      cl::desc(
-          "For sample profiles, list function names for overlapped functions "
-          "with similarities below the cutoff (percentage times 10000)."));
+      cl::desc("For sample profiles, list function names (with calling context "
+               "for csspgo) for overlapped functions "
+               "with similarities below the cutoff (percentage times 10000)."));
   cl::opt<ProfileKinds> ProfileKind(
       cl::desc("Profile kind:"), cl::init(instr),
       cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
@@ -2316,9 +2327,9 @@ showHotFunctionList(const StringMap<sampleprof::FunctionSamples> &Profiles,
         (ProfileTotalSample > 0)
             ? (Func.getTotalSamples() * 100.0) / ProfileTotalSample
             : 0;
-    PrintValues.emplace_back(
-        HotFuncInfo(Func.getName(), Func.getTotalSamples(), TotalSamplePercent,
-                    FuncPair.second.second, Func.getEntrySamples()));
+    PrintValues.emplace_back(HotFuncInfo(
+        Func.getNameWithContext(), Func.getTotalSamples(), TotalSamplePercent,
+        FuncPair.second.second, Func.getEntrySamples()));
   }
   dumpHotFunctionList(ColumnTitle, ColumnOffset, PrintValues, HotFuncCount,
                       Profiles.size(), HotFuncSample, ProfileTotalSample,


        


More information about the llvm-commits mailing list