diff options
Diffstat (limited to 'lib/Target/X86/X86RegisterInfo.td')
-rw-r--r-- | lib/Target/X86/X86RegisterInfo.td | 154 |
1 files changed, 134 insertions, 20 deletions
diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index a7b0f88..b323e78 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -49,7 +49,8 @@ let Namespace = "X86" in { def R14B : Register<"r14b">, DwarfRegNum<[14, -2, -2]>; def R15B : Register<"r15b">, DwarfRegNum<[15, -2, -2]>; - // High registers X86-32 only + // High registers. On x86-64, these cannot be used in any instruction + // with a REX prefix. def AH : Register<"ah">, DwarfRegNum<[0, 0, 0]>; def DH : Register<"dh">, DwarfRegNum<[1, 2, 2]>; def CH : Register<"ch">, DwarfRegNum<[2, 1, 1]>; @@ -185,41 +186,45 @@ let Namespace = "X86" in { // def x86_subreg_8bit : PatLeaf<(i32 1)>; -def x86_subreg_16bit : PatLeaf<(i32 2)>; -def x86_subreg_32bit : PatLeaf<(i32 3)>; +def x86_subreg_8bit_hi : PatLeaf<(i32 2)>; +def x86_subreg_16bit : PatLeaf<(i32 3)>; +def x86_subreg_32bit : PatLeaf<(i32 4)>; def : SubRegSet<1, [AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W], [AL, CL, DL, BL, SPL, BPL, SIL, DIL, R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B]>; -// It's unclear if this subreg set is safe, given that not all registers -// in the class have an 'H' subreg. -// def : SubRegSet<2, [AX, CX, DX, BX], -// [AH, CH, DH, BH]>; +def : SubRegSet<2, [AX, CX, DX, BX], + [AH, CH, DH, BH]>; def : SubRegSet<1, [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D], [AL, CL, DL, BL, SPL, BPL, SIL, DIL, R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B]>; -def : SubRegSet<2, [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, +def : SubRegSet<2, [EAX, ECX, EDX, EBX], + [AH, CH, DH, BH]>; + +def : SubRegSet<3, [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D], [AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W]>; - def : SubRegSet<1, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15], [AL, CL, DL, BL, SPL, BPL, SIL, DIL, R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B]>; -def : SubRegSet<2, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, +def : SubRegSet<2, [RAX, RCX, RDX, RBX], + [AH, CH, DH, BH]>; + +def : SubRegSet<3, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15], [AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W]>; - -def : SubRegSet<3, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, + +def : SubRegSet<4, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15], [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D]>; @@ -236,7 +241,11 @@ def : SubRegSet<3, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, // R8B, ... R15B. // Allocate R12 and R13 last, as these require an extra byte when // encoded in x86_64 instructions. -// FIXME: Allow AH, CH, DH, BH in 64-mode for non-REX instructions, +// FIXME: Allow AH, CH, DH, BH to be used as general-purpose registers in +// 64-bit mode. The main complication is that they cannot be encoded in an +// instruction requiring a REX prefix, while SIL, DIL, BPL, R8D, etc. +// require a REX prefix. For example, "addb %ah, %dil" and "movzbl %ah, %r8d" +// cannot be encoded. def GR8 : RegisterClass<"X86", [i8], 8, [AL, CL, DL, BL, AH, CH, DH, BH, SIL, DIL, BPL, SPL, R8B, R9B, R10B, R11B, R14B, R15B, R12B, R13B]> { @@ -295,7 +304,7 @@ def GR8 : RegisterClass<"X86", [i8], 8, def GR16 : RegisterClass<"X86", [i16], 16, [AX, CX, DX, SI, DI, BX, BP, SP, R8W, R9W, R10W, R11W, R14W, R15W, R12W, R13W]> { - let SubRegClassList = [GR8]; + let SubRegClassList = [GR8, GR8]; let MethodProtos = [{ iterator allocation_order_begin(const MachineFunction &MF) const; iterator allocation_order_end(const MachineFunction &MF) const; @@ -363,7 +372,7 @@ def GR16 : RegisterClass<"X86", [i16], 16, def GR32 : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP, R8D, R9D, R10D, R11D, R14D, R15D, R12D, R13D]> { - let SubRegClassList = [GR8, GR16]; + let SubRegClassList = [GR8, GR8, GR16]; let MethodProtos = [{ iterator allocation_order_begin(const MachineFunction &MF) const; iterator allocation_order_end(const MachineFunction &MF) const; @@ -431,7 +440,7 @@ def GR32 : RegisterClass<"X86", [i32], 32, def GR64 : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, RBX, R14, R15, R12, R13, RBP, RSP]> { - let SubRegClassList = [GR8, GR16, GR32]; + let SubRegClassList = [GR8, GR8, GR16, GR32]; let MethodProtos = [{ iterator allocation_order_end(const MachineFunction &MF) const; }]; @@ -452,13 +461,118 @@ def GR64 : RegisterClass<"X86", [i64], 64, } -// GR16, GR32 subclasses which contain registers that have GR8 sub-registers. -// These should only be used for 32-bit mode. +// GR8_, GR16_, GR32_, GR64_ - Subclasses of GR8, GR16, GR32, and GR64 +// which contain just the "a" "b", "c", and "d" registers. On x86-32, +// GR16_ and GR32_ are classes for registers that support 8-bit subreg +// operations. On x86-64, GR16_, GR32_, and GR64_ are classes for registers +// that support 8-bit h-register operations. +def GR8_ : RegisterClass<"X86", [i8], 8, [AL, CL, DL, BL]> { +} def GR16_ : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]> { - let SubRegClassList = [GR8]; + let SubRegClassList = [GR8_, GR8_]; } def GR32_ : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX, EBX]> { - let SubRegClassList = [GR8, GR16]; + let SubRegClassList = [GR8_, GR8_, GR16_]; +} +def GR64_ : RegisterClass<"X86", [i64], 64, [RAX, RCX, RDX, RBX]> { + let SubRegClassList = [GR8_, GR8_, GR16_, GR32_]; +} + +// GR8_NOREX, GR16_NOREX, GR32_NOREX, GR64_NOREX - Subclasses of +// GR8, GR16, GR32, and GR64 which contain only the first 8 GPRs. +// On x86-64, GR64_NOREX, GR32_NOREX and GR16_NOREX are the classes +// of registers which do not by themselves require a REX prefix. +def GR8_NOREX : RegisterClass<"X86", [i8], 8, + [AL, CL, DL, SIL, DIL, BL, BPL, SPL]> { +} +def GR16_NOREX : RegisterClass<"X86", [i16], 16, + [AX, CX, DX, SI, DI, BX, BP, SP]> { + let SubRegClassList = [GR8_NOREX, GR8_NOREX]; +} +// GR32_NOREX - GR32 registers which do not require a REX prefix. +def GR32_NOREX : RegisterClass<"X86", [i32], 32, + [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP]> { + let SubRegClassList = [GR8_NOREX, GR8_NOREX, GR16_NOREX]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + // Does the function dedicate RBP / EBP to being a frame ptr? + // If so, don't allocate ESP or EBP. + static const unsigned X86_GR32_NOREX_AO_fp[] = { + X86::EAX, X86::ECX, X86::EDX, X86::ESI, X86::EDI, X86::EBX + }; + // If not, just don't allocate ESP. + static const unsigned X86_GR32_NOREX_AO[] = { + X86::EAX, X86::ECX, X86::EDX, X86::ESI, X86::EDI, X86::EBX, X86::EBP + }; + + GR32_NOREXClass::iterator + GR32_NOREXClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + if (RI->hasFP(MF)) + return X86_GR32_NOREX_AO_fp; + else + return X86_GR32_NOREX_AO; + } + + GR32_NOREXClass::iterator + GR32_NOREXClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + if (RI->hasFP(MF)) + return X86_GR32_NOREX_AO_fp + + (sizeof(X86_GR32_NOREX_AO_fp) / sizeof(unsigned)); + else + return X86_GR32_NOREX_AO + + (sizeof(X86_GR32_NOREX_AO) / sizeof(unsigned)); + } + }]; +} + +// GR64_NOREX - GR64 registers which do not require a REX prefix. +def GR64_NOREX : RegisterClass<"X86", [i64], 64, + [RAX, RCX, RDX, RSI, RDI, RBX, RBP, RSP]> { + let SubRegClassList = [GR8_NOREX, GR8_NOREX, GR16_NOREX, GR32_NOREX]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + // Does the function dedicate RBP / EBP to being a frame ptr? + // If so, don't allocate RSP or RBP. + static const unsigned X86_GR64_NOREX_AO_fp[] = { + X86::RAX, X86::RCX, X86::RDX, X86::RSI, X86::RDI, X86::RBX + }; + // If not, just don't allocate RSP. + static const unsigned X86_GR64_NOREX_AO[] = { + X86::RAX, X86::RCX, X86::RDX, X86::RSI, X86::RDI, X86::RBX, X86::RBP + }; + + GR64_NOREXClass::iterator + GR64_NOREXClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + if (RI->hasFP(MF)) + return X86_GR64_NOREX_AO_fp; + else + return X86_GR64_NOREX_AO; + } + + GR64_NOREXClass::iterator + GR64_NOREXClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + if (RI->hasFP(MF)) + return X86_GR64_NOREX_AO_fp + + (sizeof(X86_GR64_NOREX_AO_fp) / sizeof(unsigned)); + else + return X86_GR64_NOREX_AO + + (sizeof(X86_GR64_NOREX_AO) / sizeof(unsigned)); + } + }]; } // A class to support the 'A' assembler constraint: EAX then EDX. |