From 2abe8019d159da81bf831681ffc39c207dedbd6f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 22 Aug 2016 01:37:19 +0000 Subject: [PATCH] [X86] Merge hasVEX_i8ImmReg into the ImmFormat type which had extra unused encodings. This saves one bit in TSFlags. NFC llvm-svn: 279412 --- lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 26 ++++----- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 28 ++++----- lib/Target/X86/X86InstrFormats.td | 57 +++++++++++-------- lib/Target/X86/X86InstrSSE.td | 8 +-- lib/Target/X86/X86InstrXOP.td | 56 +++++++++--------- 5 files changed, 91 insertions(+), 84 deletions(-) diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 5b34969111f..3f9f3bd16f0 100644 --- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -403,12 +403,13 @@ namespace X86II { ImmMask = 15 << ImmShift, Imm8 = 1 << ImmShift, Imm8PCRel = 2 << ImmShift, - Imm16 = 3 << ImmShift, - Imm16PCRel = 4 << ImmShift, - Imm32 = 5 << ImmShift, - Imm32PCRel = 6 << ImmShift, - Imm32S = 7 << ImmShift, - Imm64 = 8 << ImmShift, + Imm8Reg = 3 << ImmShift, + Imm16 = 4 << ImmShift, + Imm16PCRel = 5 << ImmShift, + Imm32 = 6 << ImmShift, + Imm32PCRel = 7 << ImmShift, + Imm32S = 8 << ImmShift, + Imm64 = 9 << ImmShift, //===------------------------------------------------------------------===// // FP Instruction Classification... Zero is non-fp instruction. @@ -493,17 +494,11 @@ namespace X86II { VEX_4VOp3Shift = VEX_4VShift + 1, VEX_4VOp3 = 1ULL << VEX_4VOp3Shift, - /// VEX_I8IMM - Specifies that the last register used in a AVX instruction, - /// must be encoded in the i8 immediate field. This usually happens in - /// instructions with 4 operands. - VEX_I8IMMShift = VEX_4VOp3Shift + 1, - VEX_I8IMM = 1ULL << VEX_I8IMMShift, - /// VEX_L - Stands for a bit in the VEX opcode prefix meaning the current /// instruction uses 256-bit wide registers. This is usually auto detected /// if a VR256 register is used, but some AVX instructions also have this /// field marked when using a f256 memory references. - VEX_LShift = VEX_I8IMMShift + 1, + VEX_LShift = VEX_4VOp3Shift + 1, VEX_L = 1ULL << VEX_LShift, // EVEX_K - Set if this instruction requires masking @@ -562,7 +557,8 @@ namespace X86II { switch (TSFlags & X86II::ImmMask) { default: llvm_unreachable("Unknown immediate size"); case X86II::Imm8: - case X86II::Imm8PCRel: return 1; + case X86II::Imm8PCRel: + case X86II::Imm8Reg: return 1; case X86II::Imm16: case X86II::Imm16PCRel: return 2; case X86II::Imm32: @@ -582,6 +578,7 @@ namespace X86II { case X86II::Imm32PCRel: return true; case X86II::Imm8: + case X86II::Imm8Reg: case X86II::Imm16: case X86II::Imm32: case X86II::Imm32S: @@ -599,6 +596,7 @@ namespace X86II { return true; case X86II::Imm8: case X86II::Imm8PCRel: + case X86II::Imm8Reg: case X86II::Imm16: case X86II::Imm16PCRel: case X86II::Imm32: diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 96c2e81c332..4128c4fb9c5 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -745,11 +745,11 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, // src1(ModR/M), MemAddr // src1(ModR/M), src2(VEX_4V), MemAddr // src1(ModR/M), MemAddr, imm8 - // src1(ModR/M), MemAddr, src2(VEX_I8IMM) + // src1(ModR/M), MemAddr, src2(Imm[7:4]) // // FMA4: - // dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM) - // dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM), src3(ModR/M), + // dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4]) + // dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M), unsigned RegEnc = getX86RegEncoding(MI, CurOp++); VEX_R = ~(RegEnc >> 3) & 1; EVEX_R2 = ~(RegEnc >> 4) & 1; @@ -803,13 +803,13 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, } case X86II::MRMSrcReg: { // MRMSrcReg instructions forms: - // dst(ModR/M), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM) + // dst(ModR/M), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4]) // dst(ModR/M), src1(ModR/M) // dst(ModR/M), src1(ModR/M), imm8 // // FMA4: - // dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM) - // dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM), src3(ModR/M), + // dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4]) + // dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M), unsigned RegEnc = getX86RegEncoding(MI, CurOp++); VEX_R = ~(RegEnc >> 3) & 1; EVEX_R2 = ~(RegEnc >> 4) & 1; @@ -823,7 +823,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, EVEX_V2 = ~(VRegEnc >> 4) & 1; } - if (HasMemOp4) // Skip second register source (encoded in I8IMM) + if (HasMemOp4) // Skip second register source (encoded in Imm[7:4]) CurOp++; RegEnc = getX86RegEncoding(MI, CurOp++); @@ -1135,8 +1135,8 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, bool HasVEX_4V = TSFlags & X86II::VEX_4V; bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3; bool HasMemOp4 = TSFlags & X86II::MemOp4; - bool HasVEX_I8IMM = TSFlags & X86II::VEX_I8IMM; - assert((!HasMemOp4 || HasVEX_I8IMM) && "MemOp4 should imply VEX_I8IMM"); + bool HasVEX_I8Reg = (TSFlags & X86II::ImmMask) == X86II::Imm8Reg; + assert((!HasMemOp4 || HasVEX_I8Reg) && "MemOp4 should imply VEX_I8Reg"); // It uses the EVEX.aaa field? bool HasEVEX_K = TSFlags & X86II::EVEX_K; @@ -1312,7 +1312,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV) ++SrcRegNum; - if (HasMemOp4) // Capture 2nd src (which is encoded in I8IMM) + if (HasMemOp4) // Capture 2nd src (which is encoded in Imm[7:4]) I8RegNum = getX86RegEncoding(MI, SrcRegNum++); EmitRegModRMByte(MI.getOperand(SrcRegNum), @@ -1320,7 +1320,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, CurOp = SrcRegNum + 1; if (HasVEX_4VOp3) ++CurOp; - if (!HasMemOp4 && HasVEX_I8IMM) + if (!HasMemOp4 && HasVEX_I8Reg) I8RegNum = getX86RegEncoding(MI, CurOp++); // do not count the rounding control operand if (HasEVEX_RC) @@ -1336,7 +1336,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, if (HasVEX_4V) ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). - if (HasMemOp4) // Capture second register source (encoded in I8IMM) + if (HasMemOp4) // Capture second register source (encoded in Imm[7:4]) I8RegNum = getX86RegEncoding(MI, FirstMemOp++); EmitByte(BaseOpcode, CurByte, OS); @@ -1346,7 +1346,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, CurOp = FirstMemOp + X86::AddrNumOperands; if (HasVEX_4VOp3) ++CurOp; - if (!HasMemOp4 && HasVEX_I8IMM) + if (!HasMemOp4 && HasVEX_I8Reg) I8RegNum = getX86RegEncoding(MI, CurOp++); break; } @@ -1410,7 +1410,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, break; } - if (HasVEX_I8IMM) { + if (HasVEX_I8Reg) { // The last source register of a 4 operand instruction in AVX is encoded // in bits[7:4] of a immediate byte. assert(I8RegNum < 16 && "Register encoding out of range"); diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index f75700c651b..688d050d20d 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -65,12 +65,13 @@ class ImmType val> { def NoImm : ImmType<0>; def Imm8 : ImmType<1>; def Imm8PCRel : ImmType<2>; -def Imm16 : ImmType<3>; -def Imm16PCRel : ImmType<4>; -def Imm32 : ImmType<5>; -def Imm32PCRel : ImmType<6>; -def Imm32S : ImmType<7>; -def Imm64 : ImmType<8>; +def Imm8Reg : ImmType<3>; // Register encoded in [7:4]. +def Imm16 : ImmType<4>; +def Imm16PCRel : ImmType<5>; +def Imm32 : ImmType<6>; +def Imm32PCRel : ImmType<7>; +def Imm32S : ImmType<8>; +def Imm64 : ImmType<9>; // FPFormat - This specifies what form this FP instruction has. This is used by // the Floating-Point stackifier pass. @@ -191,7 +192,6 @@ class VEX { Encoding OpEnc = EncVEX; } class VEX_W { bit hasVEX_WPrefix = 1; } class VEX_4V : VEX { bit hasVEX_4V = 1; } class VEX_4VOp3 : VEX { bit hasVEX_4VOp3 = 1; } -class VEX_I8IMM { bit hasVEX_i8ImmReg = 1; } class VEX_L { bit hasVEX_L = 1; } class VEX_LIG { bit ignoresVEX_L = 1; } class EVEX : VEX { Encoding OpEnc = EncEVEX; } @@ -267,8 +267,6 @@ class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, bit hasVEX_4V = 0; // Does this inst require the VEX.VVVV field? bit hasVEX_4VOp3 = 0; // Does this inst require the VEX.VVVV field to // encode the third operand? - bit hasVEX_i8ImmReg = 0; // Does this inst require the last source register - // to be encoded in a immediate field? bit hasVEX_L = 0; // Does this inst use large (256-bit) registers? bit ignoresVEX_L = 0; // Does this instruction ignore the L-bit bit hasEVEX_K = 0; // Does this inst require masking? @@ -318,17 +316,16 @@ class X86Inst opcod, Format f, ImmType i, dag outs, dag ins, let TSFlags{39} = hasVEX_WPrefix; let TSFlags{40} = hasVEX_4V; let TSFlags{41} = hasVEX_4VOp3; - let TSFlags{42} = hasVEX_i8ImmReg; - let TSFlags{43} = hasVEX_L; - let TSFlags{44} = hasEVEX_K; - let TSFlags{45} = hasEVEX_Z; - let TSFlags{46} = hasEVEX_L2; - let TSFlags{47} = hasEVEX_B; + let TSFlags{42} = hasVEX_L; + let TSFlags{43} = hasEVEX_K; + let TSFlags{44} = hasEVEX_Z; + let TSFlags{45} = hasEVEX_L2; + let TSFlags{46} = hasEVEX_B; // If we run out of TSFlags bits, it's possible to encode this in 3 bits. - let TSFlags{54-48} = CD8_Scale; - let TSFlags{55} = has3DNow0F0FOpcode; - let TSFlags{56} = hasMemOp4Prefix; - let TSFlags{57} = hasEVEX_RC; + let TSFlags{53-47} = CD8_Scale; + let TSFlags{54} = has3DNow0F0FOpcode; + let TSFlags{55} = hasMemOp4Prefix; + let TSFlags{56} = hasEVEX_RC; } class PseudoI pattern> @@ -350,6 +347,13 @@ class Ii8 o, Format f, dag outs, dag ins, string asm, let Pattern = pattern; let CodeSize = 3; } +class Ii8Reg o, Format f, dag outs, dag ins, string asm, + list pattern, InstrItinClass itin = NoItinerary, + Domain d = GenericDomain> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} class Ii8PCRel o, Format f, dag outs, dag ins, string asm, list pattern, InstrItinClass itin = NoItinerary> : X86Inst { @@ -848,8 +852,8 @@ class FMA3 o, Format F, dag outs, dag ins, string asm, // FMA4 Instruction Templates class FMA4 o, Format F, dag outs, dag ins, string asm, listpattern, InstrItinClass itin = NoItinerary> - : Ii8, TAPD, - VEX_4V, VEX_I8IMM, FMASC, Requires<[HasFMA4]>; + : Ii8Reg, TAPD, + VEX_4V, FMASC, Requires<[HasFMA4]>; // XOP 2, 3 and 4 Operand Instruction Template class IXOP o, Format F, dag outs, dag ins, string asm, @@ -857,17 +861,22 @@ class IXOP o, Format F, dag outs, dag ins, string asm, : I, XOP9, Requires<[HasXOP]>; -// XOP 2, 3 and 4 Operand Instruction Templates with imm byte +// XOP 2 and 3 Operand Instruction Templates with imm byte class IXOPi8 o, Format F, dag outs, dag ins, string asm, list pattern, InstrItinClass itin = NoItinerary> : Ii8, XOP8, Requires<[HasXOP]>; +// XOP 4 Operand Instruction Templates with imm byte +class IXOPi8Reg o, Format F, dag outs, dag ins, string asm, + list pattern, InstrItinClass itin = NoItinerary> + : Ii8Reg, + XOP8, Requires<[HasXOP]>; // XOP 5 operand instruction (VEX encoding!) class IXOP5 o, Format F, dag outs, dag ins, string asm, listpattern, InstrItinClass itin = NoItinerary> - : Ii8, TAPD, - VEX_4V, VEX_I8IMM, Requires<[HasXOP]>; + : Ii8Reg, TAPD, + VEX_4V, Requires<[HasXOP]>; // X86-64 Instruction templates... // diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 4269d930ca2..aad91322aff 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -7060,22 +7060,22 @@ multiclass SS41I_quaternary_int_avx opc, string OpcodeStr, RegisterClass RC, X86MemOperand x86memop, PatFrag mem_frag, Intrinsic IntId, X86FoldableSchedWrite Sched> { - def rr : Ii8, TAPD, VEX_4V, VEX_I8IMM, + NoItinerary, SSEPackedInt>, TAPD, VEX_4V, Sched<[Sched]>; - def rm : Ii8, TAPD, VEX_4V, VEX_I8IMM, + NoItinerary, SSEPackedInt>, TAPD, VEX_4V, Sched<[Sched.Folded, ReadAfterLd]>; } diff --git a/lib/Target/X86/X86InstrXOP.td b/lib/Target/X86/X86InstrXOP.td index f49917b80f3..1834780f066 100644 --- a/lib/Target/X86/X86InstrXOP.td +++ b/lib/Target/X86/X86InstrXOP.td @@ -146,19 +146,19 @@ let ExeDomain = SSEPackedInt in { // Instruction where second source can be memory, but third must be register multiclass xop4opm2 opc, string OpcodeStr, Intrinsic Int> { let isCommutable = 1 in - def rr : IXOPi8, XOP_4V, VEX_I8IMM; - def rm : IXOPi8, XOP_4V; + def rm : IXOPi8Reg, XOP_4V, VEX_I8IMM; + VR128:$src3))]>, XOP_4V; } let ExeDomain = SSEPackedInt in { @@ -224,37 +224,37 @@ let ExeDomain = SSEPackedInt in { // SSE integer instructions multiclass xop4op opc, string OpcodeStr, SDNode OpNode, ValueType vt128> { - def rrr : IXOPi8, - XOP_4V, VEX_I8IMM; - def rrm : IXOPi8, - XOP_4V, VEX_I8IMM, VEX_W, MemOp4; - def rmr : IXOPi8, - XOP_4V, VEX_I8IMM; + XOP_4V; // For disassembler let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rrr_REV : IXOPi8, XOP_4V, VEX_I8IMM, VEX_W, MemOp4; + []>, XOP_4V, VEX_W, MemOp4; } let ExeDomain = SSEPackedInt in { @@ -265,66 +265,66 @@ let ExeDomain = SSEPackedInt in { multiclass xop4op_int opc, string OpcodeStr, Intrinsic Int128, Intrinsic Int256> { // 128-bit Instruction - def rrr : IXOPi8, - XOP_4V, VEX_I8IMM; - def rrm : IXOPi8, - XOP_4V, VEX_I8IMM, VEX_W, MemOp4; - def rmr : IXOPi8, - XOP_4V, VEX_I8IMM; + XOP_4V; // For disassembler let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rrr_REV : IXOPi8, XOP_4V, VEX_I8IMM, VEX_W, MemOp4; + []>, XOP_4V, VEX_W, MemOp4; // 256-bit Instruction - def rrrY : IXOPi8, - XOP_4V, VEX_I8IMM, VEX_L; - def rrmY : IXOPi8, - XOP_4V, VEX_I8IMM, VEX_W, MemOp4, VEX_L; - def rmrY : IXOPi8, - XOP_4V, VEX_I8IMM, VEX_L; + XOP_4V, VEX_L; // For disassembler let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in - def rrrY_REV : IXOPi8, XOP_4V, VEX_I8IMM, VEX_W, MemOp4, VEX_L; + []>, XOP_4V, VEX_W, MemOp4, VEX_L; } let ExeDomain = SSEPackedInt in {