[llvm] [profdata] Use --hot-func-list to show all hot functions (PR #149428)

Ellis Hoag via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 18 13:35:50 PDT 2025


https://github.com/ellishg updated https://github.com/llvm/llvm-project/pull/149428

>From e1a572b027b664cf98918847a57c1a98669e1cc9 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Thu, 17 Jul 2025 17:19:58 -0700
Subject: [PATCH 1/3] [profdata] Use --hot-func-list to show all hot functions

---
 llvm/test/tools/llvm-profdata/c-general.test  |  6 +--
 .../tools/llvm-profdata/show-hot.proftext     | 35 +++++++++++++
 llvm/tools/llvm-profdata/llvm-profdata.cpp    | 52 +++++++++----------
 3 files changed, 62 insertions(+), 31 deletions(-)
 create mode 100644 llvm/test/tools/llvm-profdata/show-hot.proftext

diff --git a/llvm/test/tools/llvm-profdata/c-general.test b/llvm/test/tools/llvm-profdata/c-general.test
index 7c48f7b04a05c..ab4849fac034f 100644
--- a/llvm/test/tools/llvm-profdata/c-general.test
+++ b/llvm/test/tools/llvm-profdata/c-general.test
@@ -22,6 +22,6 @@ SWITCHES-LABEL: Functions shown: 1
 CHECK-LABEL: Total functions: 12
 CHECK-NEXT: Maximum function count: 1
 CHECK-NEXT: Maximum internal block count: 100
-TOPN: boolean_operators, max count = 100
-TOPN-NEXT: simple_loops, max count = 100
-TOPN-NEXT:  conditionals, max count = 100
+TOPN:         simple_loops, max count = 100
+TOPN-NEXT:    conditionals, max count = 100
+TOPN-NEXT:    boolean_operators, max count = 100
diff --git a/llvm/test/tools/llvm-profdata/show-hot.proftext b/llvm/test/tools/llvm-profdata/show-hot.proftext
new file mode 100644
index 0000000000000..5c9bd61c20d28
--- /dev/null
+++ b/llvm/test/tools/llvm-profdata/show-hot.proftext
@@ -0,0 +1,35 @@
+# RUN: llvm-profdata show %s --hot-func-list | FileCheck %s
+
+# CHECK: # Hot count threshold: 101
+# CHECK: hot_b
+# CHECK: hot_a
+# CHECK: hot_c
+
+:ir
+hot_a
+# Func Hash:
+0x1234
+# Num Counters:
+1
+# Counter Values:
+101
+
+hot_b
+0x5678
+1
+202
+
+hot_c
+0x5678
+1
+101
+
+cold_d
+0xabcd
+1
+1
+
+cold_e
+0xefff
+1
+0
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 5efabd5f2a7c6..39327722367fe 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -2846,9 +2846,9 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   auto FS = vfs::getRealFileSystem();
   auto ReaderOrErr = InstrProfReader::create(Filename, *FS);
   std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
-  if (ShowDetailedSummary && Cutoffs.empty()) {
-    Cutoffs = ProfileSummaryBuilder::DefaultCutoffs;
-  }
+  if (Cutoffs.empty())
+    if (ShowDetailedSummary || ShowHotFuncList)
+      Cutoffs = ProfileSummaryBuilder::DefaultCutoffs;
   InstrProfSummaryBuilder Builder(std::move(Cutoffs));
   if (Error E = ReaderOrErr.takeError())
     exitWithError(std::move(E), Filename);
@@ -2860,15 +2860,7 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   int NumVPKind = IPVK_Last - IPVK_First + 1;
   std::vector<ValueSitesStats> VPStats(NumVPKind);
 
-  auto MinCmp = [](const std::pair<std::string, uint64_t> &v1,
-                   const std::pair<std::string, uint64_t> &v2) {
-    return v1.second > v2.second;
-  };
-
-  std::priority_queue<std::pair<std::string, uint64_t>,
-                      std::vector<std::pair<std::string, uint64_t>>,
-                      decltype(MinCmp)>
-      HottestFuncs(MinCmp);
+  std::vector<std::pair<uint64_t, uint64_t>> NameRefAndMaxCount;
 
   if (!TextFormat && OnlyListBelow) {
     OS << "The list of functions with the maximum counter less than "
@@ -2942,15 +2934,9 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
     if (OnlyListBelow)
       continue;
 
-    if (TopNFunctions) {
-      if (HottestFuncs.size() == TopNFunctions) {
-        if (HottestFuncs.top().second < FuncMax) {
-          HottestFuncs.pop();
-          HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax));
-        }
-      } else
-        HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax));
-    }
+    if (TopNFunctions || ShowHotFuncList)
+      NameRefAndMaxCount.emplace_back(IndexedInstrProf::ComputeHash(Func.Name),
+                                      FuncMax);
 
     if (Show) {
       if (!ShownFunctions)
@@ -3029,16 +3015,26 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
        << "): " << PS->getNumFunctions() - BelowCutoffFunctions << "\n";
   }
 
