Skip to content

Commit 8d52097

Browse files
committed
[X86] Use indirect addressing for high 2GB of x32 address space
Instructions that take immediate addresses sign-extend their operands, so cannot be used when we actually need zero extension. Use indirect addressing to avoid problems. The functions in the test are a modified versions of the functions by the same names in large-constants.ll, with i64 types changed to i32. Fixes #55061 Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D124406
1 parent 837a26f commit 8d52097

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1699,10 +1699,28 @@ bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
16991699
if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
17001700
!isDispSafeForFrameIndex(Val))
17011701
return true;
1702+
// In ILP32 (x32) mode, pointers are 32 bits and need to be zero-extended to
1703+
// 64 bits. Instructions with 32-bit register addresses perform this zero
1704+
// extension for us and we can safely ignore the high bits of Offset.
1705+
// Instructions with only a 32-bit immediate address do not, though: they
1706+
// sign extend instead. This means only address the low 2GB of address space
1707+
// is directly addressable, we need indirect addressing for the high 2GB of
1708+
// address space.
1709+
// TODO: Some of the earlier checks may be relaxed for ILP32 mode as the
1710+
// implicit zero extension of instructions would cover up any problem.
1711+
// However, we have asserts elsewhere that get triggered if we do, so keep
1712+
// the checks for now.
1713+
// TODO: We would actually be able to accept these, as well as the same
1714+
// addresses in LP64 mode, by adding the EIZ pseudo-register as an operand
1715+
// to get an address size override to be emitted. However, this
1716+
// pseudo-register is not part of any register class and therefore causes
1717+
// MIR verification to fail.
1718+
if (Subtarget->isTarget64BitILP32() && !isUInt<31>(Val) &&
1719+
!AM.hasBaseOrIndexReg())
1720+
return true;
17021721
}
17031722
AM.Disp = Val;
17041723
return false;
1705-
17061724
}
17071725

17081726
bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *N, X86ISelAddressMode &AM,

llvm/test/CodeGen/X86/large-constants-x32.ll

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
define void @constant_expressions() {
55
; CHECK-LABEL: constant_expressions:
66
; CHECK: # %bb.0: # %entry
7-
; CHECK-NEXT: movl -289477652, %eax
8-
; CHECK-NEXT: movl -289477644, %ecx
9-
; CHECK-NEXT: addl -289477648, %eax
10-
; CHECK-NEXT: addl -289477636, %ecx
11-
; CHECK-NEXT: addl %eax, %ecx
12-
; CHECK-NEXT: movl %ecx, -289477652
7+
; CHECK-NEXT: movl $-289477652, %eax # imm = 0xEEBEEBEC
8+
; CHECK-NEXT: movl (%eax), %ecx
9+
; CHECK-NEXT: movl $-289477644, %edx # imm = 0xEEBEEBF4
10+
; CHECK-NEXT: movl (%edx), %edx
11+
; CHECK-NEXT: movl $-289477648, %esi # imm = 0xEEBEEBF0
12+
; CHECK-NEXT: addl (%esi), %ecx
13+
; CHECK-NEXT: movl $-289477636, %esi # imm = 0xEEBEEBFC
14+
; CHECK-NEXT: addl (%esi), %edx
15+
; CHECK-NEXT: addl %ecx, %edx
16+
; CHECK-NEXT: movl %edx, (%eax)
1317
; CHECK-NEXT: retq
1418
entry:
1519
%0 = load i32, i32* inttoptr (i32 add (i32 -289477652, i32 0) to i32*)
@@ -27,12 +31,16 @@ entry:
2731
define void @constant_expressions2() {
2832
; CHECK-LABEL: constant_expressions2:
2933
; CHECK: # %bb.0: # %entry
30-
; CHECK-NEXT: movl -289477652, %eax
31-
; CHECK-NEXT: movl -289477644, %ecx
32-
; CHECK-NEXT: addl -289477648, %eax
33-
; CHECK-NEXT: addl -289477640, %ecx
34-
; CHECK-NEXT: addl %eax, %ecx
35-
; CHECK-NEXT: movl %ecx, -289477652
34+
; CHECK-NEXT: movl $-289477652, %eax # imm = 0xEEBEEBEC
35+
; CHECK-NEXT: movl (%eax), %ecx
36+
; CHECK-NEXT: movl $-289477644, %edx # imm = 0xEEBEEBF4
37+
; CHECK-NEXT: movl (%edx), %edx
38+
; CHECK-NEXT: movl $-289477648, %esi # imm = 0xEEBEEBF0
39+
; CHECK-NEXT: addl (%esi), %ecx
40+
; CHECK-NEXT: movl $-289477640, %esi # imm = 0xEEBEEBF8
41+
; CHECK-NEXT: addl (%esi), %edx
42+
; CHECK-NEXT: addl %ecx, %edx
43+
; CHECK-NEXT: movl %edx, (%eax)
3644
; CHECK-NEXT: retq
3745
entry:
3846
%0 = load i32, i32* inttoptr (i32 -289477652 to i32*)

0 commit comments

Comments
 (0)