Index: lib/Target/X86/X86InstrInfo.td =================================================================== --- lib/Target/X86/X86InstrInfo.td +++ lib/Target/X86/X86InstrInfo.td @@ -341,18 +341,21 @@ def vz32mem : X86VMemOperand; def vz64mem : X86VMemOperand; -// 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 { +// 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 { 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 Index: lib/Target/X86/X86RegisterInfo.cpp =================================================================== --- lib/Target/X86/X86RegisterInfo.cpp +++ lib/Target/X86/X86RegisterInfo.cpp @@ -168,7 +168,15 @@ 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; Index: test/CodeGen/X86/h-register-store.ll =================================================================== --- test/CodeGen/X86/h-register-store.ll +++ 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. Index: test/CodeGen/X86/h-registers-0.ll =================================================================== --- test/CodeGen/X86/h-registers-0.ll +++ 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 Index: test/CodeGen/X86/h-registers-1.ll =================================================================== --- test/CodeGen/X86/h-registers-1.ll +++ 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 Index: test/CodeGen/X86/h-registers-3.ll =================================================================== --- test/CodeGen/X86/h-registers-3.ll +++ 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: