Skip to content

Commit 9b20fec

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

File tree

7 files changed

+151
-85
lines changed

7 files changed

+151
-85
lines changed

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

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

280+
/// MRMSrcMemOp4 - This form is used for instructions that use the Mod/RM
281+
/// byte to specify the fourth source, which in this case is memory.
282+
///
283+
MRMSrcMemOp4 = 34,
284+
280285
/// MRMXm - This form is used for instructions that use the Mod/RM byte
281286
/// to specify a memory source, but doesn't use the middle field.
282287
///
@@ -296,6 +301,11 @@ namespace X86II {
296301
///
297302
MRMSrcReg = 49,
298303

304+
/// MRMSrcRegOp4 - This form is used for instructions that use the Mod/RM
305+
/// byte to specify the fourth source, which in this case is a register.
306+
///
307+
MRMSrcRegOp4 = 50,
308+
299309
/// MRMXr - This form is used for instructions that use the Mod/RM byte
300310
/// to specify a register source, but doesn't use the middle field.
301311
///
@@ -536,13 +546,8 @@ namespace X86II {
536546
Has3DNow0F0FOpcodeShift = CD8_Scale_Shift + 7,
537547
Has3DNow0F0FOpcode = 1ULL << Has3DNow0F0FOpcodeShift,
538548

539-
/// MemOp4 - Used to indicate swapping of operand 3 and 4 to be encoded in
540-
/// ModRM or I8IMM. This is used for FMA4 and XOP instructions.
541-
MemOp4Shift = Has3DNow0F0FOpcodeShift + 1,
542-
MemOp4 = 1ULL << MemOp4Shift,
543-
544549
/// Explicitly specified rounding control
545-
EVEX_RCShift = MemOp4Shift + 1,
550+
EVEX_RCShift = Has3DNow0F0FOpcodeShift + 1,
546551
EVEX_RC = 1ULL << EVEX_RCShift
547552
};
548553

@@ -649,7 +654,6 @@ namespace X86II {
649654
///
650655
inline int getMemoryOperandNo(uint64_t TSFlags) {
651656
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
652-
bool HasMemOp4 = TSFlags & X86II::MemOp4;
653657
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
654658

655659
switch (TSFlags & X86II::FormMask) {
@@ -669,9 +673,13 @@ namespace X86II {
669673
case X86II::MRMSrcMem:
670674
// Start from 1, skip any registers encoded in VEX_VVVV or I8IMM, or a
671675
// mask register.
672-
return 1 + HasVEX_4V + HasMemOp4 + HasEVEX_K;
676+
return 1 + HasVEX_4V + HasEVEX_K;
677+
case X86II::MRMSrcMemOp4:
678+
// Skip registers encoded in reg, VEX_VVVV, and I8IMM.
679+
return 3;
673680
case X86II::MRMDestReg:
674681
case X86II::MRMSrcReg:
682+
case X86II::MRMSrcRegOp4:
675683
case X86II::MRMXr:
676684
case X86II::MRM0r: case X86II::MRM1r:
677685
case X86II::MRM2r: case X86II::MRM3r:

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

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
603603
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
604604
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
605605
bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3;
606-
bool HasMemOp4 = TSFlags & X86II::MemOp4;
607606
bool HasEVEX_RC = TSFlags & X86II::EVEX_RC;
608607

609608
// VEX_R: opcode externsion equivalent to REX.R in
@@ -749,7 +748,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
749748
//
750749
// FMA4:
751750
// dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4])
752-
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
753751
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
754752
VEX_R = ~(RegEnc >> 3) & 1;
755753
EVEX_R2 = ~(RegEnc >> 4) & 1;
@@ -779,6 +777,20 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
779777
VEX_4V = ~getX86RegEncoding(MI, CurOp + X86::AddrNumOperands) & 0xf;
780778
break;
781779
}
780+
case X86II::MRMSrcMemOp4: {
781+
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
782+
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
783+
VEX_R = ~(RegEnc >> 3) & 1;
784+
785+
unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
786+
VEX_4V = ~VRegEnc & 0xf;
787+
788+
unsigned BaseRegEnc = getX86RegEncoding(MI, MemOperand + X86::AddrBaseReg);
789+
VEX_B = ~(BaseRegEnc >> 3) & 1;
790+
unsigned IndexRegEnc = getX86RegEncoding(MI, MemOperand+X86::AddrIndexReg);
791+
VEX_X = ~(IndexRegEnc >> 3) & 1;
792+
break;
793+
}
782794
case X86II::MRM0m: case X86II::MRM1m:
783795
case X86II::MRM2m: case X86II::MRM3m:
784796
case X86II::MRM4m: case X86II::MRM5m:
@@ -808,7 +820,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
808820
// dst(ModR/M), src1(ModR/M), imm8
809821
//
810822
// FMA4:
811-
// dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4])
812823
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
813824
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
814825
VEX_R = ~(RegEnc >> 3) & 1;
@@ -823,9 +834,6 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
823834
EVEX_V2 = ~(VRegEnc >> 4) & 1;
824835
}
825836

826-
if (HasMemOp4) // Skip second register source (encoded in Imm[7:4])
827-
CurOp++;
828-
829837
RegEnc = getX86RegEncoding(MI, CurOp++);
830838
VEX_B = ~(RegEnc >> 3) & 1;
831839
VEX_X = ~(RegEnc >> 4) & 1;
@@ -841,6 +849,22 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
841849
}
842850
break;
843851
}
852+
case X86II::MRMSrcRegOp4: {
853+
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
854+
unsigned RegEnc = getX86RegEncoding(MI, CurOp++);
855+
VEX_R = ~(RegEnc >> 3) & 1;
856+
857+
unsigned VRegEnc = getX86RegEncoding(MI, CurOp++);
858+
VEX_4V = ~VRegEnc & 0xf;
859+
860+
// Skip second register source (encoded in Imm[7:4])
861+
++CurOp;
862+
863+
RegEnc = getX86RegEncoding(MI, CurOp++);
864+
VEX_B = ~(RegEnc >> 3) & 1;
865+
VEX_X = ~(RegEnc >> 4) & 1;
866+
break;
867+
}
844868
case X86II::MRMDestReg: {
845869
// MRMDestReg instructions forms:
846870
// dst(ModR/M), src(ModR/M)
@@ -1134,9 +1158,7 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
11341158
// It uses the VEX.VVVV field?
11351159
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
11361160
bool HasVEX_4VOp3 = TSFlags & X86II::VEX_4VOp3;
1137-
bool HasMemOp4 = TSFlags & X86II::MemOp4;
11381161
bool HasVEX_I8Reg = (TSFlags & X86II::ImmMask) == X86II::Imm8Reg;
1139-
assert((!HasMemOp4 || HasVEX_I8Reg) && "MemOp4 should imply VEX_I8Reg");
11401162

11411163
// It uses the EVEX.aaa field?
11421164
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
@@ -1312,21 +1334,34 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
13121334
if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
13131335
++SrcRegNum;
13141336

1315-
if (HasMemOp4) // Capture 2nd src (which is encoded in Imm[7:4])
1316-
I8RegNum = getX86RegEncoding(MI, SrcRegNum++);
1317-
13181337
EmitRegModRMByte(MI.getOperand(SrcRegNum),
13191338
GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
13201339
CurOp = SrcRegNum + 1;
13211340
if (HasVEX_4VOp3)
13221341
++CurOp;
1323-
if (!HasMemOp4 && HasVEX_I8Reg)
1342+
if (HasVEX_I8Reg)
13241343
I8RegNum = getX86RegEncoding(MI, CurOp++);
13251344
// do not count the rounding control operand
13261345
if (HasEVEX_RC)
13271346
--NumOps;
13281347
break;
13291348
}
1349+
case X86II::MRMSrcRegOp4: {
1350+
EmitByte(BaseOpcode, CurByte, OS);
1351+
unsigned SrcRegNum = CurOp + 1;
1352+
1353+
// Skip 1st src (which is encoded in VEX_VVVV)
1354+
++SrcRegNum;
1355+
1356+
// Capture 2nd src (which is encoded in Imm[7:4])
1357+
assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg");
1358+
I8RegNum = getX86RegEncoding(MI, SrcRegNum++);
1359+
1360+
EmitRegModRMByte(MI.getOperand(SrcRegNum),
1361+
GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS);
1362+
CurOp = SrcRegNum + 1;
1363+
break;
1364+
}
13301365
case X86II::MRMSrcMem: {
13311366
unsigned FirstMemOp = CurOp+1;
13321367

@@ -1336,20 +1371,33 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
13361371
if (HasVEX_4V)
13371372
++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
13381373

1339-
if (HasMemOp4) // Capture second register source (encoded in Imm[7:4])
1340-
I8RegNum = getX86RegEncoding(MI, FirstMemOp++);
1341-
13421374
EmitByte(BaseOpcode, CurByte, OS);
13431375

13441376
emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
13451377
TSFlags, Rex, CurByte, OS, Fixups, STI);
13461378
CurOp = FirstMemOp + X86::AddrNumOperands;
13471379
if (HasVEX_4VOp3)
13481380
++CurOp;
1349-
if (!HasMemOp4 && HasVEX_I8Reg)
1381+
if (HasVEX_I8Reg)
13501382
I8RegNum = getX86RegEncoding(MI, CurOp++);
13511383
break;
13521384
}
1385+
case X86II::MRMSrcMemOp4: {
1386+
unsigned FirstMemOp = CurOp+1;
1387+
1388+
++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV).
1389+
1390+
// Capture second register source (encoded in Imm[7:4])
1391+
assert(HasVEX_I8Reg && "MRMSrcRegOp4 should imply VEX_I8Reg");
1392+
I8RegNum = getX86RegEncoding(MI, FirstMemOp++);
1393+
1394+
EmitByte(BaseOpcode, CurByte, OS);
1395+
1396+
emitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
1397+
TSFlags, Rex, CurByte, OS, Fixups, STI);
1398+
CurOp = FirstMemOp + X86::AddrNumOperands;
1399+
break;
1400+
}
13531401

