Skip to content

Commit

Permalink
[X86] Don't fold very large offsets into addr displacements during ISel
Browse files Browse the repository at this point in the history
Doing so can cause the resulting displacement after frame layout to
become inexpressible (or cause over/underflow currently during frame
layout).
  • Loading branch information
wesleywiser committed Jan 5, 2025
1 parent 88a6828 commit ebee0ae
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 8 deletions.
15 changes: 9 additions & 6 deletions llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1800,10 +1800,10 @@ void X86DAGToDAGISel::emitFunctionEntryCode() {
emitSpecialCodeForMain();
}

static bool isDispSafeForFrameIndex(int64_t Val) {
// On 64-bit platforms, we can run into an issue where a frame index
static bool isDispSafeForFrameIndexOrRegBase(int64_t Val) {
// We can run into an issue where a frame index or a register base
// includes a displacement that, when added to the explicit displacement,
// will overflow the displacement field. Assuming that the frame index
// will overflow the displacement field. Assuming that the
// displacement fits into a 31-bit integer (which is only slightly more
// aggressive than the current fundamental assumption that it fits into
// a 32-bit integer), a 31-bit disp should always be safe.
Expand Down Expand Up @@ -1831,7 +1831,7 @@ bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
// In addition to the checks required for a register base, check that
// we do not try to use an unsafe Disp with a frame index.
if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
!isDispSafeForFrameIndex(Val))
!isDispSafeForFrameIndexOrRegBase(Val))
return true;
// In ILP32 (x32) mode, pointers are 32 bits and need to be zero-extended to
// 64 bits. Instructions with 32-bit register addresses perform this zero
Expand All @@ -1852,7 +1852,10 @@ bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
if (Subtarget->isTarget64BitILP32() && !isUInt<31>(Val) &&
!AM.hasBaseOrIndexReg())
return true;
}
} else if (AM.hasBaseOrIndexReg() && !isDispSafeForFrameIndexOrRegBase(Val))
// For 32-bit X86, make sure the displacement still isn't close to the
// expressible limit.
return true;
AM.Disp = Val;
return false;
}
Expand Down Expand Up @@ -2553,7 +2556,7 @@ bool X86DAGToDAGISel::matchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
case ISD::FrameIndex:
if (AM.BaseType == X86ISelAddressMode::RegBase &&
AM.Base_Reg.getNode() == nullptr &&
(!Subtarget->is64Bit() || isDispSafeForFrameIndex(AM.Disp))) {
(!Subtarget->is64Bit() || isDispSafeForFrameIndexOrRegBase(AM.Disp))) {
AM.BaseType = X86ISelAddressMode::FrameIndexBase;
AM.Base_FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
return false;
Expand Down
3 changes: 2 additions & 1 deletion llvm/test/CodeGen/X86/dag-large-offset.ll
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ define i32 @foo(i1 %b) #0 {
; CHECK-NEXT: xorl %esi, %esi
; CHECK-NEXT: jmp LBB0_3
; CHECK-NEXT: LBB0_1:
; CHECK-NEXT: leal 2147483640(%ebp), %esi
; CHECK-NEXT: movl $-2147483647, %eax # imm = 0x80000001
; CHECK-NEXT: leal -9(%ebp,%eax), %esi
; CHECK-NEXT: LBB0_3: # %entry
; CHECK-NEXT: movl -8(%ebp), %ecx
; CHECK-NEXT: xorl %ebp, %ecx
Expand Down
3 changes: 2 additions & 1 deletion llvm/test/CodeGen/X86/xor-lea.ll
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@ define i32 @xor_shl_sminval_i32(i32 %x) {
; X86-LABEL: xor_shl_sminval_i32:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: leal -2147483648(,%eax,8), %eax
; X86-NEXT: movl $-2147483648, %ecx # imm = 0x80000000
; X86-NEXT: leal (%ecx,%eax,8), %eax
; X86-NEXT: retl
;
; X64-LABEL: xor_shl_sminval_i32:
Expand Down

0 comments on commit ebee0ae

Please sign in to comment.