Skip to content

Commit 56142a5

Browse files
committed
[X86] Don't fold very large offsets into addr displacements during ISel
Doing so can cause the resulting displacement after frame layout to become inexpressible (or cause over/underflow currently during frame layout).
1 parent 7f78b6c commit 56142a5

File tree

3 files changed

+15
-9
lines changed

3 files changed

+15
-9
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,10 +1800,10 @@ void X86DAGToDAGISel::emitFunctionEntryCode() {
18001800
emitSpecialCodeForMain();
18011801
}
18021802

1803-
static bool isDispSafeForFrameIndex(int64_t Val) {
1804-
// On 64-bit platforms, we can run into an issue where a frame index
1803+
static bool isDispSafeForFrameIndexOrRegBase(int64_t Val) {
1804+
// We can run into an issue where a frame index or a register base
18051805
// includes a displacement that, when added to the explicit displacement,
1806-
// will overflow the displacement field. Assuming that the frame index
1806+
// will overflow the displacement field. Assuming that the
18071807
// displacement fits into a 31-bit integer (which is only slightly more
18081808
// aggressive than the current fundamental assumption that it fits into
18091809
// a 32-bit integer), a 31-bit disp should always be safe.
@@ -1831,7 +1831,7 @@ bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
18311831
// In addition to the checks required for a register base, check that
18321832
// we do not try to use an unsafe Disp with a frame index.
18331833
if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
1834-
!isDispSafeForFrameIndex(Val))
1834+
!isDispSafeForFrameIndexOrRegBase(Val))
18351835
return true;
18361836
// In ILP32 (x32) mode, pointers are 32 bits and need to be zero-extended to
18371837
// 64 bits. Instructions with 32-bit register addresses perform this zero
@@ -1849,10 +1849,14 @@ bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
18491849
// to get an address size override to be emitted. However, this
18501850
// pseudo-register is not part of any register class and therefore causes
18511851
// MIR verification to fail.
1852-
if (Subtarget->isTarget64BitILP32() && !isUInt<31>(Val) &&
1852+
if (Subtarget->isTarget64BitILP32() &&
1853+
!isDispSafeForFrameIndexOrRegBase((uint32_t)Val) &&
18531854
!AM.hasBaseOrIndexReg())
18541855
return true;
1855-
}
1856+
} else if (AM.hasBaseOrIndexReg() && !isDispSafeForFrameIndexOrRegBase(Val))
1857+
// For 32-bit X86, make sure the displacement still isn't close to the
1858+
// expressible limit.
1859+
return true;
18561860
AM.Disp = Val;
18571861
return false;
18581862
}
@@ -2553,7 +2557,7 @@ bool X86DAGToDAGISel::matchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
25532557
case ISD::FrameIndex:
25542558
if (AM.BaseType == X86ISelAddressMode::RegBase &&
25552559
AM.Base_Reg.getNode() == nullptr &&
2556-
(!Subtarget->is64Bit() || isDispSafeForFrameIndex(AM.Disp))) {
2560+
(!Subtarget->is64Bit() || isDispSafeForFrameIndexOrRegBase(AM.Disp))) {
25572561
AM.BaseType = X86ISelAddressMode::FrameIndexBase;
25582562
AM.Base_FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
25592563
return false;

llvm/test/CodeGen/X86/dag-large-offset.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ define i32 @foo(i1 %b) #0 {
2222
; CHECK-NEXT: xorl %eax, %eax
2323
; CHECK-NEXT: jmp .LBB0_3
2424
; CHECK-NEXT: .LBB0_1:
25-
; CHECK-NEXT: leal 2147483644(%ebp), %eax
25+
; CHECK-NEXT: movl $-2147483647, %eax # imm = 0x80000001
26+
; CHECK-NEXT: leal -5(%ebp,%eax), %eax
2627
; CHECK-NEXT: .LBB0_3: # %entry
2728
; CHECK-NEXT: movl __stack_chk_guard, %ecx
2829
; CHECK-NEXT: cmpl -4(%ebp), %ecx

llvm/test/CodeGen/X86/xor-lea.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,8 @@ define i32 @xor_shl_sminval_i32(i32 %x) {
327327
; X86-LABEL: xor_shl_sminval_i32:
328328
; X86: # %bb.0:
329329
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
330-
; X86-NEXT: leal -2147483648(,%eax,8), %eax
330+
; X86-NEXT: movl $-2147483648, %ecx # imm = 0x80000000
331+
; X86-NEXT: leal (%ecx,%eax,8), %eax
331332
; X86-NEXT: retl
332333
;
333334
; X64-LABEL: xor_shl_sminval_i32:

0 commit comments

Comments
 (0)