[llvm] 137d8e6 - [X86] Fix eliminateFrameIndex dropping existing index register for huge frame offsets

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 7 06:58:19 PDT 2026


Author: Alexey Bataev
Date: 2026-09-07T09:58:14-04:00
New Revision: 137d8e684984df207576c8f24bd8743ddb71c5c9

URL: https://github.com/llvm/llvm-project/commit/137d8e684984df207576c8f24bd8743ddb71c5c9
DIFF: https://github.com/llvm/llvm-project/commit/137d8e684984df207576c8f24bd8743ddb71c5c9.diff

LOG: [X86] Fix eliminateFrameIndex dropping existing index register for huge frame offsets

When the frame offset does not fit in disp32 and the address mode already
uses an index register, the register-scavenging path overwrote the index
operand with the scratch register, silently dropping the index from the
effective address (and applying the stale scale to the frame offset).
Fold the offset into the base register with an LEA in this case instead.

Fixes #213960

Assisted-by: Cursor

Reviewers: RKSimon, qcolombet

Pull Request: https://github.com/llvm/llvm-project/pull/221016

Added: 
    llvm/test/CodeGen/X86/huge-frame-index.ll

Modified: 
    llvm/lib/Target/X86/X86RegisterInfo.cpp
    llvm/test/CodeGen/X86/avx512f-large-stack.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 8bf56a7d6bbe6..cc132fa1bc4db 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -1024,7 +1024,19 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
       BuildMI(MBB, II, DL, TII->get(X86::MOV64ri), ScratchReg).addImm(Offset);
 
       MI.getOperand(FIOperandNum + 3).setImm(0);
-      MI.getOperand(FIOperandNum + 2).setReg(ScratchReg);
+      if (MI.getOperand(FIOperandNum + 2).getReg() == X86::NoRegister) {
+        MI.getOperand(FIOperandNum + 2).setReg(ScratchReg);
+      } else {
+        // The index register slot is already in use, fold the offset into
+        // the base register instead. LEA does not clobber EFLAGS.
+        BuildMI(MBB, II, DL, TII->get(X86::LEA64r), ScratchReg)
+            .addReg(MachineBasePtr)
+            .addImm(1)
+            .addReg(ScratchReg)
+            .addImm(0)
+            .addReg(X86::NoRegister);
+        MI.getOperand(FIOperandNum).setReg(ScratchReg);
+      }
 
       return false;
     }

diff  --git a/llvm/test/CodeGen/X86/avx512f-large-stack.ll b/llvm/test/CodeGen/X86/avx512f-large-stack.ll
index 3cb5391c56abf..6065cfb2ab4b6 100644
--- a/llvm/test/CodeGen/X86/avx512f-large-stack.ll
+++ b/llvm/test/CodeGen/X86/avx512f-large-stack.ll
@@ -10,7 +10,8 @@ define void @f(i16 %LGV2, i1 %LGV3) {
 ; CHECK-NEXT:    movswq %ax, %rax
 ; CHECK-NEXT:    andb $1, %cl
 ; CHECK-NEXT:    movabsq $-2147483768, %rdx # imm = 0xFFFFFFFF7FFFFF88
-; CHECK-NEXT:    movb %cl, (%rsp,%rdx)
+; CHECK-NEXT:    leaq (%rsp,%rdx), %rdx
+; CHECK-NEXT:    movb %cl, (%rdx,%rax)
 ; CHECK-NEXT:    addq $2147483528, %rsp # imm = 0x7FFFFF88
 ; CHECK-NEXT:    .cfi_def_cfa_offset 8
 ; CHECK-NEXT:    retq

diff  --git a/llvm/test/CodeGen/X86/huge-frame-index.ll b/llvm/test/CodeGen/X86/huge-frame-index.ll
new file mode 100644
index 0000000000000..ce24a0fbba2a4
--- /dev/null
+++ b/llvm/test/CodeGen/X86/huge-frame-index.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64 -frame-pointer=all -verify-machineinstrs | FileCheck %s
+
+; The frame offset does not fit in disp32 and the address mode already uses
+; an index register; the scavenged register holding the offset must be
+; combined with the base register, not overwrite the index register.
+
+define ptr @huge_frame_index() {
+; CHECK-LABEL: huge_frame_index:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    .cfi_offset %rbp, -16
+; CHECK-NEXT:    movq %rsp, %rbp
+; CHECK-NEXT:    .cfi_def_cfa_register %rbp
+; CHECK-NEXT:    movl $3221225352, %eax # imm = 0xBFFFFF88
+; CHECK-NEXT:    subq %rax, %rsp
+; CHECK-NEXT:    movl $3221225471, %eax # imm = 0xBFFFFFFF
+; CHECK-NEXT:    movabsq $-3221225480, %rcx # imm = 0xFFFFFFFF3FFFFFF8
+; CHECK-NEXT:    addq %rbp, %rcx
+; CHECK-NEXT:    addq %rcx, %rax
+; CHECK-NEXT:    addq $2147483647, %rsp # imm = 0x7FFFFFFF
+; CHECK-NEXT:    addq $1073741705, %rsp # imm = 0x3FFFFF89
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    .cfi_def_cfa %rsp, 8
+; CHECK-NEXT:    retq
+  %x = alloca [3221225472 x i8], align 1
+  %p = getelementptr i8, ptr %x, i64 3221225471
+  ret ptr %p
+}
+
+define ptr @huge_frame_index_scaled(i64 %i) {
+; CHECK-LABEL: huge_frame_index_scaled:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pushq %rbp
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    .cfi_offset %rbp, -16
+; CHECK-NEXT:    movq %rsp, %rbp
+; CHECK-NEXT:    .cfi_def_cfa_register %rbp
+; CHECK-NEXT:    movl $3221225352, %eax # imm = 0xBFFFFF88
+; CHECK-NEXT:    subq %rax, %rsp
+; CHECK-NEXT:    movabsq $-3221225480, %rcx # imm = 0xFFFFFFFF3FFFFFF8
+; CHECK-NEXT:    addq %rbp, %rcx
+; CHECK-NEXT:    leaq (%rcx,%rdi,4), %rax
+; CHECK-NEXT:    addq $2147483647, %rsp # imm = 0x7FFFFFFF
+; CHECK-NEXT:    addq $1073741705, %rsp # imm = 0x3FFFFF89
+; CHECK-NEXT:    popq %rbp
+; CHECK-NEXT:    .cfi_def_cfa %rsp, 8
+; CHECK-NEXT:    retq
+  %x = alloca [3221225472 x i8], align 1
+  %p = getelementptr i32, ptr %x, i64 %i
+  ret ptr %p
+}


        


More information about the llvm-commits mailing list