[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