summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuentin Colombet <qcolombet@apple.com>2016-05-04 22:45:31 +0000
committerQuentin Colombet <qcolombet@apple.com>2016-05-04 22:45:31 +0000
commit0c5bfd0514f90f0c7a33ab80c82f318d3d98a3af (patch)
tree8ada75497a8b0907cbf3a9278b95401e97794570
parent2da2982abe2844ac362b9517f4568faa90ece92b (diff)
downloadbcm5719-llvm-0c5bfd0514f90f0c7a33ab80c82f318d3d98a3af.tar.gz
bcm5719-llvm-0c5bfd0514f90f0c7a33ab80c82f318d3d98a3af.zip
[X86] Add a few register classes for x32 address accesses.
The new register classes allow to tell the machine verifier that it is fine to use RIP for address accesses in x32 mode. Prior to that patch, we would complain that we are using a GR64 in place of GR32, whereas it is actually fine to use GR64 for x32 as long as the 32 high bits are 0s. RIP has this property and is used for RIP-relative addressing. This partially fixes http://llvm.org/PR27481. llvm-svn: 268567
-rw-r--r--llvm/lib/Target/X86/X86RegisterInfo.cpp10
-rw-r--r--llvm/lib/Target/X86/X86RegisterInfo.td11
-rw-r--r--llvm/test/CodeGen/X86/musttail-varargs.ll10
3 files changed, 24 insertions, 7 deletions
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 1ea9533eaf9..c1da3db7cec 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -162,18 +162,24 @@ X86RegisterInfo::getPointerRegClass(const MachineFunction &MF,
case 0: // Normal GPRs.
if (Subtarget.isTarget64BitLP64())
return &X86::GR64RegClass;
- return &X86::GR32RegClass;
+ // If the target is 64bit but we have been told to use 32bit addresses,
+ // we can still use RIP-relative addresses.
+ // Reflect that in the returned register class.
+ return Is64Bit ? &X86::X32_ADDR_ACCESSRegClass : &X86::GR32RegClass;
case 1: // Normal GPRs except the stack pointer (for encoding reasons).
if (Subtarget.isTarget64BitLP64())
return &X86::GR64_NOSPRegClass;
+ // NOSP does not contain RIP, so no special case here.
return &X86::GR32_NOSPRegClass;
case 2: // NOREX GPRs.
if (Subtarget.isTarget64BitLP64())
return &X86::GR64_NOREXRegClass;
- return &X86::GR32_NOREXRegClass;
+ return Is64Bit ? &X86::X32_NOREX_ADDR_ACCESSRegClass
+ : &X86::GR32_NOREXRegClass;
case 3: // NOREX GPRs except the stack pointer (for encoding reasons).
if (Subtarget.isTarget64BitLP64())
return &X86::GR64_NOREX_NOSPRegClass;
+ // NOSP does not contain RIP, so no special case here.
return &X86::GR32_NOREX_NOSPRegClass;
case 4: // Available for tailcall (not callee-saved GPRs).
return getGPRsForTailCall(MF);
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.td b/llvm/lib/Target/X86/X86RegisterInfo.td
index dfbca49adae..ef02914ae27 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.td
+++ b/llvm/lib/Target/X86/X86RegisterInfo.td
@@ -415,6 +415,17 @@ def GR32_NOREX_NOSP : RegisterClass<"X86", [i32], 32,
def GR64_NOREX_NOSP : RegisterClass<"X86", [i64], 64,
(and GR64_NOREX, GR64_NOSP)>;
+// Register classes used for X32 address accesses.
+// In X32 mode it is fine to use RIP as we are sure the 32 high bits
+// are not set.
+// We do not need variants for NOSP as RIP is not allowed there.
+// Alignment is 64 because we have RIP.
+// FIXME: We could allow all 64bit registers, but we would need
+// something to check that the 32 high bits are not set.
+def X32_ADDR_ACCESS : RegisterClass<"X86", [i32], 64, (add GR32, RIP)>;
+def X32_NOREX_ADDR_ACCESS : RegisterClass<"X86", [i32], 64,
+ (add GR32_NOREX, RIP)>;
+
// A class to support the 'A' assembler constraint: EAX then EDX.
def GR32_AD : RegisterClass<"X86", [i32], 32, (add EAX, EDX)>;
diff --git a/llvm/test/CodeGen/X86/musttail-varargs.ll b/llvm/test/CodeGen/X86/musttail-varargs.ll
index db4a6f75d83..b3f73aaf890 100644
--- a/llvm/test/CodeGen/X86/musttail-varargs.ll
+++ b/llvm/test/CodeGen/X86/musttail-varargs.ll
@@ -1,8 +1,8 @@
-; RUN: llc < %s -enable-tail-merge=0 -mtriple=x86_64-linux | FileCheck %s --check-prefix=LINUX
-; RUN: llc < %s -enable-tail-merge=0 -mtriple=x86_64-linux-gnux32 | FileCheck %s --check-prefix=LINUX-X32
-; RUN: llc < %s -enable-tail-merge=0 -mtriple=x86_64-windows | FileCheck %s --check-prefix=WINDOWS
-; RUN: llc < %s -enable-tail-merge=0 -mtriple=i686-windows | FileCheck %s --check-prefix=X86
-; RUN: llc < %s -enable-tail-merge=0 -mtriple=i686-windows -mattr=+sse2 | FileCheck %s --check-prefix=X86
+; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-linux | FileCheck %s --check-prefix=LINUX
+; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-linux-gnux32 | FileCheck %s --check-prefix=LINUX-X32
+; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=x86_64-windows | FileCheck %s --check-prefix=WINDOWS
+; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=i686-windows | FileCheck %s --check-prefix=X86
+; RUN: llc -verify-machineinstrs < %s -enable-tail-merge=0 -mtriple=i686-windows -mattr=+sse2 | FileCheck %s --check-prefix=X86
; Test that we actually spill and reload all arguments in the variadic argument
; pack. Doing a normal call will clobber all argument registers, and we will
OpenPOWER on IntegriCloud