[llvm] 10ce0f7 - [ICP] Introduce a hot function cutoff threshold for ICP (#208060)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 28 22:07:03 PDT 2026
Author: Congzhe Cao
Date: 2026-07-29T05:06:58Z
New Revision: 10ce0f74886f04a78b1183b598a656cb0957b15a
URL: https://github.com/llvm/llvm-project/commit/10ce0f74886f04a78b1183b598a656cb0957b15a
DIFF: https://github.com/llvm/llvm-project/commit/10ce0f74886f04a78b1183b598a656cb0957b15a.diff
LOG: [ICP] Introduce a hot function cutoff threshold for ICP (#208060)
Introduce a new hot function cutoff threshold specific to Indirect Call
Promotion (ICP) that can enable promotion of more indirect call targets.
Currently by default the threshold value is the same as the general
threshold `ProfileSummaryCutoffHot` that had also been used for ICP, so
by default the ICP behavior stays exactly the same unless users
specify some other value for the new threshold `-hot-func-cutoff-for-icp`.
Added:
llvm/test/Transforms/PGOProfile/icp_hot_func_threshold.ll
Modified:
llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
index cc6361f03d89b..f18287ba9de27 100644
--- a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
+++ b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
@@ -32,6 +32,7 @@
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Value.h"
#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -160,6 +161,14 @@ static cl::list<std::string> ICPIgnoredBaseTypes(
"binary could be
diff erent due to profiling limitations. Type info "
"names are those string literals used in LLVM type metadata"));
+static cl::opt<int> HotFuncCutoffForICP(
+ "hot-func-cutoff-for-icp", cl::Hidden, cl::init(-1),
+ cl::desc("A count is hot for indirect call promotion if it exceeds "
+ "the minimum count to reach this percentile of total counts."
+ "Note that this percentile is specified as "
+ "percentile * 10000 = HotFuncCutoffForICP."
+ "Default value -1 means that if the flag is unspecified then "
+ "the value of ProfileSummaryCutoffHot will be used instead."));
namespace {
// The key is a vtable global variable, and the value is a map.
@@ -881,8 +890,14 @@ bool IndirectCallPromoter::processFunction(ProfileSummaryInfo *PSI) {
<< TotalCount << "\n");
continue;
}
- // Only pormote hot if ICPAllowHotOnly is true.
- if (ICPAllowHotOnly && !PSI->isHotCount(TotalCount)) {
+ // Only promote hot if ICPAllowHotOnly is true. ICP has its own cutoff
+ // threshold for hotness, which defaults to ProfileSummaryCutoffHot if
+ // unspecified.
+ if (ICPAllowHotOnly &&
+ !PSI->isHotCountNthPercentile(HotFuncCutoffForICP == -1
+ ? ProfileSummaryCutoffHot
+ : HotFuncCutoffForICP,
+ TotalCount)) {
LLVM_DEBUG(dbgs() << "Don't promote the non-hot candidate: TotalCount="
<< TotalCount << "\n");
continue;
diff --git a/llvm/test/Transforms/PGOProfile/icp_hot_func_threshold.ll b/llvm/test/Transforms/PGOProfile/icp_hot_func_threshold.ll
new file mode 100644
index 0000000000000..24339ec110b7c
--- /dev/null
+++ b/llvm/test/Transforms/PGOProfile/icp_hot_func_threshold.ll
@@ -0,0 +1,102 @@
+; RUN: opt < %s -passes=pgo-icall-prom -hot-func-cutoff-for-icp=200000 -pass-remarks=pgo-icall-prom 2>&1 | FileCheck %s --check-prefix=PASS-REMARK
+; RUN: opt < %s -passes=pgo-icall-prom -hot-func-cutoff-for-icp=100000 -pass-remarks=pgo-icall-prom 2>&1 | FileCheck %s --check-prefix=FAIL-REMARK
+; RUN: opt < %s -passes=pgo-icall-prom -pass-remarks=pgo-icall-prom 2>&1 | FileCheck %s --check-prefix=PASS-REMARK-DEFAULT
+
+; ICP has its own cutoff threshold for hotness that can be tuned.
+
+;; Cutoff of 200000 (20%) has a cutoff count of 14. The profile count of the VP metadata for %call reaches 14
+;; so it is promoted. The profile count of the VP metadata for %call2 is 5 and does not reach 14,
+;; so it is not promoted.
+; PASS-REMARK: remark: <unknown>:0:0: Promote indirect call to func4 with count 5 out of 14
+; PASS-REMARK: remark: <unknown>:0:0: Promote indirect call to func2 with count 4 out of 9
+; PASS-REMARK: remark: <unknown>:0:0: Promote indirect call to func3 with count 3 out of 5
+; PASS-REMARK-NOT: remark: <unknown>:0:0: Promote indirect call to func4 with count 3 out of 5
+; PASS-REMARK-NOT: remark: <unknown>:0:0: Promote indirect call to func2 with count 1 out of 2
+
+;; Cutoff of 100000 (10%) has a cutoff count of 15. Neither of the profile counts of %call and %call2
+;; reaches 15 so nothing is promoted.
+; FAIL-REMARK-NOT: Promote indirect call
+
+;; If ICP does not specify "-hot-func-cutoff-for-icp", then it falls back to the default ProfileSummaryCutoffHot value,
+;; and both "%call" and "%call2" will be promoted.
+; PASS-REMARK-DEFAULT: remark: <unknown>:0:0: Promote indirect call to func4 with count 5 out of 14
+; PASS-REMARK-DEFAULT: remark: <unknown>:0:0: Promote indirect call to func2 with count 4 out of 9
+; PASS-REMARK-DEFAULT: remark: <unknown>:0:0: Promote indirect call to func3 with count 3 out of 5
+; PASS-REMARK-DEFAULT: remark: <unknown>:0:0: Promote indirect call to func4 with count 3 out of 5
+; PASS-REMARK-DEFAULT: remark: <unknown>:0:0: Promote indirect call to func2 with count 1 out of 2
+
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at foo = common global ptr null, align 8
+ at baz = common global ptr null, align 8
+
+define i32 @func1() {
+entry:
+ ret i32 0
+}
+
+define i32 @func2() {
+entry:
+ ret i32 1
+}
+
+define i32 @func3() {
+entry:
+ ret i32 2
+}
+
+define i32 @func4() {
+entry:
+ ret i32 3
+}
+
+define i32 @bar() {
+entry:
+ %tmp = load ptr, ptr @foo, align 8
+ %tmp2 = load ptr, ptr @baz, align 8
+ %call = call i32 %tmp(), !prof !34
+ %call2 = call i32 %tmp2(), !prof !35
+ ret i32 %call
+}
+
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"PIC Level", i32 2}
+!2 = !{i32 7, !"PIE Level", i32 2}
+!3 = !{i32 7, !"uwtable", i32 2}
+!4 = !{i32 7, !"frame-pointer", i32 1}
+!5 = !{i32 1, !"ProfileSummary", !6}
+!6 = !{!7, !8, !9, !10, !11, !12, !13, !14, !15, !16}
+!7 = !{!"ProfileFormat", !"InstrProf"}
+!8 = !{!"TotalCount", i64 136}
+!9 = !{!"MaxCount", i64 16}
+!10 = !{!"MaxInternalCount", i64 5}
+!11 = !{!"MaxFunctionCount", i64 16}
+!12 = !{!"NumCounts", i64 16}
+!13 = !{!"NumFunctions", i64 4}
+!14 = !{!"IsPartialProfile", i64 0}
+!15 = !{!"PartialProfileRatio", double 0.000000e+00}
+!16 = !{!"DetailedSummary", !17}
+!17 = !{!18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33}
+!18 = !{i32 10000, i64 16, i32 1}
+!19 = !{i32 100000, i64 15, i32 2}
+!20 = !{i32 200000, i64 14, i32 3}
+!21 = !{i32 300000, i64 13, i32 4}
+!22 = !{i32 400000, i64 12, i32 5}
+!23 = !{i32 500000, i64 11, i32 6}
+!24 = !{i32 600000, i64 10, i32 7}
+!25 = !{i32 700000, i64 9, i32 8}
+!26 = !{i32 800000, i64 8, i32 9}
+!27 = !{i32 900000, i64 7, i32 10}
+!28 = !{i32 950000, i64 6, i32 11}
+!29 = !{i32 990000, i64 5, i32 12}
+!30 = !{i32 999000, i64 4, i32 13}
+!31 = !{i32 999900, i64 3, i32 14}
+!32 = !{i32 999990, i64 2, i32 15}
+!33 = !{i32 999999, i64 1, i32 16}
+!34 = !{!"VP", i32 0, i64 14, i64 7651369219802541373, i64 5, i64 -4377547752858689819, i64 4, i64 -6929281286627296573, i64 3, i64 -2545542355363006406, i64 2}
+!35 = !{!"VP", i32 0, i64 5, i64 7651369219802541373, i64 3, i64 -4377547752858689819, i64 1}
\ No newline at end of file
More information about the llvm-commits
mailing list