[llvm] [NFCI][PGO]Re-purpose synthetic entry count to pseduo entry count for AFDO supplementary profiles (PR #139578)

Mingming Liu via llvm-commits llvm-commits at lists.llvm.org
Mon May 12 09:51:29 PDT 2025


https://github.com/mingmingl-llvm created https://github.com/llvm/llvm-project/pull/139578

>From https://github.com/llvm/llvm-project/pull/107471 and on, there are no active user of setting a function's synthetic counts (except in unit tests). This patch proposes to repurpose the synthetic count concepts to record the fact that a function's entry count is generated from AFDO supplementary profiles. This patch doesn't include the change to 'set' pseudo count itself. A follow-up change will do it.

AFDO supplementary profiles are introduced to enhance instrumented FDO profiles for representativeness, by merging a binary's AFDO production sample into FDO profile. During the merge, a function's hot/cold attribute is _corrected_ by AFDO profiles, and the branch weights of the function's basic blocks are not accurate.

The goal of this re-purpose is for compiler passes to tell whether a function's branch weights are static or based on profiles.


>From 64dfe1b68b3330dbc1d98d56d5bff0e9eeb6521f Mon Sep 17 00:00:00 2001
From: mingmingl <mingmingl at google.com>
Date: Sun, 11 May 2025 23:31:37 -0700
Subject: [PATCH] [PGO]Re-purpose synthetic entry count to pseduo entry count
 for AFDO supplementary profiles

---
 llvm/include/llvm/IR/Function.h              | 19 ++++++++++---------
 llvm/include/llvm/IR/MDBuilder.h             |  8 ++++----
 llvm/lib/IR/Function.cpp                     | 13 ++++++-------
 llvm/lib/IR/MDBuilder.cpp                    |  7 +++----
 llvm/lib/Transforms/Utils/InlineFunction.cpp |  2 +-
 llvm/unittests/IR/MetadataTest.cpp           |  8 ++++----
 6 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index 6d4a53da7ff22..f2242742de0bd 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -296,11 +296,11 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
     }
   }
 
-  enum ProfileCountType { PCT_Real, PCT_Synthetic };
+  enum ProfileCountType { PCT_Real, PCT_Pseudo };
 
   /// Class to represent profile counts.
   ///
-  /// This class represents both real and synthetic profile counts.
+  /// This class represents both real and supplementary profile counts.
   class ProfileCount {
   private:
     uint64_t Count = 0;
@@ -311,7 +311,7 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
         : Count(Count), PCT(PCT) {}
     uint64_t getCount() const { return Count; }
     ProfileCountType getType() const { return PCT; }
-    bool isSynthetic() const { return PCT == PCT_Synthetic; }
+    bool isPseudo() const { return PCT == PCT_Pseudo; }
   };
 
   /// Set the entry count for this function.
@@ -330,16 +330,17 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
   /// Get the entry count for this function.
   ///
   /// Entry count is the number of times the function was executed.
-  /// When AllowSynthetic is false, only pgo_data will be returned.
-  std::optional<ProfileCount> getEntryCount(bool AllowSynthetic = false) const;
+  /// When \p AllowPseudo is false, supplementary AFDO profile counts in an
+  /// iFDO-optimized binary is not used.
+  std::optional<ProfileCount> getEntryCount(bool AllowPseudo = false) const;
 
   /// Return true if the function is annotated with profile data.
   ///
   /// Presence of entry counts from a profile run implies the function has
