[llvm] Reland [RISCV] Check SP-relative offset in needsFrameBaseReg when FP offset overflows (PR #202499)

Garvit Gupta via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 8 23:05:38 PDT 2026


https://github.com/quic-garvgupt updated https://github.com/llvm/llvm-project/pull/202499

>From 243e4bd97c288304e84ec70e9a30b654f783db2e Mon Sep 17 00:00:00 2001
From: Garvit Gupta <garvgupt at qti.qualcomm.com>
Date: Fri, 5 Jun 2026 03:42:04 -0700
Subject: [PATCH] Reland [RISCV] Check SP-relative offset in needsFrameBaseReg
 when FP offset overflows

When a frame pointer is present, needsFrameBaseReg previously only
checked the FP-relative offset to decide if a virtual base register was
needed. If the worst-case FP offset exceeded the 12-bit immediate range,
a base register was always materialized, even when the SP-relative
offset would fit.

Since getFrameIndexReference can now select SP over FP when the offset
fits in the compressed instruction immediate range, also check the
SP-relative offset before deciding a base register is needed. This
avoids unnecessary base register materialization and results in some
code size savings.

Reland of b5d577d3faef.
---
 llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp   |  8 ++++-
 llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll  | 35 +++++++++----------
 .../RISCV/local-stack-slot-allocation.ll      |  5 ++-
 3 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 634f81fa18c53..7ee3542b05458 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -734,7 +734,13 @@ bool RISCVRegisterInfo::needsFrameBaseReg(MachineInstr *MI,
     }
 
     int64_t MaxFPOffset = Offset - CalleeSavedSize;
-    return !isFrameOffsetLegal(MI, RISCV::X8, MaxFPOffset);
+    if (isFrameOffsetLegal(MI, RISCV::X8, MaxFPOffset))
+      return false;
+
+    // If the FP-relative offset doesn't fit, fall through to check the
+    // SP-relative offset. getFrameIndexReference may select SP over FP when
+    // the SP offset fits in the compressed instruction immediate range, so a
+    // base register might not be needed.
   }
 
   // Assume 128 bytes spill slots size to estimate the maximum possible
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll
index 35368efbb659a..3d2ec63096251 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll
@@ -1670,20 +1670,19 @@ define i32 @va_large_stack(ptr %fmt, ...) {
 ; RV32-WITHFP-NEXT:    lui a0, 24414
 ; RV32-WITHFP-NEXT:    addi a0, a0, -1728
 ; RV32-WITHFP-NEXT:    sub sp, sp, a0
-; RV32-WITHFP-NEXT:    mv a0, sp
 ; RV32-WITHFP-NEXT:    sw a1, 4(s0)
 ; RV32-WITHFP-NEXT:    sw a2, 8(s0)
 ; RV32-WITHFP-NEXT:    sw a3, 12(s0)
 ; RV32-WITHFP-NEXT:    sw a4, 16(s0)
-; RV32-WITHFP-NEXT:    addi a1, s0, 4
-; RV32-WITHFP-NEXT:    sw a1, 0(a0)
-; RV32-WITHFP-NEXT:    lw a1, 0(a0)
+; RV32-WITHFP-NEXT:    addi a0, s0, 4
+; RV32-WITHFP-NEXT:    sw a0, 0(sp)
+; RV32-WITHFP-NEXT:    lw a0, 0(sp)
 ; RV32-WITHFP-NEXT:    sw a5, 20(s0)
 ; RV32-WITHFP-NEXT:    sw a6, 24(s0)
 ; RV32-WITHFP-NEXT:    sw a7, 28(s0)
-; RV32-WITHFP-NEXT:    addi a2, a1, 4
-; RV32-WITHFP-NEXT:    sw a2, 0(a0)
-; RV32-WITHFP-NEXT:    lw a0, 0(a1)
+; RV32-WITHFP-NEXT:    addi a1, a0, 4
+; RV32-WITHFP-NEXT:    sw a1, 0(sp)
+; RV32-WITHFP-NEXT:    lw a0, 0(a0)
 ; RV32-WITHFP-NEXT:    lui a1, 24414
 ; RV32-WITHFP-NEXT:    addi a1, a1, -1728
 ; RV32-WITHFP-NEXT:    add sp, sp, a1
@@ -1709,25 +1708,25 @@ define i32 @va_large_stack(ptr %fmt, ...) {
 ; RV64-WITHFP-NEXT:    lui a0, 24414
 ; RV64-WITHFP-NEXT:    addi a0, a0, -1680
 ; RV64-WITHFP-NEXT:    sub sp, sp, a0
-; RV64-WITHFP-NEXT:    mv a0, sp
 ; RV64-WITHFP-NEXT:    sd a1, 8(s0)
 ; RV64-WITHFP-NEXT:    sd a2, 16(s0)
 ; RV64-WITHFP-NEXT:    sd a3, 24(s0)
 ; RV64-WITHFP-NEXT:    sd a4, 32(s0)
+; RV64-WITHFP-NEXT:    mv a0, sp
 ; RV64-WITHFP-NEXT:    addi a1, s0, 8
-; RV64-WITHFP-NEXT:    sd a1, 0(a0)
-; RV64-WITHFP-NEXT:    lwu a1, 0(a0)
-; RV64-WITHFP-NEXT:    lw a2, 4(a0)
+; RV64-WITHFP-NEXT:    sd a1, 0(sp)
+; RV64-WITHFP-NEXT:    lw a0, 4(a0)
+; RV64-WITHFP-NEXT:    lwu a1, 0(sp)
 ; RV64-WITHFP-NEXT:    sd a5, 40(s0)
 ; RV64-WITHFP-NEXT:    sd a6, 48(s0)
 ; RV64-WITHFP-NEXT:    sd a7, 56(s0)
-; RV64-WITHFP-NEXT:    slli a2, a2, 32
-; RV64-WITHFP-NEXT:    or a1, a2, a1
-; RV64-WITHFP-NEXT:    addi a2, a1, 4
-; RV64-WITHFP-NEXT:    srli a3, a2, 32
-; RV64-WITHFP-NEXT:    sw a2, 0(a0)
-; RV64-WITHFP-NEXT:    sw a3, 4(a0)
-; RV64-WITHFP-NEXT:    lw a0, 0(a1)
+; RV64-WITHFP-NEXT:    slli a0, a0, 32
+; RV64-WITHFP-NEXT:    or a0, a0, a1
+; RV64-WITHFP-NEXT:    addi a1, a0, 4
+; RV64-WITHFP-NEXT:    srli a2, a1, 32
+; RV64-WITHFP-NEXT:    sw a1, 0(sp)
+; RV64-WITHFP-NEXT:    sw a2, 4(sp)
+; RV64-WITHFP-NEXT:    lw a0, 0(a0)
 ; RV64-WITHFP-NEXT:    lui a1, 24414
 ; RV64-WITHFP-NEXT:    addi a1, a1, -1680
 ; RV64-WITHFP-NEXT:    add sp, sp, a1
diff --git a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll
index 1ad78f4112351..9a535943d837d 100644
--- a/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll
+++ b/llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll
@@ -153,9 +153,8 @@ define void @frame_pointer() "frame-pointer"="all" {
 ; RV64I-NEXT:    addi s0, sp, 2032
 ; RV64I-NEXT:    .cfi_def_cfa s0, 0
 ; RV64I-NEXT:    addi sp, sp, -496
-; RV64I-NEXT:    addi a0, sp, 556
-; RV64I-NEXT:    lbu a1, 0(a0)
-; RV64I-NEXT:    sb a1, 0(a0)
+; RV64I-NEXT:    lbu a0, 556(sp)
+; RV64I-NEXT:    sb a0, 556(sp)
 ; RV64I-NEXT:    addi sp, sp, 496
 ; RV64I-NEXT:    .cfi_def_cfa sp, 2032
 ; RV64I-NEXT:    ld ra, 2024(sp) # 8-byte Folded Reload



More information about the llvm-commits mailing list