[llvm] [AMDGPU] Fix eliminateFrameIndex assertion when reusing the frame register. (PR #215182)
Vikash Gupta via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 11 03:03:29 PDT 2026
https://github.com/vg0204 updated https://github.com/llvm/llvm-project/pull/215182
>From 81bba0ddfa06f88688f4078da644fd80d3b9252f Mon Sep 17 00:00:00 2001
From: vg0204 <Vikash.Gupta at amd.com>
Date: Fri, 7 Aug 2026 17:21:32 +0530
Subject: [PATCH 1/2] [AMDGPU] Fix eliminateFrameIndex assertion when reusing
the frame register
On a flat-scratch target, a frame index used by a VALU instruction with
a live frame register but no scavengeable SGPR entered the branch that
assumes no frame register exists, tripping `assert(!FrameReg && "there
is a frame register!")`.
Restore the `!FrameReg` term in the guard so this case falls through to
the existing path that reuses the frame register as the temporary (offset
folded in, then restored). The `!FrameReg` assertion is moved into the
SVS fallback, where it actually holds.
This resolves the pre-commit testcase in the cdcd
---
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 12 ++++++++++--
...me-index-flat-scratch-frame-reg-no-sgpr.ll | 19 +++++++++++++------
2 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index a3d6509628d50..c661787b301c0 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -3260,10 +3260,18 @@ bool SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
: RS->scavengeRegisterBackwards(AMDGPU::SReg_32_XM0RegClass,
MI, false, 0, !UseSGPR);
- if (!TmpSReg || (!TmpReg && !UseSGPR)) {
- assert(!FrameReg && "there is a frame register!");
+ // If no SGPR was scavenged but a frame register is available, fall
+ // through to reuse it as the temporary (computed in place, restored
+ // after). Only bail out when there is no frame register, or a VGPR
+ // operand is needed but none could be scavenged.
+ if ((!TmpSReg && !FrameReg) || (!TmpReg && !UseSGPR)) {
int SVOpcode = AMDGPU::getFlatScratchInstSVfromSS(MI->getOpcode());
if (ST.hasFlatScratchSVSMode() && SVOpcode != -1) {
+ // SV form encodes only the offset in vaddr; an SS-form scratch op
+ // keeps its FI in the SGPR saddr, so this is only reached with no
+ // frame register.
+ assert(!FrameReg &&
+ "SV-form fallback cannot encode a frame register");
Register TmpVGPR = RS->scavengeRegisterBackwards(
AMDGPU::VGPR_32RegClass, MI, false, 0, /*AllowSpill=*/true);
diff --git a/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll b/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll
index b4a1b565032da..9fe4c547a3e72 100644
--- a/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll
+++ b/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll
@@ -1,12 +1,13 @@
; RUN: not --crash llc -mtriple=amdgpu9.42-amd-amdhsa -amdgpu-stress-sgpr=16 < %s 2>&1 | FileCheck %s
; REQUIRES: asserts
-; NOTE: SIRegisterInfo::eliminateFrameIndex currently asserts on a
-; flat-scratch target when a frame index used by a VALU instruction reaches the
-; generic SGPR scavenging path, the function has a frame register, and no SGPR
-; is free for the scavenger. Control then enters the branch that assumes no
-; frame register exists: it asserts !FrameReg and its SVS lowering materializes
-; the address from the offset alone, without a frame-register term.
+; Verifies SIRegisterInfo::eliminateFrameIndex on a flat-scratch target: a frame
+; index used by a VALU instruction reaches the generic SGPR scavenging path.
+; When the function has a frame register but no SGPR is free for the scavenger,
+; the fix reuses the frame register as the temporary instead of taking the SVS
+; fallback (which assumes no frame register and previously asserted here). The
+; offset is folded into the frame register in place, the subtract reads it
+; directly as an SGPR source, and the frame register is restored afterwards.
;
; The reproducer needs all of following conditions:
; 1. A VALU frame-index user (V_SUB_CO_U32_e32 from the addrspacecast).
@@ -20,6 +21,12 @@
; CHECK: there is a frame register!
define fastcc i64 @no_scavengeable_sgpr_with_frame_register(
+; CHECK-LABEL: no_scavengeable_sgpr_with_frame_register:
+; Fold the frame-index offset into the frame register in place, use it directly
+; as the SGPR source of the subtract, then restore the frame register.
+; CHECK: s_add_i32 s32, s32, 24
+; CHECK: v_sub_co_u32_e32 v0, vcc, s32, v0
+; CHECK: s_addk_i32 s32, 0xffe8
ptr %p0, i32 %i0, i64 %l0, i64 %l1, i64 %l2,
i64 %l3, i64 %l4, i16 %s0, i32 %i1, ptr %p1,
i64 %l5, i32 %i2, i32 %i3, i32 %i4,
>From 0dc66aa78c1ee27a06e0c3808b677808d6de453d Mon Sep 17 00:00:00 2001
From: vg0204 <Vikash.Gupta at amd.com>
Date: Mon, 10 Aug 2026 15:07:07 +0530
Subject: [PATCH 2/2] updated the crashing test that got fixed.
---
.../eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll b/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll
index 9fe4c547a3e72..ce8c21bcce617 100644
--- a/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll
+++ b/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-flat-scratch-frame-reg-no-sgpr.ll
@@ -1,5 +1,4 @@
-; RUN: not --crash llc -mtriple=amdgpu9.42-amd-amdhsa -amdgpu-stress-sgpr=16 < %s 2>&1 | FileCheck %s
-; REQUIRES: asserts
+; RUN: llc -mtriple=amdgpu9.42-amd-amdhsa -amdgpu-stress-sgpr=16 < %s 2>&1 | FileCheck %s
; Verifies SIRegisterInfo::eliminateFrameIndex on a flat-scratch target: a frame
; index used by a VALU instruction reaches the generic SGPR scavenging path.
@@ -18,8 +17,6 @@
; The data dependency through %diff keeps every SGPR live across the subtract so
; the scheduler cannot free one up.
-; CHECK: there is a frame register!
-
define fastcc i64 @no_scavengeable_sgpr_with_frame_register(
; CHECK-LABEL: no_scavengeable_sgpr_with_frame_register:
; Fold the frame-index offset into the frame register in place, use it directly
More information about the llvm-commits
mailing list