From c76507d03c22b3ba0cfeba87a505c5bad1128fb4 Mon Sep 17 00:00:00 2001
From: Derek Schuff <dschuff@google.com>
Date: Tue, 8 Sep 2015 19:47:15 +0000
Subject: [PATCH] x32. Fixes a bug in i8mem_NOREX declaration.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

The old implementation assumed LP64 which is broken for x32.  Specifically, the
MOVE8rm_NOREX and MOVE8mr_NOREX, when selected, would cause a 'Cannot emit
physreg copy instruction' error message to be reported.

This patch also enable the h-register*ll tests for x32.

Differential Revision: http://reviews.llvm.org/D12336

Patch by João Porto

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247058 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Target/X86/X86InstrInfo.td       | 13 ++++++++-----
 lib/Target/X86/X86RegisterInfo.cpp   | 10 +++++++++-
 test/CodeGen/X86/h-register-store.ll | 25 +++++++++++++++++--------
 test/CodeGen/X86/h-registers-0.ll    |  1 +
 test/CodeGen/X86/h-registers-1.ll    |  1 +
 test/CodeGen/X86/h-registers-3.ll    |  1 +
 6 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 5618c779608..73136d9c5d9 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -341,18 +341,21 @@ def vy64xmem : X86VMemOperand<VR256X, "printi64mem", X86MemVY64XOperand>;
 def vz32mem  : X86VMemOperand<VR512,  "printi32mem", X86MemVZ32Operand>;
 def vz64mem  : X86VMemOperand<VR512,  "printi64mem", X86MemVZ64Operand>;
 
-// A version of i8mem for use on x86-64 that uses GR64_NOREX instead of
-// plain GR64, so that it doesn't potentially require a REX prefix.
-def i8mem_NOREX : Operand<i64> {
+// A version of i8mem for use on x86-64 and x32 that uses a NOREX GPR instead
+// of a plain GPR, so that it doesn't potentially require a REX prefix.
+def ptr_rc_norex : PointerLikeRegClass<2>;
+def ptr_rc_norex_nosp : PointerLikeRegClass<3>;
+
+def i8mem_NOREX : Operand<iPTR> {
   let PrintMethod = "printi8mem";
-  let MIOperandInfo = (ops GR64_NOREX, i8imm, GR64_NOREX_NOSP, i32imm, i8imm);
+  let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm, i8imm);
   let ParserMatchClass = X86Mem8AsmOperand;
   let OperandType = "OPERAND_MEMORY";
 }
 
 // GPRs available for tailcall.
 // It represents GR32_TC, GR64_TC or GR64_TCW64.
-def ptr_rc_tailcall : PointerLikeRegClass<2>;
+def ptr_rc_tailcall : PointerLikeRegClass<4>;
 
 // Special i32mem for addresses of load folding tail calls. These are not
 // allowed to use callee-saved registers since they must be scheduled
diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp
index ff6b204482e..7b04e81c483 100644
--- a/lib/Target/X86/X86RegisterInfo.cpp
+++ b/lib/Target/X86/X86RegisterInfo.cpp
@@ -168,7 +168,15 @@ X86RegisterInfo::getPointerRegClass(const MachineFunction &MF,
     if (Subtarget.isTarget64BitLP64())
       return &X86::GR64_NOSPRegClass;
     return &X86::GR32_NOSPRegClass;
-  case 2: // Available for tailcall (not callee-saved GPRs).
+  case 2: // NOREX GPRs.
+    if (Subtarget.isTarget64BitLP64())
+      return &X86::GR64_NOREXRegClass;
+    return &X86::GR32_NOREXRegClass;
+  case 3: // NOREX GPRs except the stack pointer (for encoding reasons).
+    if (Subtarget.isTarget64BitLP64())
+      return &X86::GR64_NOREX_NOSPRegClass;
+    return &X86::GR32_NOREX_NOSPRegClass;
+  case 4: // Available for tailcall (not callee-saved GPRs).
     const Function *F = MF.getFunction();
     if (IsWin64 || (F && F->getCallingConv() == CallingConv::X86_64_Win64))
       return &X86::GR64_TCW64RegClass;
diff --git a/test/CodeGen/X86/h-register-store.ll b/test/CodeGen/X86/h-register-store.ll
index 0adb2b148c3..0e6a0236d2c 100644
--- a/test/CodeGen/X86/h-register-store.ll
+++ b/test/CodeGen/X86/h-register-store.ll
@@ -7,6 +7,15 @@
 ; X64-NEXT: movb %ah, (%rsi)
 ; X64-NOT:      mov
 
+; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s -check-prefix=X32
+; X32:      mov
+; X32-NEXT: movb %ah, (%esi)
+; X32:      mov
+; X32-NEXT: movb %ah, (%esi)
+; X32:      mov
+; X32-NEXT: movb %ah, (%esi)
+; X32-NOT:      mov
+
 ; RUN: llc < %s -mtriple=x86_64-win32 | FileCheck %s -check-prefix=W64
 ; W64-NOT:      mov
 ; W64:      movb %ch, (%rdx)
@@ -16,14 +25,14 @@
 ; W64:      movb %ch, (%rdx)
 ; W64-NOT:      mov
 
-; RUN: llc < %s -march=x86 | FileCheck %s -check-prefix=X32
-; X32-NOT:      mov
-; X32:      movb %ah, (%e
-; X32-NOT:      mov
-; X32:      movb %ah, (%e
-; X32-NOT:      mov
-; X32:      movb %ah, (%e
-; X32-NOT:      mov
+; RUN: llc < %s -march=x86 | FileCheck %s -check-prefix=X86
+; X86-NOT:      mov
+; X86:      movb %ah, (%e
+; X86-NOT:      mov
+; X86:      movb %ah, (%e
+; X86-NOT:      mov
+; X86:      movb %ah, (%e
+; X86-NOT:      mov
 
 ; Use h-register extract and store.
 
diff --git a/test/CodeGen/X86/h-registers-0.ll b/test/CodeGen/X86/h-registers-0.ll
index 6a5ccaa1e76..9b72916ea74 100644
--- a/test/CodeGen/X86/h-registers-0.ll
+++ b/test/CodeGen/X86/h-registers-0.ll
@@ -1,4 +1,5 @@
 ; RUN: llc < %s -mattr=-bmi -mtriple=x86_64-linux | FileCheck %s -check-prefix=X86-64
+; RUN: llc < %s -mattr=-bmi -mtriple=x86_64-linux-gnux32 | FileCheck %s -check-prefix=X86-64
 ; RUN: llc < %s -mattr=-bmi -mtriple=x86_64-win32 | FileCheck %s -check-prefix=WIN64
 ; RUN: llc < %s -mattr=-bmi -march=x86    | FileCheck %s -check-prefix=X86-32
 
diff --git a/test/CodeGen/X86/h-registers-1.ll b/test/CodeGen/X86/h-registers-1.ll
index 7254325a926..469d5517b40 100644
--- a/test/CodeGen/X86/h-registers-1.ll
+++ b/test/CodeGen/X86/h-registers-1.ll
@@ -1,4 +1,5 @@
 ; RUN: llc -mattr=-bmi < %s -mtriple=x86_64-linux | FileCheck %s
+; RUN: llc -mattr=-bmi < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s
 
 ; LLVM creates virtual registers for values live across blocks
 ; based on the type of the value. Make sure that the extracts
diff --git a/test/CodeGen/X86/h-registers-3.ll b/test/CodeGen/X86/h-registers-3.ll
index 29d0c280c4f..58b02b7df21 100644
--- a/test/CodeGen/X86/h-registers-3.ll
+++ b/test/CodeGen/X86/h-registers-3.ll
@@ -1,5 +1,6 @@
 ; RUN: llc < %s -march=x86    | grep mov | count 1
 ; RUN: llc < %s -march=x86-64 | grep mov | count 1
+; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | grep mov | count 1
 
 define zeroext i8 @foo() nounwind ssp {
 entry:
-- 
2.34.1