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

Garvit Gupta via llvm-commits llvm-commits at lists.llvm.org
Tue May 12 23:09:54 PDT 2026


https://github.com/quic-garvgupt created https://github.com/llvm/llvm-project/pull/197368

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.

>From 852e3e25e7c9d825405b16f07cd69e23c08b53b8 Mon Sep 17 00:00:00 2001
From: Garvit Gupta <garvgupt at qti.qualcomm.com>
Date: Tue, 12 May 2026 23:06:44 -0700
Subject: [PATCH] [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.
---
 llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp            | 8 +++++++-
 llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll | 5 ++---
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 6baa30cf9e6f6..30441eaee87f0 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -725,7 +725,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/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