X86: Switch to RegClassByHwMode (#158274)
Replace the target uses of PointerLikeRegClass with RegClassByHwMode
This commit is contained in:
parent
562146499c
commit
2654b511fe
8 changed files with 58 additions and 44 deletions
|
|
@ -55,6 +55,9 @@ std::string X86_MC::ParseX86Triple(const Triple &TT) {
|
|||
else
|
||||
FS = "-64bit-mode,-32bit-mode,+16bit-mode";
|
||||
|
||||
if (TT.isX32())
|
||||
FS += ",+x32";
|
||||
|
||||
return FS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ def Is32Bit : SubtargetFeature<"32bit-mode", "Is32Bit", "true",
|
|||
"32-bit mode (80386)">;
|
||||
def Is16Bit : SubtargetFeature<"16bit-mode", "Is16Bit", "true",
|
||||
"16-bit mode (i8086)">;
|
||||
def IsX32 : SubtargetFeature<"x32", "IsX32", "true",
|
||||
"64-bit with ILP32 programming model (e.g. x32 ABI)">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Subtarget ISA features
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@
|
|||
include "X86InstrFragments.td"
|
||||
include "X86InstrFragmentsSIMD.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Operand Definitions.
|
||||
//
|
||||
include "X86InstrOperands.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Predicate Definitions.
|
||||
//
|
||||
include "X86InstrPredicates.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Operand Definitions.
|
||||
//
|
||||
include "X86InstrOperands.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Instruction Format Definitions.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -6,9 +6,15 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def x86_ptr_rc : RegClassByHwMode<
|
||||
[X86_32, X86_64, X86_64_X32],
|
||||
[GR32, GR64, LOW32_ADDR_ACCESS]>;
|
||||
|
||||
// A version of ptr_rc which excludes SP, ESP, and RSP. This is used for
|
||||
// the index operand of an address, to conform to x86 encoding restrictions.
|
||||
def ptr_rc_nosp : PointerLikeRegClass<1>;
|
||||
def ptr_rc_nosp : RegClassByHwMode<
|
||||
[X86_32, X86_64, X86_64_X32],
|
||||
[GR32_NOSP, GR64_NOSP, GR32_NOSP]>;
|
||||
|
||||
// *mem - Operand definitions for the funky X86 addressing mode operands.
|
||||
//
|
||||
|
|
@ -53,7 +59,7 @@ class X86MemOperand<string printMethod,
|
|||
AsmOperandClass parserMatchClass = X86MemAsmOperand,
|
||||
int size = 0> : Operand<iPTR> {
|
||||
let PrintMethod = printMethod;
|
||||
let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG);
|
||||
let MIOperandInfo = (ops x86_ptr_rc, i8imm, ptr_rc_nosp, i32imm, SEGMENT_REG);
|
||||
let ParserMatchClass = parserMatchClass;
|
||||
let OperandType = "OPERAND_MEMORY";
|
||||
int Size = size;
|
||||
|
|
@ -63,7 +69,7 @@ class X86MemOperand<string printMethod,
|
|||
class X86VMemOperand<RegisterClass RC, string printMethod,
|
||||
AsmOperandClass parserMatchClass, int size = 0>
|
||||
: X86MemOperand<printMethod, parserMatchClass, size> {
|
||||
let MIOperandInfo = (ops ptr_rc, i8imm, RC, i32imm, SEGMENT_REG);
|
||||
let MIOperandInfo = (ops x86_ptr_rc, i8imm, RC, i32imm, SEGMENT_REG);
|
||||
}
|
||||
|
||||
def anymem : X86MemOperand<"printMemReference">;
|
||||
|
|
@ -113,8 +119,14 @@ def sdmem : X86MemOperand<"printqwordmem", X86Mem64AsmOperand>;
|
|||
|
||||
// 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 ptr_rc_norex : RegClassByHwMode<
|
||||
[X86_32, X86_64, X86_64_X32],
|
||||
[GR32_NOREX, GR64_NOREX, GR32_NOREX]>;
|
||||
|
||||
def ptr_rc_norex_nosp : RegClassByHwMode<
|
||||
[X86_32, X86_64, X86_64_X32],
|
||||
[GR32_NOREX_NOSP, GR64_NOREX_NOSP, GR32_NOREX_NOSP]>;
|
||||
|
||||
|
||||
def i8mem_NOREX : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8> {
|
||||
let MIOperandInfo = (ops ptr_rc_norex, i8imm, ptr_rc_norex_nosp, i32imm,
|
||||
|
|
@ -123,7 +135,9 @@ def i8mem_NOREX : X86MemOperand<"printbytemem", X86Mem8AsmOperand, 8> {
|
|||
|
||||
// GPRs available for tailcall.
|
||||
// It represents GR32_TC, GR64_TC or GR64_TCW64.
|
||||
def ptr_rc_tailcall : PointerLikeRegClass<4>;
|
||||
def ptr_rc_tailcall : RegClassByHwMode<
|
||||
[X86_32, X86_64, X86_64_X32],
|
||||
[GR32_TC, GR64_TC, GR64_TC]>;
|
||||
|
||||
// Special i32mem for addresses of load folding tail calls. These are not
|
||||
// allowed to use callee-saved registers since they must be scheduled
|
||||
|
|
@ -270,12 +284,12 @@ let RenderMethod = "addMemOffsOperands" in {
|
|||
|
||||
class X86SrcIdxOperand<string printMethod, AsmOperandClass parserMatchClass>
|
||||
: X86MemOperand<printMethod, parserMatchClass> {
|
||||
let MIOperandInfo = (ops ptr_rc, SEGMENT_REG);
|
||||
let MIOperandInfo = (ops x86_ptr_rc, SEGMENT_REG);
|
||||
}
|
||||
|
||||
class X86DstIdxOperand<string printMethod, AsmOperandClass parserMatchClass>
|
||||
: X86MemOperand<printMethod, parserMatchClass> {
|
||||
let MIOperandInfo = (ops ptr_rc);
|
||||
let MIOperandInfo = (ops x86_ptr_rc);
|
||||
}
|
||||
|
||||
def srcidx8 : X86SrcIdxOperand<"printSrcIdx8", X86SrcIdx8Operand>;
|
||||
|
|
|
|||
|
|
@ -195,6 +195,12 @@ def Not64BitMode : Predicate<"!Subtarget->is64Bit()">,
|
|||
AssemblerPredicate<(all_of (not Is64Bit)), "Not 64-bit mode">;
|
||||
def In64BitMode : Predicate<"Subtarget->is64Bit()">,
|
||||
AssemblerPredicate<(all_of Is64Bit), "64-bit mode">;
|
||||
|
||||
def IsX32Mode : Predicate<"Subtarget->getTargetTriple().isX32()">,
|
||||
AssemblerPredicate<(all_of IsX32), "x32 ABI">;
|
||||
def NotX32Mode : Predicate<"!Subtarget->getTargetTriple().isX32()">,
|
||||
AssemblerPredicate<(all_of (not IsX32)), "not x32 ABI">;
|
||||
|
||||
def IsLP64 : Predicate<"Subtarget->isTarget64BitLP64()">;
|
||||
def NotLP64 : Predicate<"!Subtarget->isTarget64BitLP64()">;
|
||||
def In16BitMode : Predicate<"Subtarget->is16Bit()">,
|
||||
|
|
@ -250,3 +256,11 @@ def HasMFence : Predicate<"Subtarget->hasMFence()">;
|
|||
def HasFastDPWSSD: Predicate<"Subtarget->hasFastDPWSSD()">;
|
||||
def UseIndirectThunkCalls : Predicate<"Subtarget->useIndirectThunkCalls()">;
|
||||
def NotUseIndirectThunkCalls : Predicate<"!Subtarget->useIndirectThunkCalls()">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// HwModes
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
defvar X86_32 = DefaultMode;
|
||||
def X86_64 : HwMode<[In64BitMode, NotX32Mode]>;
|
||||
def X86_64_X32 : HwMode<[IsX32Mode]>;
|
||||
|
|
|
|||
|
|
@ -194,33 +194,14 @@ X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
|
|||
|
||||
const TargetRegisterClass *
|
||||
X86RegisterInfo::getPointerRegClass(unsigned Kind) const {
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("Unexpected Kind in getPointerRegClass!");
|
||||
case 0: // Normal GPRs.
|
||||
if (IsTarget64BitLP64)
|
||||
return &X86::GR64RegClass;
|
||||
// If the target is 64bit but we have been told to use 32bit addresses,
|
||||
// we can still use 64-bit register as long as we know the high bits
|
||||
// are zeros.
|
||||
// Reflect that in the returned register class.
|
||||
return Is64Bit ? &X86::LOW32_ADDR_ACCESSRegClass : &X86::GR32RegClass;
|
||||
case 1: // Normal GPRs except the stack pointer (for encoding reasons).
|
||||
if (IsTarget64BitLP64)
|
||||
return &X86::GR64_NOSPRegClass;
|
||||
// NOSP does not contain RIP, so no special case here.
|
||||
return &X86::GR32_NOSPRegClass;
|
||||
case 2: // NOREX GPRs.
|
||||
if (IsTarget64BitLP64)
|
||||
return &X86::GR64_NOREXRegClass;
|
||||
return &X86::GR32_NOREXRegClass;
|
||||
case 3: // NOREX GPRs except the stack pointer (for encoding reasons).
|
||||
if (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 Is64Bit ? &X86::GR64_TCRegClass : &X86::GR32_TCRegClass;
|
||||
}
|
||||
assert(Kind == 0 && "this should only be used for default cases");
|
||||
if (IsTarget64BitLP64)
|
||||
return &X86::GR64RegClass;
|
||||
// If the target is 64bit but we have been told to use 32bit addresses,
|
||||
// we can still use 64-bit register as long as we know the high bits
|
||||
// are zeros.
|
||||
// Reflect that in the returned register class.
|
||||
return Is64Bit ? &X86::LOW32_ADDR_ACCESSRegClass : &X86::GR32RegClass;
|
||||
}
|
||||
|
||||
const TargetRegisterClass *
|
||||
|
|
|
|||
|
|
@ -170,10 +170,10 @@ public:
|
|||
#include "X86GenSubtargetInfo.inc"
|
||||
|
||||
/// Is this x86_64 with the ILP32 programming model (x32 ABI)?
|
||||
bool isTarget64BitILP32() const { return Is64Bit && (TargetTriple.isX32()); }
|
||||
bool isTarget64BitILP32() const { return Is64Bit && IsX32; }
|
||||
|
||||
/// Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
|
||||
bool isTarget64BitLP64() const { return Is64Bit && (!TargetTriple.isX32()); }
|
||||
bool isTarget64BitLP64() const { return Is64Bit && !IsX32; }
|
||||
|
||||
PICStyles::Style getPICStyle() const { return PICStyle; }
|
||||
void setPICStyle(PICStyles::Style Style) { PICStyle = Style; }
|
||||
|
|
|
|||
|
|
@ -553,10 +553,10 @@ void X86FoldTablesEmitter::updateTables(const CodeGenInstruction *RegInst,
|
|||
for (unsigned I = RegOutSize, E = RegInst->Operands.size(); I < E; I++) {
|
||||
const Record *RegOpRec = RegInst->Operands[I].Rec;
|
||||
const Record *MemOpRec = MemInst->Operands[I].Rec;
|
||||
// PointerLikeRegClass: For instructions like TAILJMPr, TAILJMPr64,
|
||||
// RegClassByHwMode: For instructions like TAILJMPr, TAILJMPr64,
|
||||
// TAILJMPr64_REX
|
||||
if ((isRegisterOperand(RegOpRec) ||
|
||||
RegOpRec->isSubClassOf("PointerLikeRegClass")) &&
|
||||
(RegOpRec->isSubClassOf("RegClassByHwMode"))) &&
|
||||
isMemoryOperand(MemOpRec)) {
|
||||
switch (I) {
|
||||
case 0:
|
||||
|
|
|
|||
Loading…
Reference in a new issue