[llvm] [Inliner] Don't apply the cold-callsite threshold in non-callable functions (PR #211255)
Spencer Bryngelson via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 22 12:57:14 PDT 2026
https://github.com/sbryngelson updated https://github.com/llvm/llvm-project/pull/211255
>From 48b5eab52db49c2d26abd853f94c9d070057f6b7 Mon Sep 17 00:00:00 2001
From: Spencer Bryngelson <sbryngelson at gmail.com>
Date: Wed, 22 Jul 2026 08:15:27 -0500
Subject: [PATCH] [Inliner] Don't apply the cold-callsite threshold in
non-callable functions
A function whose calling convention is not callable is a hardware entry
point, e.g. a GPU kernel. Register allocation there is whole-function and
occupancy is set by the worst case over it, so a call left out of line
costs the hot path too, however cold the call itself is.
Skip the reduced cold-callsite threshold in that case, keyed off the
existing CallingConv::isCallableCC rather than a new target hook.
---
llvm/lib/Analysis/InlineCost.cpp | 8 ++-
.../Inline/AMDGPU/cold-callsite-in-kernel.ll | 59 +++++++++++++++++++
2 files changed, 66 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/Transforms/Inline/AMDGPU/cold-callsite-in-kernel.ll
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index 73f7f5e6cba04..266422d5cd3aa 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -2152,7 +2152,13 @@ void InlineCostCallAnalyzer::updateThreshold(CallBase &Call, Function &Callee) {
// behavior to prevent inlining of hot callsites during ThinLTO
// compile phase.
Threshold = *HotCallSiteThreshold;
- } else if (isColdCallSite(Call, CallerBFI)) {
+ } else if (isColdCallSite(Call, CallerBFI) &&
+ isCallableCC(Caller->getCallingConv())) {
+ // In a function that is a hardware entry point rather than something
+ // callable, e.g. a GPU kernel, register allocation is whole-function and
+ // occupancy is set by the worst case over it. A call left out of line
+ // there costs the hot path too, however cold the call itself is, so the
+ // reduced threshold does not apply.
LLVM_DEBUG(dbgs() << "Cold callsite.\n");
// Do not apply bonuses for a cold callsite including the
// LastCallToStatic bonus. While this bonus might result in code size
diff --git a/llvm/test/Transforms/Inline/AMDGPU/cold-callsite-in-kernel.ll b/llvm/test/Transforms/Inline/AMDGPU/cold-callsite-in-kernel.ll
new file mode 100644
index 0000000000000..3f4ba6271058d
--- /dev/null
+++ b/llvm/test/Transforms/Inline/AMDGPU/cold-callsite-in-kernel.ll
@@ -0,0 +1,59 @@
+; RUN: opt -passes=inline -mtriple=amdgpu-amd-amdhsa -inline-instr-cost=50 \
+; RUN: -pass-remarks=inline -pass-remarks-missed=inline < %s 2>&1 | FileCheck %s
+
+; A call left out of line in a kernel is register allocated against the worst
+; case for the whole kernel, so it costs the hot path too and the reduced
+; cold-callsite threshold does not apply. It still applies in a callable
+; caller. Both callsites are equally cold and the callee has two uses, so the
+; only difference is the caller's calling convention.
+
+; CHECK-DAG: 'callee' inlined into 'kernel'
+; CHECK-DAG: 'callee' not inlined into 'func' because too costly to inline
+
+define internal void @callee(ptr addrspace(1) %p, i32 %x) {
+entry:
+ %v0 = mul i32 %x, 3
+ %v1 = mul i32 %v0, 4
+ %v2 = mul i32 %v1, 5
+ %v3 = mul i32 %v2, 6
+ %v4 = mul i32 %v3, 7
+ %v5 = mul i32 %v4, 8
+ %v6 = mul i32 %v5, 9
+ %v7 = mul i32 %v6, 10
+ %v8 = mul i32 %v7, 11
+ %v9 = mul i32 %v8, 12
+ %v10 = mul i32 %v9, 13
+ %v11 = mul i32 %v10, 14
+ %v12 = mul i32 %v11, 15
+ %v13 = mul i32 %v12, 16
+ %v14 = mul i32 %v13, 17
+ %v15 = mul i32 %v14, 18
+ store i32 %v15, ptr addrspace(1) %p, align 4
+ ret void
+}
+
+define amdgpu_kernel void @kernel(ptr addrspace(1) %p, i32 %x, i1 %c) {
+entry:
+ br i1 %c, label %cold, label %exit, !prof !0
+
+cold:
+ call void @callee(ptr addrspace(1) %p, i32 %x)
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @func(ptr addrspace(1) %p, i32 %x, i1 %c) {
+entry:
+ br i1 %c, label %cold, label %exit, !prof !0
+
+cold:
+ call void @callee(ptr addrspace(1) %p, i32 %x)
+ br label %exit
+
+exit:
+ ret void
+}
+
+!0 = !{!"branch_weights", i32 1, i32 4000}
More information about the llvm-commits
mailing list