+  // Sort by MaxCount in decreasing order
+  llvm::stable_sort(NameRefAndMaxCount, [](const auto &L, const auto &R) {
+    return L.second > R.second;
+  });
   if (TopNFunctions) {
-    std::vector<std::pair<std::string, uint64_t>> SortedHottestFuncs;
-    while (!HottestFuncs.empty()) {
-      SortedHottestFuncs.emplace_back(HottestFuncs.top());
-      HottestFuncs.pop();
-    }
     OS << "Top " << TopNFunctions
        << " functions with the largest internal block counts: \n";
-    for (auto &hotfunc : llvm::reverse(SortedHottestFuncs))
-      OS << "  " << hotfunc.first << ", max count = " << hotfunc.second << "\n";
+    auto TopFuncs = ArrayRef(NameRefAndMaxCount).take_front(TopNFunctions);
+    for (auto [NameRef, MaxCount] : TopFuncs)
+      OS << "  " << Reader->getSymtab().getFuncOrVarName(NameRef)
+         << ", max count = " << MaxCount << "\n";
+  }
+
+  if (ShowHotFuncList) {
+    auto HotCountThreshold =
+        ProfileSummaryBuilder::getHotCountThreshold(PS->getDetailedSummary());
+    OS << "# Hot count threshold: " << HotCountThreshold << "\n";
+    for (auto [NameRef, MaxCount] : NameRefAndMaxCount)
+      if (MaxCount >= HotCountThreshold)
+        OS << Reader->getSymtab().getFuncOrVarName(NameRef) << "\n";
   }
 
   if (ShownFunctions && ShowIndirectCallTargets) {

>From d0a658dd5970b0f531c79f00fa26fe85ba649a7e Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Thu, 17 Jul 2025 17:48:07 -0700
Subject: [PATCH 2/3] remove include

---
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 39327722367fe..cd36600d48d0b 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -46,7 +46,6 @@
 #include <algorithm>
 #include <cmath>
 #include <optional>
-#include <queue>
 
 using namespace llvm;
 using ProfCorrelatorKind = InstrProfCorrelator::ProfCorrelatorKind;

>From ca37cddde82fbe5da0e6c8da3e8801e93729259e Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellis.sparky.hoag at gmail.com>
Date: Fri, 18 Jul 2025 13:35:29 -0700
Subject: [PATCH 3/3] use stringref

---
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 27 +++++++++++-----------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index cd36600d48d0b..96d135b9746ff 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -2845,9 +2845,8 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   auto FS = vfs::getRealFileSystem();
   auto ReaderOrErr = InstrProfReader::create(Filename, *FS);
   std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
-  if (Cutoffs.empty())
-    if (ShowDetailedSummary || ShowHotFuncList)
-      Cutoffs = ProfileSummaryBuilder::DefaultCutoffs;
+  if (Cutoffs.empty() && (ShowDetailedSummary || ShowHotFuncList))
+    Cutoffs = ProfileSummaryBuilder::DefaultCutoffs;
   InstrProfSummaryBuilder Builder(std::move(Cutoffs));
   if (Error E = ReaderOrErr.takeError())
     exitWithError(std::move(E), Filename);
@@ -2859,7 +2858,7 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   int NumVPKind = IPVK_Last - IPVK_First + 1;
   std::vector<ValueSitesStats> VPStats(NumVPKind);
 
-  std::vector<std::pair<uint64_t, uint64_t>> NameRefAndMaxCount;
+  std::vector<std::pair<StringRef, uint64_t>> NameAndMaxCount;
 
   if (!TextFormat && OnlyListBelow) {
     OS << "The list of functions with the maximum counter less than "
@@ -2934,8 +2933,7 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
       continue;
 
     if (TopNFunctions || ShowHotFuncList)
-      NameRefAndMaxCount.emplace_back(IndexedInstrProf::ComputeHash(Func.Name),
-                                      FuncMax);
+      NameAndMaxCount.emplace_back(Func.Name, FuncMax);
 
     if (Show) {
       if (!ShownFunctions)
@@ -3015,25 +3013,26 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   }
 
   // Sort by MaxCount in decreasing order
-  llvm::stable_sort(NameRefAndMaxCount, [](const auto &L, const auto &R) {
+  llvm::stable_sort(NameAndMaxCount, [](const auto &L, const auto &R) {
     return L.second > R.second;
   });
   if (TopNFunctions) {
     OS << "Top " << TopNFunctions
        << " functions with the largest internal block counts: \n";
-    auto TopFuncs = ArrayRef(NameRefAndMaxCount).take_front(TopNFunctions);
-    for (auto [NameRef, MaxCount] : TopFuncs)
-      OS << "  " << Reader->getSymtab().getFuncOrVarName(NameRef)
-         << ", max count = " << MaxCount << "\n";
+    auto TopFuncs = ArrayRef(NameAndMaxCount).take_front(TopNFunctions);
+    for (auto [Name, MaxCount] : TopFuncs)
+      OS << "  " << Name << ", max count = " << MaxCount << "\n";
   }
 
   if (ShowHotFuncList) {
     auto HotCountThreshold =
         ProfileSummaryBuilder::getHotCountThreshold(PS->getDetailedSummary());
     OS << "# Hot count threshold: " << HotCountThreshold << "\n";
-    for (auto [NameRef, MaxCount] : NameRefAndMaxCount)
-      if (MaxCount >= HotCountThreshold)
-        OS << Reader->getSymtab().getFuncOrVarName(NameRef) << "\n";
+    for (auto [Name, MaxCount] : NameAndMaxCount) {
+      if (MaxCount < HotCountThreshold)
+        break;
+      OS << Name << "\n";
+    }
   }
 
   if (ShownFunctions && ShowIndirectCallTargets) {



More information about the llvm-commits mailing list