[llvm] [AMDGPU][GlobalISel] Reject guaranteed tail calls in call lowering (PR #216260)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 13 23:43:06 PDT 2026


https://github.com/aobolensk created https://github.com/llvm/llvm-project/pull/216260

The FPDiff immediate was being written to the wrong operand, corrupting the callee GlobalAddress

Reject required tail calls like SelectionDAG does, and fix the stale index for the one path that still needs it (cs.chain lowering)

>From 80dd703bb7f25332a1de8ff08688a9cf41eae955 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 14 Aug 2026 08:42:07 +0200
Subject: [PATCH] [AMDGPU][GlobalISel] Reject guaranteed tail calls in call
 lowering

The FPDiff immediate was being written to the wrong operand, corrupting the callee GlobalAddress

Reject required tail calls like SelectionDAG does, and fix the stale index for the one path that still needs it (cs.chain lowering)
---
 llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp |  7 ++++++-
 llvm/test/CodeGen/AMDGPU/unsupported-calls.ll | 16 ++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
index 3c78bb1dd7be3..3a2de1c0b45b5 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp
@@ -1484,7 +1484,7 @@ bool AMDGPUCallLowering::lowerTailCall(
   // If we have -tailcallopt, we need to adjust the stack. We'll do the call
   // sequence start and end here.
   if (!IsSibCall) {
-    MIB->getOperand(CalleeIdx + 1).setImm(FPDiff);
+    MIB->getOperand(CalleeIdx + 2).setImm(FPDiff);
     CallSeqStart.addImm(NumBytes).addImm(0);
     // End the call sequence *before* emitting the call. Normally, we would
     // tidy the frame up after the call. However, here, we've laid out the
@@ -1613,6 +1613,11 @@ bool AMDGPUCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
   if (Info.CanLowerReturn && !Info.OrigRet.Ty->isVoidTy())
     splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv);
 
+  if (Info.IsTailCall && MF.getTarget().Options.GuaranteedTailCallOpt) {
+    LLVM_DEBUG(dbgs() << "Required tail calls not implemented\n");
+    return false;
+  }
+
   // If we can lower as a tail call, do that instead.
   bool CanTailCallOpt =
       isEligibleForTailCallOptimization(MIRBuilder, Info, InArgs, OutArgs);
diff --git a/llvm/test/CodeGen/AMDGPU/unsupported-calls.ll b/llvm/test/CodeGen/AMDGPU/unsupported-calls.ll
index 61140d383a151..0d509b3dda0c1 100644
--- a/llvm/test/CodeGen/AMDGPU/unsupported-calls.ll
+++ b/llvm/test/CodeGen/AMDGPU/unsupported-calls.ll
@@ -1,4 +1,5 @@
 ; RUN: not llc -mtriple=amdgpu6.00-mesa-mesa3d -tailcallopt < %s 2>&1 | FileCheck --check-prefix=GCN %s
+; RUN: not llc -global-isel -global-isel-abort=0 -mtriple=amdgpu6.00-mesa-mesa3d -tailcallopt < %s 2>&1 | FileCheck --check-prefix=GCN %s
 ; RUN: not llc -mtriple=amdgpu6.00--amdpal -tailcallopt < %s 2>&1 | FileCheck --check-prefix=GCN %s
 ; RUN: not llc -mtriple=r600-- -mcpu=cypress -tailcallopt < %s 2>&1 | FileCheck -check-prefix=R600 %s
 
@@ -43,6 +44,21 @@ define i32 @test_tail_call(ptr addrspace(1) %out, ptr addrspace(1) %in) {
   ret i32 %c
 }
 
+define fastcc i32 @defined_fastcc_function(i32 %x) nounwind noinline {
+  %y = add i32 %x, 8
+  ret i32 %y
+}
+
+; GCN: error: <unknown>:0:0: in function test_tail_call_fastcc i32 (ptr addrspace(1), ptr addrspace(1)): unsupported required tail call to function defined_fastcc_function
+; R600: in function test_tail_call_fastcc{{.*}}: unsupported call to function defined_fastcc_function
+define fastcc i32 @test_tail_call_fastcc(ptr addrspace(1) %out, ptr addrspace(1) %in) {
+  %b_ptr = getelementptr i32, ptr addrspace(1) %in, i32 1
+  %a = load i32, ptr addrspace(1) %in
+  %b = load i32, ptr addrspace(1) %b_ptr
+  %c = tail call fastcc i32 @defined_fastcc_function(i32 %b)
+  ret i32 %c
+}
+
 ; R600: in function test_c_call{{.*}}: unsupported call to function defined_function
 define amdgpu_ps i32 @test_c_call_from_shader() {
   %call = call i32 @defined_function(i32 0)



More information about the llvm-commits mailing list