Skip to content

Commit 5f8419d

Browse files
committed
[X86] Create a new instruction format to handle 4VOp3 encoding. This saves one bit in TSFlags and simplifies MRMSrcMem/MRMSrcReg format handling.
llvm-svn: 279424
1 parent 9b20fec commit 5f8419d

File tree

9 files changed

+128
-82
lines changed

9 files changed

+128
-82
lines changed

llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,15 @@ namespace X86II {
277277
///
278278
MRMSrcMem = 33,
279279

280+
/// MRMSrcMem4VOp3 - This form is used for instructions that encode
281+
/// operand 3 with VEX.VVVV and load from memory.
282+
///
283+
MRMSrcMem4VOp3 = 34,
284+
280285
/// MRMSrcMemOp4 - This form is used for instructions that use the Mod/RM
281286
/// byte to specify the fourth source, which in this case is memory.
282287
///
283-
MRMSrcMemOp4 = 34,
288+
MRMSrcMemOp4 = 35,
284289

285290
/// MRMXm - This form is used for instructions that use the Mod/RM byte
286291
/// to specify a memory source, but doesn't use the middle field.
@@ -301,10 +306,15 @@ namespace X86II {
301306
///
302307
MRMSrcReg = 49,
303308

309+
/// MRMSrcReg4VOp3 - This form is used for instructions that encode
310+
/// operand 3 with VEX.VVVV and do not load from memory.
311+
///
312+
MRMSrcReg4VOp3 = 50,
313+
304314
/// MRMSrcRegOp4 - This form is used for instructions that use the Mod/RM
305315
/// byte to specify the fourth source, which in this case is a register.
306316
///
307-
MRMSrcRegOp4 = 50,
317+
MRMSrcRegOp4 = 51,
308318

309319
/// MRMXr - This form is used for instructions that use the Mod/RM byte
310320
/// to specify a register source, but doesn't use the middle field.
@@ -505,16 +515,11 @@ namespace X86II {
505515
VEX_4VShift = VEX_WShift + 1,
506516
VEX_4V = 1ULL << VEX_4VShift,
507517

508-
/// VEX_4VOp3 - Similar to VEX_4V, but used on instructions that encode
509-
/// operand 3 with VEX.vvvv.
510-
VEX_4VOp3Shift = VEX_4VShift + 1,
511-
VEX_4VOp3 = 1ULL << VEX_4VOp3Shift,
512-
513518
/// VEX_L - Stands for a bit in the VEX opcode prefix meaning the current
514519
/// instruction uses 256-bit wide registers. This is usually auto detected
515520
/// if a VR256 register is used, but some AVX instructions also have this
516521
/// field marked when using a f256 memory references.
517-
VEX_LShift = VEX_4VOp3Shift + 1,
522+
VEX_LShift = VEX_4VShift + 1,
518523
VEX_L = 1ULL << VEX_LShift,
519524

520525
// EVEX_K - Set if this instruction requires masking
@@ -674,11 +679,15 @@ namespace X86II {
674679
// Start from 1, skip any registers encoded in VEX_VVVV or I8IMM, or a
675680
// mask register.
676681
return 1 + HasVEX_4V + HasEVEX_K;
682+
case X86II::MRMSrcMem4VOp3:
683+
// Skip registers encoded in reg.
684+
return 1 + HasEVEX_K;
677685
case X86II::MRMSrcMemOp4:
678686
// Skip registers encoded in reg, VEX_VVVV, and I8IMM.
679687
return 3;
680688
case X86II::MRMDestReg:
681689
case X86II::MRMSrcReg:
690+
case X86II::MRMSrcReg4VOp3:
682691
case X86II::MRMSrcRegOp4:
683692
case X86II::MRMXr:
684693
case X86II::MRM0r: case X86II::MRM1r:

llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
602602
uint64_t Encoding = TSFlags & X86II::EncodingMask;
603603
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
604604
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
605-
bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3;
606605
bool HasEVEX_RC = TSFlags & X86II::EVEX_RC;
607606

608607
// VEX_R: opcode externsion equivalent to REX.R in
@@ -768,13 +767,20 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
768767
if (!HasVEX_4V) // Only needed with VSIB which don't use VVVV.
769768
EVEX_V2 = ~(IndexRegEnc >> 4) & 1;
770769

771-
if (HasVEX_4VOp3)
772-
// Instruction format for 4VOp3:
773-
// src1(ModR/M), MemAddr, src3(VEX_4V)
774-
// CurOp points to start of the MemoryOperand,
775-
// it skips TIED_TO operands if exist, then increments past src1.
776-
// CurOp + X86::AddrNumOperands will point to src3.
777-
VEX_4V = ~getX86RegEncoding(MI, CurOp + X86::AddrNumOperands) & 0xf;
770+
break;
771+
}
772+
case X86II::MRMSrcMem4VOp3: {
773+
// Instruction format for 4VOp3:
774+
// src1(ModR/M), MemAddr, src3(VEX_4V)
775+
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
776+
VEX_R = ~(RegEnc >> 3) & 1;
777+
778+
unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
779+
VEX_B = ~(BaseRegEnc >> 3) & 1;
780+
unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg);
781+
VEX_X = ~(IndexRegEnc >> 3) & 1;
782+
783+
VEX_4V = ~getX86RegEncoding(MI, CurOp + X86::AddrNumOperands) & 0xf;
778784
break;
779785
}
780786
case X86II::MRMSrcMemOp4: {
@@ -837,8 +843,7 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
837843
RegEnc = getX86RegEncoding(MI, CurOp++);
838844
VEX_B = ~(RegEnc >> 3) & 1;
839845
VEX_X = ~(RegEnc >> 4) & 1;
840-
if (HasVEX_4VOp3)
841-
VEX_4V = ~getX86RegEncoding(MI, CurOp++) & 0xf;
846+
842847
if (EVEX_b) {
843848
if (HasEVEX_RC) {
844849
unsigned RcOperand = NumOps-1;
@@ -849,6 +854,18 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
849854
}
850855
break;
851856
}
857+
case X86II::MRMSrcReg4VOp3: {
858+
// Instruction format for 4VOp3:
859+
// src1(ModR/M), src2(ModR/M), src3(VEX_4V)
860+
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
861+
VEX_R = ~(RegEnc >> 3) & 1;
862+
863+
RegEnc = getX86RegEncoding(MI, CurOp++);
864+
VEX_B = ~(RegEnc >> 3) & 1;
865+
866+
VEX_4V = ~getX86RegEncoding(MI, CurOp++) & 0xf;
867+
break;
868+
}
852869
case X86II::MRMSrcRegOp4: {
853870
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
854871
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
@@ -1157,7 +1174,6 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
11571174

11581175
// It uses the VEX.VVVV field?
11591176
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
1160-
bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3;
11611177
bool HasVEX_I8Reg = (TSFlags & X86II::ImmMask) == X86II::Imm8Reg;
11621178

11631179
// It uses the EVEX.aaa field?
@@ -1337,15 +1353,23 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
13371353
EmitRegModRMByte(MI.getOperand(SrcRegNum),
13381354
GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
13391355
CurOp = SrcRegNum + 1;
1340-
if (HasVEX_4VOp3)
1341-
++CurOp;
13421356
if (HasVEX_I8Reg)
13431357
I8RegNum = getX86RegEncoding(MI, CurOp++);
13441358
// do not count the rounding control operand
13451359
if (HasEVEX_RC)
13461360
--NumOps;
13471361
break;
13481362
}
1363+
case X86II::MRMSrcReg4VOp3: {
1364+
EmitByte(BaseOpcode, CurByte, OS);
1365+
unsigned SrcRegNum = CurOp + 1;
1366+
1367+
EmitRegModRMByte(MI.getOperand(SrcRegNum),
1368+
GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
1369+
CurOp = SrcRegNum + 1;
1370+
++CurOp; // Encoded in VEX.VVVV
1371+
break;
1372+
}
13491373
case X86II::MRMSrcRegOp4: {
13501374
EmitByte(BaseOpcode, CurByte, OS);
13511375
unsigned SrcRegNum = CurOp + 1;
@@ -1376,12 +1400,21 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
13761400
emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
13771401
TSFlags, Rex, CurByte, OS, Fixups, STI);
13781402
CurOp = FirstMemOp + X86::AddrNumOperands;
1379-
if (HasVEX_4VOp3)
1380-
++CurOp;
13811403
if (HasVEX_I8Reg)
13821404
I8RegNum = getX86RegEncoding(MI, CurOp++);
13831405
break;
13841406
}
1407+
case X86II::MRMSrcMem4VOp3: {
1408+
unsigned FirstMemOp = CurOp+1;
1409+
1410+
EmitByte(BaseOpcode, CurByte, OS);
1411+
1412+
emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
1413+
TSFlags, Rex, CurByte, OS, Fixups, STI);
1414+
CurOp = FirstMemOp + X86::AddrNumOperands;
1415+
++CurOp; // Encoded in VEX.VVVV.
1416+
break;
1417+
}
13851418
case X86II::MRMSrcMemOp4: {
13861419
unsigned FirstMemOp = CurOp+1;
13871420

llvm/lib/Target/X86/X86InstrFormats.td

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,18 @@ def RawFrmDst : Format<5>;
2727
def RawFrmDstSrc : Format<6>;
2828
def RawFrmImm8 : Format<7>;
2929
def RawFrmImm16 : Format<8>;
30-
def MRMDestMem : Format<32>;
31-
def MRMSrcMem : Format<33>;
32-
def MRMSrcMemOp4 : Format<34>;
30+
def MRMDestMem : Format<32>;
31+
def MRMSrcMem : Format<33>;
32+
def MRMSrcMem4VOp3 : Format<34>;
33+
def MRMSrcMemOp4 : Format<35>;
3334
def MRMXm : Format<39>;
3435
def MRM0m : Format<40>; def MRM1m : Format<41>; def MRM2m : Format<42>;
3536
def MRM3m : Format<43>; def MRM4m : Format<44>; def MRM5m : Format<45>;
3637
def MRM6m : Format<46>; def MRM7m : Format<47>;
37-
def MRMDestReg : Format<48>;
38-
def MRMSrcReg : Format<49>;
39-
def MRMSrcRegOp4 : Format<50>;
38+
def MRMDestReg : Format<48>;
39+
def MRMSrcReg : Format<49>;
40+
def MRMSrcReg4VOp3 : Format<50>;
41+
def MRMSrcRegOp4 : Format<51>;
4042
def MRMXr : Format<55>;
4143
def MRM0r : Format<56>; def MRM1r : Format<57>; def MRM2r : Format<58>;
4244
def MRM3r : Format<59>; def MRM4r : Format<60>; def MRM5r : Format<61>;
@@ -199,7 +201,6 @@ class TAXD : TA { Prefix OpPrefix = XD; }
199201
class VEX { Encoding OpEnc = EncVEX; }
200202
class VEX_W { bit hasVEX_WPrefix = 1; }
201203
class VEX_4V : VEX { bit hasVEX_4V = 1; }
202-
class VEX_4VOp3 : VEX { bit hasVEX_4VOp3 = 1; }
203204
class VEX_L { bit hasVEX_L = 1; }
204205
class VEX_LIG { bit ignoresVEX_L = 1; }
205206
class EVEX : VEX { Encoding OpEnc = EncEVEX; }
@@ -222,7 +223,6 @@ class EVEX_CD8<int esize, CD8VForm form> {
222223
class Has3DNow0F0FOpcode { bit has3DNow0F0FOpcode = 1; }
223224
class XOP { Encoding OpEnc = EncXOP; }
224225
class XOP_4V : XOP { bit hasVEX_4V = 1; }
225-
class XOP_4VOp3 : XOP { bit hasVEX_4VOp3 = 1; }
226226

227227
class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
228228
string AsmStr,
@@ -272,8 +272,6 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
272272
bits<2> OpEncBits = OpEnc.Value;
273273
bit hasVEX_WPrefix = 0; // Does this inst set the VEX_W field?
274274
bit hasVEX_4V = 0; // Does this inst require the VEX.VVVV field?
275-
bit hasVEX_4VOp3 = 0; // Does this inst require the VEX.VVVV field to
276-
// encode the third operand?
277275
bit hasVEX_L = 0; // Does this inst use large (256-bit) registers?
278276
bit ignoresVEX_L = 0; // Does this instruction ignore the L-bit
279277
bit hasEVEX_K = 0; // Does this inst require masking?
@@ -321,16 +319,15 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
321319
let TSFlags{38-31} = Opcode;
322320
let TSFlags{39} = hasVEX_WPrefix;
323321
let TSFlags{40} = hasVEX_4V;
324-
let TSFlags{41} = hasVEX_4VOp3;
325-
let TSFlags{42} = hasVEX_L;
326-
let TSFlags{43} = hasEVEX_K;
327-
let TSFlags{44} = hasEVEX_Z;
328-
let TSFlags{45} = hasEVEX_L2;
329-
let TSFlags{46} = hasEVEX_B;
322+
let TSFlags{41} = hasVEX_L;
323+
let TSFlags{42} = hasEVEX_K;
324+
let TSFlags{43} = hasEVEX_Z;
325+
let TSFlags{44} = hasEVEX_L2;
326+
let TSFlags{45} = hasEVEX_B;
330327
// If we run out of TSFlags bits, it's possible to encode this in 3 bits.
331-
let TSFlags{53-47} = CD8_Scale;
332-
let TSFlags{54} = has3DNow0F0FOpcode;
333-
let TSFlags{55} = hasEVEX_RC;
328+
let TSFlags{52-46} = CD8_Scale;
329+
let TSFlags{53} = has3DNow0F0FOpcode;
330+
let TSFlags{54} = hasEVEX_RC;
334331
}
335332

336333
class PseudoI<dag oops, dag iops, list<dag> pattern>

llvm/lib/Target/X86/X86InstrInfo.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,14 +2254,14 @@ let Predicates = [HasBMI] in {
22542254
multiclass bmi_bextr_bzhi<bits<8> opc, string mnemonic, RegisterClass RC,
22552255
X86MemOperand x86memop, Intrinsic Int,
22562256
PatFrag ld_frag> {
2257-
def rr : I<opc, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
2257+
def rr : I<opc, MRMSrcReg4VOp3, (outs RC:$dst), (ins RC:$src1, RC:$src2),
22582258
!strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
22592259
[(set RC:$dst, (Int RC:$src1, RC:$src2)), (implicit EFLAGS)]>,
2260-
T8PS, VEX_4VOp3;
2261-
def rm : I<opc, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src1, RC:$src2),
2260+
T8PS, VEX;
2261+
def rm : I<opc, MRMSrcMem4VOp3, (outs RC:$dst), (ins x86memop:$src1, RC:$src2),
22622262
!strconcat(mnemonic, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
22632263
[(set RC:$dst, (Int (ld_frag addr:$src1), RC:$src2)),
2264-
(implicit EFLAGS)]>, T8PS, VEX_4VOp3;
2264+
(implicit EFLAGS)]>, T8PS, VEX;
22652265
}
22662266

22672267
let Predicates = [HasBMI], Defs = [EFLAGS] in {

llvm/lib/Target/X86/X86InstrSSE.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8696,16 +8696,16 @@ let Predicates = [HasAVX2, NoVLX] in {
86968696
// VGATHER - GATHER Operations
86978697
multiclass avx2_gather<bits<8> opc, string OpcodeStr, RegisterClass RC256,
86988698
X86MemOperand memop128, X86MemOperand memop256> {
8699-
def rm : AVX28I<opc, MRMSrcMem, (outs VR128:$dst, VR128:$mask_wb),
8699+
def rm : AVX28I<opc, MRMSrcMem4VOp3, (outs VR128:$dst, VR128:$mask_wb),
87008700
(ins VR128:$src1, memop128:$src2, VR128:$mask),
87018701
!strconcat(OpcodeStr,
87028702
"\t{$mask, $src2, $dst|$dst, $src2, $mask}"),
8703-
[]>, VEX_4VOp3;
8704-
def Yrm : AVX28I<opc, MRMSrcMem, (outs RC256:$dst, RC256:$mask_wb),
8703+
[]>, VEX;
8704+
def Yrm : AVX28I<opc, MRMSrcMem4VOp3, (outs RC256:$dst, RC256:$mask_wb),
87058705
(ins RC256:$src1, memop256:$src2, RC256:$mask),
87068706
!strconcat(OpcodeStr,
87078707
"\t{$mask, $src2, $dst|$dst, $src2, $mask}"),
8708-
[]>, VEX_4VOp3, VEX_L;
8708+
[]>, VEX, VEX_L;
87098709
}
87108710

87118711
let mayLoad = 1, hasSideEffects = 0, Constraints

llvm/lib/Target/X86/X86InstrShiftRotate.td

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -873,19 +873,19 @@ let hasSideEffects = 0 in {
873873

874874
multiclass bmi_shift<string asm, RegisterClass RC, X86MemOperand x86memop> {
875875
let hasSideEffects = 0 in {
876-
def rr : I<0xF7, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, RC:$src2),
876+
def rr : I<0xF7, MRMSrcReg4VOp3, (outs RC:$dst), (ins RC:$src1, RC:$src2),
877877
!strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>,
878-
VEX_4VOp3, Sched<[WriteShift]>;
878+
VEX, Sched<[WriteShift]>;
879879
let mayLoad = 1 in
880-
def rm : I<0xF7, MRMSrcMem, (outs RC:$dst), (ins x86memop:$src1, RC:$src2),
880+
def rm : I<0xF7, MRMSrcMem4VOp3,
881+
(outs RC:$dst), (ins x86memop:$src1, RC:$src2),
881882
!strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>,
882-
VEX_4VOp3,
883-
Sched<[WriteShiftLd,
884-
// x86memop:$src1
885-
ReadDefault, ReadDefault, ReadDefault, ReadDefault,
886-
ReadDefault,
887-
// RC:$src1
888-
ReadAfterLd]>;
883+
VEX, Sched<[WriteShiftLd,
884+
// x86memop:$src1
885+
ReadDefault, ReadDefault, ReadDefault, ReadDefault,
886+
ReadDefault,
887+
// RC:$src1
888+
ReadAfterLd]>;
889889
}
890890
}
891891

llvm/lib/Target/X86/X86InstrXOP.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,26 +85,26 @@ let ExeDomain = SSEPackedDouble in {
8585

8686
multiclass xop3op<bits<8> opc, string OpcodeStr, SDNode OpNode,
8787
ValueType vt128> {
88-
def rr : IXOP<opc, MRMSrcReg, (outs VR128:$dst),
88+
def rr : IXOP<opc, MRMSrcReg4VOp3, (outs VR128:$dst),
8989
(ins VR128:$src1, VR128:$src2),
9090
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
9191
[(set VR128:$dst,
9292
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2))))]>,
93-
XOP_4VOp3, Sched<[WriteVarVecShift]>;
93+
XOP, Sched<[WriteVarVecShift]>;
9494
def rm : IXOP<opc, MRMSrcMem, (outs VR128:$dst),
9595
(ins VR128:$src1, i128mem:$src2),
9696
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
9797
[(set VR128:$dst,
9898
(vt128 (OpNode (vt128 VR128:$src1),
9999
(vt128 (bitconvert (loadv2i64 addr:$src2))))))]>,
100100
XOP_4V, VEX_W, Sched<[WriteVarVecShift, ReadAfterLd]>;
101-
def mr : IXOP<opc, MRMSrcMem, (outs VR128:$dst),
101+
def mr : IXOP<opc, MRMSrcMem4VOp3, (outs VR128:$dst),
102102
(ins i128mem:$src1, VR128:$src2),
103103
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
104104
[(set VR128:$dst,
105105
(vt128 (OpNode (vt128 (bitconvert (loadv2i64 addr:$src1))),
106106
(vt128 VR128:$src2))))]>,
107-
XOP_4VOp3, Sched<[WriteVarVecShift, ReadAfterLd]>;
107+
XOP, Sched<[WriteVarVecShift, ReadAfterLd]>;
108108
}
109109

110110
let ExeDomain = SSEPackedInt in {

0 commit comments

Comments
 (0)