13541402
case X86II::MRMXr:
13551403
case X86II::MRM0r: case X86II::MRM1r:

llvm/lib/Target/X86/X86InstrFMA.td

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -269,18 +269,18 @@ multiclass fma4s<bits<8> opc, string OpcodeStr, RegisterClass RC,
269269
X86MemOperand x86memop, ValueType OpVT, SDNode OpNode,
270270
PatFrag mem_frag> {
271271
let isCommutable = 1 in
272-
def rr : FMA4<opc, MRMSrcReg, (outs RC:$dst),
272+
def rr : FMA4<opc, MRMSrcRegOp4, (outs RC:$dst),
273273
(ins RC:$src1, RC:$src2, RC:$src3),
274274
!strconcat(OpcodeStr,
275275
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
276276
[(set RC:$dst,
277-
(OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, VEX_LIG, MemOp4;
278-
def rm : FMA4<opc, MRMSrcMem, (outs RC:$dst),
277+
(OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, VEX_LIG;
278+
def rm : FMA4<opc, MRMSrcMemOp4, (outs RC:$dst),
279279
(ins RC:$src1, RC:$src2, x86memop:$src3),
280280
!strconcat(OpcodeStr,
281281
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
282282
[(set RC:$dst, (OpNode RC:$src1, RC:$src2,
283-
(mem_frag addr:$src3)))]>, VEX_W, VEX_LIG, MemOp4;
283+
(mem_frag addr:$src3)))]>, VEX_W, VEX_LIG;
284284
def mr : FMA4<opc, MRMSrcMem, (outs RC:$dst),
285285
(ins RC:$src1, x86memop:$src2, RC:$src3),
286286
!strconcat(OpcodeStr,
@@ -300,18 +300,18 @@ multiclass fma4s_int<bits<8> opc, string OpcodeStr, Operand memop,
300300
ComplexPattern mem_cpat, Intrinsic Int> {
301301
let isCodeGenOnly = 1 in {
302302
let isCommutable = 1 in
303-
def rr_Int : FMA4<opc, MRMSrcReg, (outs VR128:$dst),
303+
def rr_Int : FMA4<opc, MRMSrcRegOp4, (outs VR128:$dst),
304304
(ins VR128:$src1, VR128:$src2, VR128:$src3),
305305
!strconcat(OpcodeStr,
306306
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
307307
[(set VR128:$dst,
308-
(Int VR128:$src1, VR128:$src2, VR128:$src3))]>, VEX_W, VEX_LIG, MemOp4;
309-
def rm_Int : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
308+
(Int VR128:$src1, VR128:$src2, VR128:$src3))]>, VEX_W, VEX_LIG;
309+
def rm_Int : FMA4<opc, MRMSrcMemOp4, (outs VR128:$dst),
310310
(ins VR128:$src1, VR128:$src2, memop:$src3),
311311
!strconcat(OpcodeStr,
312312
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
313313
[(set VR128:$dst, (Int VR128:$src1, VR128:$src2,
314-
mem_cpat:$src3))]>, VEX_W, VEX_LIG, MemOp4;
314+
mem_cpat:$src3))]>, VEX_W, VEX_LIG;
315315
def mr_Int : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
316316
(ins VR128:$src1, memop:$src2, VR128:$src3),
317317
!strconcat(OpcodeStr,
@@ -325,39 +325,39 @@ multiclass fma4p<bits<8> opc, string OpcodeStr, SDNode OpNode,
325325
ValueType OpVT128, ValueType OpVT256,
326326
PatFrag ld_frag128, PatFrag ld_frag256> {
327327
let isCommutable = 1 in
328-
def rr : FMA4<opc, MRMSrcReg, (outs VR128:$dst),
328+
def rr : FMA4<opc, MRMSrcRegOp4, (outs VR128:$dst),
329329
(ins VR128:$src1, VR128:$src2, VR128:$src3),
330330
!strconcat(OpcodeStr,
331331
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
332332
[(set VR128:$dst,
333333
(OpVT128 (OpNode VR128:$src1, VR128:$src2, VR128:$src3)))]>,
334-
VEX_W, MemOp4;
335-
def rm : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
334+
VEX_W;
335+
def rm : FMA4<opc, MRMSrcMemOp4, (outs VR128:$dst),
336336
(ins VR128:$src1, VR128:$src2, f128mem:$src3),
337337
!strconcat(OpcodeStr,
338338
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
339339
[(set VR128:$dst, (OpNode VR128:$src1, VR128:$src2,
340-
(ld_frag128 addr:$src3)))]>, VEX_W, MemOp4;
340+
(ld_frag128 addr:$src3)))]>, VEX_W;
341341
def mr : FMA4<opc, MRMSrcMem, (outs VR128:$dst),
342342
(ins VR128:$src1, f128mem:$src2, VR128:$src3),
343343
!strconcat(OpcodeStr,
344344
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
345345
[(set VR128:$dst,
346346
(OpNode VR128:$src1, (ld_frag128 addr:$src2), VR128:$src3))]>;
347347
let isCommutable = 1 in
348-
def Yrr : FMA4<opc, MRMSrcReg, (outs VR256:$dst),
348+
def Yrr : FMA4<opc, MRMSrcRegOp4, (outs VR256:$dst),
349349
(ins VR256:$src1, VR256:$src2, VR256:$src3),
350350
!strconcat(OpcodeStr,
351351
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
352352
[(set VR256:$dst,
353353
(OpVT256 (OpNode VR256:$src1, VR256:$src2, VR256:$src3)))]>,
354-
VEX_W, MemOp4, VEX_L;
355-
def Yrm : FMA4<opc, MRMSrcMem, (outs VR256:$dst),
354+
VEX_W, VEX_L;
355+
def Yrm : FMA4<opc, MRMSrcMemOp4, (outs VR256:$dst),
356356
(ins VR256:$src1, VR256:$src2, f256mem:$src3),
357357
!strconcat(OpcodeStr,
358358
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
359359
[(set VR256:$dst, (OpNode VR256:$src1, VR256:$src2,
360-
(ld_frag256 addr:$src3)))]>, VEX_W, MemOp4, VEX_L;
360+
(ld_frag256 addr:$src3)))]>, VEX_W, VEX_L;
361361
def Ymr : FMA4<opc, MRMSrcMem, (outs VR256:$dst),
362362
(ins VR256:$src1, f256mem:$src2, VR256:$src3),
363363
!strconcat(OpcodeStr,

llvm/lib/Target/X86/X86InstrFormats.td

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ 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>;
30+
def MRMDestMem : Format<32>;
31+
def MRMSrcMem : Format<33>;
32+
def MRMSrcMemOp4 : Format<34>;
3233
def MRMXm : Format<39>;
3334
def MRM0m : Format<40>; def MRM1m : Format<41>; def MRM2m : Format<42>;
3435
def MRM3m : Format<43>; def MRM4m : Format<44>; def MRM5m : Format<45>;
3536
def MRM6m : Format<46>; def MRM7m : Format<47>;
36-
def MRMDestReg : Format<48>;
37-
def MRMSrcReg : Format<49>;
37+
def MRMDestReg : Format<48>;
38+
def MRMSrcReg : Format<49>;
39+
def MRMSrcRegOp4 : Format<50>;
3840
def MRMXr : Format<55>;
3941
def MRM0r : Format<56>; def MRM1r : Format<57>; def MRM2r : Format<58>;
4042
def MRM3r : Format<59>; def MRM4r : Format<60>; def MRM5r : Format<61>;
@@ -218,7 +220,6 @@ class EVEX_CD8<int esize, CD8VForm form> {
218220
}
219221

220222
class Has3DNow0F0FOpcode { bit has3DNow0F0FOpcode = 1; }
221-
class MemOp4 { bit hasMemOp4Prefix = 1; }
222223
class XOP { Encoding OpEnc = EncXOP; }
223224
class XOP_4V : XOP { bit hasVEX_4V = 1; }
224225
class XOP_4VOp3 : XOP { bit hasVEX_4VOp3 = 1; }
@@ -284,7 +285,6 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
284285
// assigning to bits<7>.
285286
int CD8_EltSize = 0; // Compressed disp8 form - element-size in bytes.
286287
bit has3DNow0F0FOpcode =0;// Wacky 3dNow! encoding?
287-
bit hasMemOp4Prefix = 0; // Same bit as VEX_W, but used for swapping operands
288288
bit hasEVEX_RC = 0; // Explicitly specified rounding control in FP instruction.
289289

290290
bits<2> EVEX_LL;
@@ -330,8 +330,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
330330
// If we run out of TSFlags bits, it's possible to encode this in 3 bits.
331331
let TSFlags{53-47} = CD8_Scale;
332332
let TSFlags{54} = has3DNow0F0FOpcode;
333-
let TSFlags{55} = hasMemOp4Prefix;
334-
let TSFlags{56} = hasEVEX_RC;
333+
let TSFlags{55} = hasEVEX_RC;
335334
}
336335

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

0 commit comments

Comments
 (0)