-  /// profile annotations. If IncludeSynthetic is false, only return true
-  /// when the profile data is real.
-  bool hasProfileData(bool IncludeSynthetic = false) const {
-    return getEntryCount(IncludeSynthetic).has_value();
+  /// profile annotations. If \p AllowPseudo is false, supplementary AFDO
+  /// profile counts in an iFDO-optimized binary is not used.
+  bool hasProfileData(bool AllowPseudo = false) const {
+    return getEntryCount(AllowPseudo).has_value();
   }
 
   /// Returns the set of GUIDs that needs to be imported to the function for
diff --git a/llvm/include/llvm/IR/MDBuilder.h b/llvm/include/llvm/IR/MDBuilder.h
index ce4e1da656049..c1aa28557f210 100644
--- a/llvm/include/llvm/IR/MDBuilder.h
+++ b/llvm/include/llvm/IR/MDBuilder.h
@@ -83,10 +83,10 @@ class MDBuilder {
   MDNode *createUnpredictable();
 
   /// Return metadata containing the entry \p Count for a function, a boolean
-  /// \Synthetic indicating whether the counts were synthetized, and the
-  /// GUIDs stored in \p Imports that need to be imported for sample PGO, to
-  /// enable the same inlines as the profiled optimized binary
-  MDNode *createFunctionEntryCount(uint64_t Count, bool Synthetic,
+  /// \p Pseudo indicating whether the counts were from supplementary AFDO
+  /// profiles, and the GUIDs stored in \p Imports that need to be imported for
+  /// sample PGO, to enable the same inlines as the profiled optimized binary
+  MDNode *createFunctionEntryCount(uint64_t Count, bool Pseudo,
                                    const DenseSet<GlobalValue::GUID> *Imports);
 
   /// Return metadata containing the section prefix for a global object.
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 85c28b0205691..23e08ba66238a 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -1119,9 +1119,8 @@ void Function::setEntryCount(ProfileCount Count,
     S = &ImportGUIDs;
 
   MDBuilder MDB(getContext());
-  setMetadata(
-      LLVMContext::MD_prof,
-      MDB.createFunctionEntryCount(Count.getCount(), Count.isSynthetic(), S));
+  setMetadata(LLVMContext::MD_prof, MDB.createFunctionEntryCount(
+                                        Count.getCount(), Count.isPseudo(), S));
 }
 
 void Function::setEntryCount(uint64_t Count, Function::ProfileCountType Type,
@@ -1129,7 +1128,7 @@ void Function::setEntryCount(uint64_t Count, Function::ProfileCountType Type,
   setEntryCount(ProfileCount(Count, Type), Imports);
 }
 
-std::optional<ProfileCount> Function::getEntryCount(bool AllowSynthetic) const {
+std::optional<ProfileCount> Function::getEntryCount(bool AllowPseudo) const {
   MDNode *MD = getMetadata(LLVMContext::MD_prof);
   if (MD && MD->getOperand(0))
     if (MDString *MDS = dyn_cast<MDString>(MD->getOperand(0))) {
@@ -1141,11 +1140,11 @@ std::optional<ProfileCount> Function::getEntryCount(bool AllowSynthetic) const {
         if (Count == (uint64_t)-1)
           return std::nullopt;
         return ProfileCount(Count, PCT_Real);
-      } else if (AllowSynthetic &&
-                 MDS->getString() == "synthetic_function_entry_count") {
+      } else if (AllowPseudo &&
+                 MDS->getString() == "pseudo_function_entry_count") {
         ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(1));
         uint64_t Count = CI->getValue().getZExtValue();
-        return ProfileCount(Count, PCT_Synthetic);
+        return ProfileCount(Count, PCT_Pseudo);
       }
     }
   return std::nullopt;
diff --git a/llvm/lib/IR/MDBuilder.cpp b/llvm/lib/IR/MDBuilder.cpp
index b6aa8844a7eaf..849fd52024f30 100644
--- a/llvm/lib/IR/MDBuilder.cpp
+++ b/llvm/lib/IR/MDBuilder.cpp
@@ -69,12 +69,11 @@ MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights,
 MDNode *MDBuilder::createUnpredictable() { return MDNode::get(Context, {}); }
 
 MDNode *MDBuilder::createFunctionEntryCount(
-    uint64_t Count, bool Synthetic,
-    const DenseSet<GlobalValue::GUID> *Imports) {
+    uint64_t Count, bool Pseudo, const DenseSet<GlobalValue::GUID> *Imports) {
   Type *Int64Ty = Type::getInt64Ty(Context);
   SmallVector<Metadata *, 8> Ops;
-  if (Synthetic)
-    Ops.push_back(createString("synthetic_function_entry_count"));
+  if (Pseudo)
+    Ops.push_back(createString("pseudo_function_entry_count"));
   else
     Ops.push_back(createString("function_entry_count"));
   Ops.push_back(createConstant(ConstantInt::get(Int64Ty, Count)));
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index eaf57e7bf899d..92361b934e498 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -2046,7 +2046,7 @@ static void updateCallProfile(Function *Callee, const ValueToValueMapTy &VMap,
                               const ProfileCount &CalleeEntryCount,
                               const CallBase &TheCall, ProfileSummaryInfo *PSI,
                               BlockFrequencyInfo *CallerBFI) {
-  if (CalleeEntryCount.isSynthetic() || CalleeEntryCount.getCount() < 1)
+  if (CalleeEntryCount.isPseudo() || CalleeEntryCount.getCount() < 1)
     return;
   auto CallSiteCount =
       PSI ? PSI->getProfileCount(TheCall, CallerBFI) : std::nullopt;
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 56367e07b9d09..cc4b3ab10903b 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -5190,14 +5190,14 @@ TEST_F(FunctionAttachmentTest, RealEntryCount) {
   EXPECT_EQ(Function::PCT_Real, Count->getType());
 }
 
-TEST_F(FunctionAttachmentTest, SyntheticEntryCount) {
+TEST_F(FunctionAttachmentTest, PseudoEntryCount) {
   Function *F = getFunction("bar");
   EXPECT_FALSE(F->getEntryCount().has_value());
-  F->setEntryCount(123, Function::PCT_Synthetic);
-  auto Count = F->getEntryCount(true /*allow synthetic*/);
+  F->setEntryCount(123, Function::PCT_Pseudo);
+  auto Count = F->getEntryCount(true /*allow pseudo*/);
   EXPECT_TRUE(Count.has_value());
   EXPECT_EQ(123u, Count->getCount());
-  EXPECT_EQ(Function::PCT_Synthetic, Count->getType());
+  EXPECT_EQ(Function::PCT_Pseudo, Count->getType());
 }
 
 TEST_F(FunctionAttachmentTest, SubprogramAttachment) {



More information about the llvm-commits mailing list