2012-02-19 10:03:36 +08:00
|
|
|
//===-- X86InstrXOP.td - XOP Instruction Set ---------------*- tablegen -*-===//
|
2011-12-13 03:37:49 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-12-13 03:37:49 +08:00
|
|
|
//
|
2012-02-18 20:03:15 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2011-12-13 03:37:49 +08:00
|
|
|
//
|
|
|
|
// This file describes XOP (eXtended OPerations)
|
|
|
|
//
|
2012-02-18 20:03:15 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2011-12-13 03:37:49 +08:00
|
|
|
|
2018-10-23 06:14:05 +08:00
|
|
|
multiclass xop2op<bits<8> opc, string OpcodeStr, Intrinsic Int> {
|
2011-12-13 03:37:49 +08:00
|
|
|
def rr : IXOP<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-05-11 01:06:09 +08:00
|
|
|
[(set VR128:$dst, (Int VR128:$src))]>, XOP, Sched<[SchedWritePHAdd.XMM]>;
|
2012-06-10 15:31:56 +08:00
|
|
|
def rm : IXOP<opc, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
|
2011-12-13 03:37:49 +08:00
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-10-23 06:14:05 +08:00
|
|
|
[(set VR128:$dst, (Int (load addr:$src)))]>, XOP,
|
2018-10-06 01:57:29 +08:00
|
|
|
Sched<[SchedWritePHAdd.XMM.Folded, SchedWritePHAdd.XMM.ReadAfterFold]>;
|
2012-01-11 23:20:20 +08:00
|
|
|
}
|
|
|
|
|
2015-02-15 06:40:46 +08:00
|
|
|
let ExeDomain = SSEPackedInt in {
|
2018-10-23 06:14:05 +08:00
|
|
|
defm VPHSUBWD : xop2op<0xE2, "vphsubwd", int_x86_xop_vphsubwd>;
|
|
|
|
defm VPHSUBDQ : xop2op<0xE3, "vphsubdq", int_x86_xop_vphsubdq>;
|
|
|
|
defm VPHSUBBW : xop2op<0xE1, "vphsubbw", int_x86_xop_vphsubbw>;
|
|
|
|
defm VPHADDWQ : xop2op<0xC7, "vphaddwq", int_x86_xop_vphaddwq>;
|
|
|
|
defm VPHADDWD : xop2op<0xC6, "vphaddwd", int_x86_xop_vphaddwd>;
|
|
|
|
defm VPHADDUWQ : xop2op<0xD7, "vphadduwq", int_x86_xop_vphadduwq>;
|
|
|
|
defm VPHADDUWD : xop2op<0xD6, "vphadduwd", int_x86_xop_vphadduwd>;
|
|
|
|
defm VPHADDUDQ : xop2op<0xDB, "vphaddudq", int_x86_xop_vphaddudq>;
|
|
|
|
defm VPHADDUBW : xop2op<0xD1, "vphaddubw", int_x86_xop_vphaddubw>;
|
|
|
|
defm VPHADDUBQ : xop2op<0xD3, "vphaddubq", int_x86_xop_vphaddubq>;
|
|
|
|
defm VPHADDUBD : xop2op<0xD2, "vphaddubd", int_x86_xop_vphaddubd>;
|
|
|
|
defm VPHADDDQ : xop2op<0xCB, "vphadddq", int_x86_xop_vphadddq>;
|
|
|
|
defm VPHADDBW : xop2op<0xC1, "vphaddbw", int_x86_xop_vphaddbw>;
|
|
|
|
defm VPHADDBQ : xop2op<0xC3, "vphaddbq", int_x86_xop_vphaddbq>;
|
|
|
|
defm VPHADDBD : xop2op<0xC2, "vphaddbd", int_x86_xop_vphaddbd>;
|
2015-02-15 06:40:46 +08:00
|
|
|
}
|
2012-01-11 23:20:20 +08:00
|
|
|
|
|
|
|
// Scalar load 2 addr operand instructions
|
|
|
|
multiclass xop2opsld<bits<8> opc, string OpcodeStr, Intrinsic Int,
|
2018-05-03 00:25:41 +08:00
|
|
|
Operand memop, ComplexPattern mem_cpat,
|
|
|
|
X86FoldableSchedWrite sched> {
|
2012-06-13 15:18:53 +08:00
|
|
|
def rr : IXOP<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-05-03 00:25:41 +08:00
|
|
|
[(set VR128:$dst, (Int VR128:$src))]>, XOP, Sched<[sched]>;
|
2012-06-13 15:18:53 +08:00
|
|
|
def rm : IXOP<opc, MRMSrcMem, (outs VR128:$dst), (ins memop:$src),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-10-23 06:14:05 +08:00
|
|
|
[(set VR128:$dst, (Int mem_cpat:$src))]>, XOP,
|
2018-10-06 01:57:29 +08:00
|
|
|
Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2011-12-13 03:37:49 +08:00
|
|
|
}
|
|
|
|
|
2012-06-10 15:31:56 +08:00
|
|
|
multiclass xop2op128<bits<8> opc, string OpcodeStr, Intrinsic Int,
|
2018-10-23 06:14:05 +08:00
|
|
|
X86FoldableSchedWrite sched> {
|
2012-06-10 15:31:56 +08:00
|
|
|
def rr : IXOP<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-05-03 00:25:41 +08:00
|
|
|
[(set VR128:$dst, (Int VR128:$src))]>, XOP, Sched<[sched]>;
|
2012-06-10 15:31:56 +08:00
|
|
|
def rm : IXOP<opc, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-10-23 06:14:05 +08:00
|
|
|
[(set VR128:$dst, (Int (load addr:$src)))]>, XOP,
|
2018-10-06 01:57:29 +08:00
|
|
|
Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2012-06-10 15:31:56 +08:00
|
|
|
}
|
|
|
|
|
2012-01-11 23:20:20 +08:00
|
|
|
multiclass xop2op256<bits<8> opc, string OpcodeStr, Intrinsic Int,
|
2018-10-23 06:14:05 +08:00
|
|
|
X86FoldableSchedWrite sched> {
|
2018-01-24 13:14:39 +08:00
|
|
|
def Yrr : IXOP<opc, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
|
2011-12-13 03:37:49 +08:00
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-05-03 00:25:41 +08:00
|
|
|
[(set VR256:$dst, (Int VR256:$src))]>, XOP, VEX_L, Sched<[sched]>;
|
2018-01-24 13:14:39 +08:00
|
|
|
def Yrm : IXOP<opc, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
|
2011-12-13 03:37:49 +08:00
|
|
|
!strconcat(OpcodeStr, "\t{$src, $dst|$dst, $src}"),
|
2018-10-23 06:14:05 +08:00
|
|
|
[(set VR256:$dst, (Int (load addr:$src)))]>, XOP, VEX_L,
|
2018-10-06 01:57:29 +08:00
|
|
|
Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2011-12-13 03:37:49 +08:00
|
|
|
}
|
|
|
|
|
2015-02-15 06:40:46 +08:00
|
|
|
let ExeDomain = SSEPackedSingle in {
|
|
|
|
defm VFRCZSS : xop2opsld<0x82, "vfrczss", int_x86_xop_vfrcz_ss,
|
2018-05-04 20:59:24 +08:00
|
|
|
ssmem, sse_load_f32, SchedWriteFRnd.Scl>;
|
2018-10-23 06:14:05 +08:00
|
|
|
defm VFRCZPS : xop2op128<0x80, "vfrczps", int_x86_xop_vfrcz_ps,
|
2018-05-04 20:59:24 +08:00
|
|
|
SchedWriteFRnd.XMM>;
|
2018-10-23 06:14:05 +08:00
|
|
|
defm VFRCZPS : xop2op256<0x80, "vfrczps", int_x86_xop_vfrcz_ps_256,
|
2018-05-04 20:59:24 +08:00
|
|
|
SchedWriteFRnd.YMM>;
|
2015-02-15 06:40:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
let ExeDomain = SSEPackedDouble in {
|
|
|
|
defm VFRCZSD : xop2opsld<0x83, "vfrczsd", int_x86_xop_vfrcz_sd,
|
2018-05-04 20:59:24 +08:00
|
|
|
sdmem, sse_load_f64, SchedWriteFRnd.Scl>;
|
2018-10-23 06:14:05 +08:00
|
|
|
defm VFRCZPD : xop2op128<0x81, "vfrczpd", int_x86_xop_vfrcz_pd,
|
2018-05-04 20:59:24 +08:00
|
|
|
SchedWriteFRnd.XMM>;
|
2018-10-23 06:14:05 +08:00
|
|
|
defm VFRCZPD : xop2op256<0x81, "vfrczpd", int_x86_xop_vfrcz_pd_256,
|
2018-05-04 20:59:24 +08:00
|
|
|
SchedWriteFRnd.YMM>;
|
2015-02-15 06:40:46 +08:00
|
|
|
}
|
2011-12-13 03:37:49 +08:00
|
|
|
|
2015-09-30 16:17:50 +08:00
|
|
|
multiclass xop3op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
2018-05-03 00:25:41 +08:00
|
|
|
ValueType vt128, X86FoldableSchedWrite sched> {
|
2016-08-22 15:38:50 +08:00
|
|
|
def rr : IXOP<opc, MRMSrcReg4VOp3, (outs VR128:$dst),
|
2015-09-30 16:17:50 +08:00
|
|
|
(ins VR128:$src1, VR128:$src2),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
|
|
[(set VR128:$dst,
|
|
|
|
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2))))]>,
|
2018-05-03 00:25:41 +08:00
|
|
|
XOP, Sched<[sched]>;
|
2015-09-30 16:17:50 +08:00
|
|
|
def rm : IXOP<opc, MRMSrcMem, (outs VR128:$dst),
|
|
|
|
(ins VR128:$src1, i128mem:$src2),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
|
|
[(set VR128:$dst,
|
|
|
|
(vt128 (OpNode (vt128 VR128:$src1),
|
2018-10-23 06:14:05 +08:00
|
|
|
(vt128 (load addr:$src2)))))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP_4V, VEX_W, Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2016-08-22 15:38:50 +08:00
|
|
|
def mr : IXOP<opc, MRMSrcMem4VOp3, (outs VR128:$dst),
|
2015-09-30 16:17:50 +08:00
|
|
|
(ins i128mem:$src1, VR128:$src2),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
|
|
[(set VR128:$dst,
|
2018-10-23 06:14:05 +08:00
|
|
|
(vt128 (OpNode (vt128 (load addr:$src1)),
|
2015-09-30 16:17:50 +08:00
|
|
|
(vt128 VR128:$src2))))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP, Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2016-11-26 10:14:00 +08:00
|
|
|
// For disassembler
|
|
|
|
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
|
|
|
def rr_REV : IXOP<opc, MRMSrcReg, (outs VR128:$dst),
|
|
|
|
(ins VR128:$src1, VR128:$src2),
|
|
|
|
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
|
|
[]>,
|
2018-05-03 00:25:41 +08:00
|
|
|
XOP_4V, VEX_W, Sched<[sched]>, FoldGenData<NAME#rr>;
|
2015-09-30 16:17:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
let ExeDomain = SSEPackedInt in {
|
2018-05-03 00:25:41 +08:00
|
|
|
defm VPROTB : xop3op<0x90, "vprotb", rotl, v16i8, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPROTD : xop3op<0x92, "vprotd", rotl, v4i32, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPROTQ : xop3op<0x93, "vprotq", rotl, v2i64, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPROTW : xop3op<0x91, "vprotw", rotl, v8i16, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHAB : xop3op<0x98, "vpshab", X86vpsha, v16i8, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHAD : xop3op<0x9A, "vpshad", X86vpsha, v4i32, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHAQ : xop3op<0x9B, "vpshaq", X86vpsha, v2i64, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHAW : xop3op<0x99, "vpshaw", X86vpsha, v8i16, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHLB : xop3op<0x94, "vpshlb", X86vpshl, v16i8, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHLD : xop3op<0x96, "vpshld", X86vpshl, v4i32, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHLQ : xop3op<0x97, "vpshlq", X86vpshl, v2i64, SchedWriteVarVecShift.XMM>;
|
|
|
|
defm VPSHLW : xop3op<0x95, "vpshlw", X86vpshl, v8i16, SchedWriteVarVecShift.XMM>;
|
2015-09-30 16:17:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-18 03:04:24 +08:00
|
|
|
multiclass xop3opimm<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
2018-05-03 00:25:41 +08:00
|
|
|
ValueType vt128, X86FoldableSchedWrite sched> {
|
2012-06-10 15:31:56 +08:00
|
|
|
def ri : IXOPi8<opc, MRMSrcReg, (outs VR128:$dst),
|
2015-10-13 13:06:25 +08:00
|
|
|
(ins VR128:$src1, u8imm:$src2),
|
2012-06-10 15:31:56 +08:00
|
|
|
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
2015-10-18 03:04:24 +08:00
|
|
|
[(set VR128:$dst,
|
2019-09-20 00:26:14 +08:00
|
|
|
(vt128 (OpNode (vt128 VR128:$src1), timm:$src2)))]>,
|
2018-05-03 00:25:41 +08:00
|
|
|
XOP, Sched<[sched]>;
|
2012-06-10 15:31:56 +08:00
|
|
|
def mi : IXOPi8<opc, MRMSrcMem, (outs VR128:$dst),
|
2015-10-13 13:06:25 +08:00
|
|
|
(ins i128mem:$src1, u8imm:$src2),
|
2012-06-10 15:31:56 +08:00
|
|
|
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
|
|
[(set VR128:$dst,
|
2019-09-20 00:26:14 +08:00
|
|
|
(vt128 (OpNode (vt128 (load addr:$src1)), timm:$src2)))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP, Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2011-12-13 03:37:49 +08:00
|
|
|
}
|
|
|
|
|
2015-02-15 06:40:46 +08:00
|
|
|
let ExeDomain = SSEPackedInt in {
|
2018-05-04 01:56:43 +08:00
|
|
|
defm VPROTB : xop3opimm<0xC0, "vprotb", X86vrotli, v16i8,
|
|
|
|
SchedWriteVecShiftImm.XMM>;
|
|
|
|
defm VPROTD : xop3opimm<0xC2, "vprotd", X86vrotli, v4i32,
|
|
|
|
SchedWriteVecShiftImm.XMM>;
|
|
|
|
defm VPROTQ : xop3opimm<0xC3, "vprotq", X86vrotli, v2i64,
|
|
|
|
SchedWriteVecShiftImm.XMM>;
|
|
|
|
defm VPROTW : xop3opimm<0xC1, "vprotw", X86vrotli, v8i16,
|
|
|
|
SchedWriteVecShiftImm.XMM>;
|
2015-02-15 06:40:46 +08:00
|
|
|
}
|
2011-12-13 03:37:49 +08:00
|
|
|
|
|
|
|
// Instruction where second source can be memory, but third must be register
|
2018-04-25 02:13:57 +08:00
|
|
|
multiclass xop4opm2<bits<8> opc, string OpcodeStr, Intrinsic Int,
|
|
|
|
X86FoldableSchedWrite sched> {
|
2015-02-15 06:40:46 +08:00
|
|
|
let isCommutable = 1 in
|
2016-08-22 09:37:19 +08:00
|
|
|
def rr : IXOPi8Reg<opc, MRMSrcReg, (outs VR128:$dst),
|
2011-12-13 03:37:49 +08:00
|
|
|
(ins VR128:$src1, VR128:$src2, VR128:$src3),
|
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
2012-01-11 23:20:20 +08:00
|
|
|
[(set VR128:$dst,
|
2017-11-21 20:02:18 +08:00
|
|
|
(Int VR128:$src1, VR128:$src2, VR128:$src3))]>, XOP_4V,
|
2018-04-25 02:13:57 +08:00
|
|
|
Sched<[sched]>;
|
2016-08-22 09:37:19 +08:00
|
|
|
def rm : IXOPi8Reg<opc, MRMSrcMem, (outs VR128:$dst),
|
2012-06-10 15:31:56 +08:00
|
|
|
(ins VR128:$src1, i128mem:$src2, VR128:$src3),
|
2011-12-13 03:37:49 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
2012-01-11 23:20:20 +08:00
|
|
|
[(set VR128:$dst,
|
2018-10-23 06:14:05 +08:00
|
|
|
(Int VR128:$src1, (load addr:$src2),
|
2018-10-06 01:57:29 +08:00
|
|
|
VR128:$src3))]>, XOP_4V, Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2011-12-13 03:37:49 +08:00
|
|
|
}
|
|
|
|
|
2015-02-15 06:40:46 +08:00
|
|
|
let ExeDomain = SSEPackedInt in {
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMADCSWD : xop4opm2<0xB6, "vpmadcswd",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmadcswd, SchedWriteVecIMul.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMADCSSWD : xop4opm2<0xA6, "vpmadcsswd",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmadcsswd, SchedWriteVecIMul.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSWW : xop4opm2<0x95, "vpmacsww",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacsww, SchedWriteVecIMul.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSWD : xop4opm2<0x96, "vpmacswd",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacswd, SchedWriteVecIMul.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSSWW : xop4opm2<0x85, "vpmacssww",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacssww, SchedWriteVecIMul.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSSWD : xop4opm2<0x86, "vpmacsswd",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacsswd, SchedWriteVecIMul.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSSDQL : xop4opm2<0x87, "vpmacssdql",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacssdql, SchedWritePMULLD.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSSDQH : xop4opm2<0x8F, "vpmacssdqh",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacssdqh, SchedWritePMULLD.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSSDD : xop4opm2<0x8E, "vpmacssdd",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacssdd, SchedWritePMULLD.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSDQL : xop4opm2<0x97, "vpmacsdql",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacsdql, SchedWritePMULLD.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSDQH : xop4opm2<0x9F, "vpmacsdqh",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacsdqh, SchedWritePMULLD.XMM>;
|
2018-04-25 02:13:57 +08:00
|
|
|
defm VPMACSDD : xop4opm2<0x9E, "vpmacsdd",
|
2018-05-03 00:25:41 +08:00
|
|
|
int_x86_xop_vpmacsdd, SchedWritePMULLD.XMM>;
|
2015-02-15 06:40:46 +08:00
|
|
|
}
|
2011-12-13 03:37:49 +08:00
|
|
|
|
2017-01-15 01:13:52 +08:00
|
|
|
// IFMA patterns - for cases where we can safely ignore the overflow bits from
|
2017-01-15 02:08:54 +08:00
|
|
|
// the multiply or easily match with existing intrinsics.
|
2017-01-15 01:13:52 +08:00
|
|
|
let Predicates = [HasXOP] in {
|
|
|
|
def : Pat<(v8i16 (add (mul (v8i16 VR128:$src1), (v8i16 VR128:$src2)),
|
|
|
|
(v8i16 VR128:$src3))),
|
|
|
|
(VPMACSWWrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
|
|
|
def : Pat<(v4i32 (add (mul (v4i32 VR128:$src1), (v4i32 VR128:$src2)),
|
|
|
|
(v4i32 VR128:$src3))),
|
|
|
|
(VPMACSDDrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
2018-03-08 16:02:52 +08:00
|
|
|
def : Pat<(v2i64 (add (X86pmuldq (bc_v2i64 (X86PShufd (v4i32 VR128:$src1), (i8 -11))),
|
|
|
|
(bc_v2i64 (X86PShufd (v4i32 VR128:$src2), (i8 -11)))),
|
2017-01-15 02:08:54 +08:00
|
|
|
(v2i64 VR128:$src3))),
|
|
|
|
(VPMACSDQHrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
2018-03-08 16:02:52 +08:00
|
|
|
def : Pat<(v2i64 (add (X86pmuldq (v2i64 VR128:$src1), (v2i64 VR128:$src2)),
|
2017-01-15 02:08:54 +08:00
|
|
|
(v2i64 VR128:$src3))),
|
|
|
|
(VPMACSDQLrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
2017-01-15 02:52:13 +08:00
|
|
|
def : Pat<(v4i32 (add (X86vpmaddwd (v8i16 VR128:$src1), (v8i16 VR128:$src2)),
|
|
|
|
(v4i32 VR128:$src3))),
|
|
|
|
(VPMADCSWDrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
2017-01-15 01:13:52 +08:00
|
|
|
}
|
|
|
|
|
2018-02-20 11:58:13 +08:00
|
|
|
// Transforms to swizzle an immediate to help matching memory operand in first
|
|
|
|
// operand.
|
|
|
|
def CommuteVPCOMCC : SDNodeXForm<imm, [{
|
|
|
|
uint8_t Imm = N->getZExtValue() & 0x7;
|
|
|
|
Imm = X86::getSwappedVPCOMImm(Imm);
|
|
|
|
return getI8Imm(Imm, SDLoc(N));
|
|
|
|
}]>;
|
|
|
|
|
2011-12-13 03:37:49 +08:00
|
|
|
// Instruction where second source can be memory, third must be imm8
|
2018-05-03 00:25:41 +08:00
|
|
|
multiclass xopvpcom<bits<8> opc, string Suffix, SDNode OpNode, ValueType vt128,
|
|
|
|
X86FoldableSchedWrite sched> {
|
2018-02-20 11:58:13 +08:00
|
|
|
let ExeDomain = SSEPackedInt in { // SSE integer instructions
|
|
|
|
let isCommutable = 1 in
|
|
|
|
def ri : IXOPi8<opc, MRMSrcReg, (outs VR128:$dst),
|
[X86] Remove the _alt forms of XOP VPCOM instructions. Use a combination of custom printing and custom parsing to achieve the same result and more
Previously we had a regular form of the instruction used when the immediate was 0-7. And _alt form that allowed the full 8 bit immediate. Codegen would always use the 0-7 form since the immediate was always checked to be in range. Assembly parsing would use the 0-7 form when a mnemonic like vpcomtrueb was used. If the immediate was specified directly the _alt form was used. The disassembler would prefer to use the 0-7 form instruction when the immediate was in range and the _alt form otherwise. This way disassembly would print the most readable form when possible.
The assembly parsing for things like vpcomtrueb relied on splitting the mnemonic into 3 pieces. A "vpcom" prefix, an immediate representing the "true", and a suffix of "b". The tablegenerated printing code would similarly print a "vpcom" prefix, decode the immediate into a string, and then print "b".
The _alt form on the other hand parsed and printed like any other instruction with no specialness.
With this patch we drop to one form and solve the disassembly printing issue by doing custom printing when the immediate is 0-7. The parsing code has been tweaked to turn "vpcomtrueb" into "vpcomb" and then the immediate for the "true" is inserted either before or after the other operands depending on at&t or intel syntax.
I'd rather not do the custom printing, but I tried using an InstAlias for each possible mnemonic for all 8 immediates for all 16 combinations of element size, signedness, and memory/register. The code emitted into printAliasInstr ended up checking the number of operands, the register class of each operand, and the immediate for all 256 aliases. This was repeated for both the at&t and intel printer. Despite a lot of common checks between all of the aliases, when compiled with clang at least this commonality was not well optimized. Nor do all the checks seem necessary. Since I want to do a similar thing for vcmpps/pd/ss/sd which have 32 immediate values and 3 encoding flavors, 3 register sizes, etc. This didn't seem to scale well for clang binary size. So custom printing seemed a better trade off.
I also considered just using the InstAlias for the matching and not the printing. But that seemed like it would add a lot of extra rows to the matcher table. Especially given that the 32 immediates for vpcmpps have 46 strings associated with them.
Differential Revision: https://reviews.llvm.org/D59398
llvm-svn: 356343
2019-03-18 05:21:37 +08:00
|
|
|
(ins VR128:$src1, VR128:$src2, u8imm:$cc),
|
|
|
|
!strconcat("vpcom", Suffix,
|
|
|
|
"\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"),
|
2018-02-20 11:58:13 +08:00
|
|
|
[(set VR128:$dst,
|
|
|
|
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2),
|
2019-09-20 00:26:14 +08:00
|
|
|
timm:$cc)))]>,
|
2018-05-03 00:25:41 +08:00
|
|
|
XOP_4V, Sched<[sched]>;
|
2018-02-20 11:58:13 +08:00
|
|
|
def mi : IXOPi8<opc, MRMSrcMem, (outs VR128:$dst),
|
[X86] Remove the _alt forms of XOP VPCOM instructions. Use a combination of custom printing and custom parsing to achieve the same result and more
Previously we had a regular form of the instruction used when the immediate was 0-7. And _alt form that allowed the full 8 bit immediate. Codegen would always use the 0-7 form since the immediate was always checked to be in range. Assembly parsing would use the 0-7 form when a mnemonic like vpcomtrueb was used. If the immediate was specified directly the _alt form was used. The disassembler would prefer to use the 0-7 form instruction when the immediate was in range and the _alt form otherwise. This way disassembly would print the most readable form when possible.
The assembly parsing for things like vpcomtrueb relied on splitting the mnemonic into 3 pieces. A "vpcom" prefix, an immediate representing the "true", and a suffix of "b". The tablegenerated printing code would similarly print a "vpcom" prefix, decode the immediate into a string, and then print "b".
The _alt form on the other hand parsed and printed like any other instruction with no specialness.
With this patch we drop to one form and solve the disassembly printing issue by doing custom printing when the immediate is 0-7. The parsing code has been tweaked to turn "vpcomtrueb" into "vpcomb" and then the immediate for the "true" is inserted either before or after the other operands depending on at&t or intel syntax.
I'd rather not do the custom printing, but I tried using an InstAlias for each possible mnemonic for all 8 immediates for all 16 combinations of element size, signedness, and memory/register. The code emitted into printAliasInstr ended up checking the number of operands, the register class of each operand, and the immediate for all 256 aliases. This was repeated for both the at&t and intel printer. Despite a lot of common checks between all of the aliases, when compiled with clang at least this commonality was not well optimized. Nor do all the checks seem necessary. Since I want to do a similar thing for vcmpps/pd/ss/sd which have 32 immediate values and 3 encoding flavors, 3 register sizes, etc. This didn't seem to scale well for clang binary size. So custom printing seemed a better trade off.
I also considered just using the InstAlias for the matching and not the printing. But that seemed like it would add a lot of extra rows to the matcher table. Especially given that the 32 immediates for vpcmpps have 46 strings associated with them.
Differential Revision: https://reviews.llvm.org/D59398
llvm-svn: 356343
2019-03-18 05:21:37 +08:00
|
|
|
(ins VR128:$src1, i128mem:$src2, u8imm:$cc),
|
|
|
|
!strconcat("vpcom", Suffix,
|
|
|
|
"\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"),
|
2018-02-20 11:58:13 +08:00
|
|
|
[(set VR128:$dst,
|
|
|
|
(vt128 (OpNode (vt128 VR128:$src1),
|
2018-10-23 06:14:05 +08:00
|
|
|
(vt128 (load addr:$src2)),
|
2019-09-20 00:26:14 +08:00
|
|
|
timm:$cc)))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP_4V, Sched<[sched.Folded, sched.ReadAfterFold]>;
|
2015-02-13 15:42:25 +08:00
|
|
|
}
|
2011-12-13 03:37:49 +08:00
|
|
|
|
2018-10-23 06:14:05 +08:00
|
|
|
def : Pat<(OpNode (load addr:$src2),
|
2019-09-20 00:26:14 +08:00
|
|
|
(vt128 VR128:$src1), timm:$cc),
|
2018-02-20 11:58:13 +08:00
|
|
|
(!cast<Instruction>(NAME#"mi") VR128:$src1, addr:$src2,
|
2019-09-23 03:49:39 +08:00
|
|
|
(CommuteVPCOMCC timm:$cc))>;
|
2015-02-15 06:40:46 +08:00
|
|
|
}
|
2011-12-13 03:37:49 +08:00
|
|
|
|
2018-05-03 00:25:41 +08:00
|
|
|
defm VPCOMB : xopvpcom<0xCC, "b", X86vpcom, v16i8, SchedWriteVecALU.XMM>;
|
|
|
|
defm VPCOMW : xopvpcom<0xCD, "w", X86vpcom, v8i16, SchedWriteVecALU.XMM>;
|
|
|
|
defm VPCOMD : xopvpcom<0xCE, "d", X86vpcom, v4i32, SchedWriteVecALU.XMM>;
|
|
|
|
defm VPCOMQ : xopvpcom<0xCF, "q", X86vpcom, v2i64, SchedWriteVecALU.XMM>;
|
|
|
|
defm VPCOMUB : xopvpcom<0xEC, "ub", X86vpcomu, v16i8, SchedWriteVecALU.XMM>;
|
|
|
|
defm VPCOMUW : xopvpcom<0xED, "uw", X86vpcomu, v8i16, SchedWriteVecALU.XMM>;
|
|
|
|
defm VPCOMUD : xopvpcom<0xEE, "ud", X86vpcomu, v4i32, SchedWriteVecALU.XMM>;
|
|
|
|
defm VPCOMUQ : xopvpcom<0xEF, "uq", X86vpcomu, v2i64, SchedWriteVecALU.XMM>;
|
2018-02-20 11:58:13 +08:00
|
|
|
|
2016-03-24 19:52:43 +08:00
|
|
|
multiclass xop4op<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
2018-05-03 00:25:41 +08:00
|
|
|
ValueType vt128, X86FoldableSchedWrite sched> {
|
2016-08-22 09:37:19 +08:00
|
|
|
def rrr : IXOPi8Reg<opc, MRMSrcReg, (outs VR128:$dst),
|
2016-03-25 00:31:30 +08:00
|
|
|
(ins VR128:$src1, VR128:$src2, VR128:$src3),
|
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
|
|
|
[(set VR128:$dst,
|
|
|
|
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2),
|
|
|
|
(vt128 VR128:$src3))))]>,
|
2018-05-03 00:25:41 +08:00
|
|
|
XOP_4V, Sched<[sched]>;
|
2016-08-22 15:38:45 +08:00
|
|
|
def rrm : IXOPi8Reg<opc, MRMSrcMemOp4, (outs VR128:$dst),
|
2016-03-25 00:31:30 +08:00
|
|
|
(ins VR128:$src1, VR128:$src2, i128mem:$src3),
|
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
|
|
|
[(set VR128:$dst,
|
|
|
|
(vt128 (OpNode (vt128 VR128:$src1), (vt128 VR128:$src2),
|
2018-10-23 06:14:05 +08:00
|
|
|
(vt128 (load addr:$src3)))))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP_4V, VEX_W, Sched<[sched.Folded, sched.ReadAfterFold, sched.ReadAfterFold]>;
|
2016-08-22 09:37:19 +08:00
|
|
|
def rmr : IXOPi8Reg<opc, MRMSrcMem, (outs VR128:$dst),
|
2016-03-25 00:31:30 +08:00
|
|
|
(ins VR128:$src1, i128mem:$src2, VR128:$src3),
|
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
|
|
|
[(set VR128:$dst,
|
2018-10-23 06:14:05 +08:00
|
|
|
(v16i8 (OpNode (vt128 VR128:$src1), (vt128 (load addr:$src2)),
|
2016-03-25 00:31:30 +08:00
|
|
|
(vt128 VR128:$src3))))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP_4V, Sched<[sched.Folded, sched.ReadAfterFold,
|
2018-03-30 06:03:05 +08:00
|
|
|
// 128mem:$src2
|
|
|
|
ReadDefault, ReadDefault, ReadDefault, ReadDefault,
|
|
|
|
ReadDefault,
|
|
|
|
// VR128:$src3
|
2018-10-06 01:57:29 +08:00
|
|
|
sched.ReadAfterFold]>;
|
2016-03-24 19:52:43 +08:00
|
|
|
// For disassembler
|
|
|
|
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
2016-08-22 15:38:45 +08:00
|
|
|
def rrr_REV : IXOPi8Reg<opc, MRMSrcRegOp4, (outs VR128:$dst),
|
2016-03-25 00:31:30 +08:00
|
|
|
(ins VR128:$src1, VR128:$src2, VR128:$src3),
|
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
2018-05-03 00:25:41 +08:00
|
|
|
[]>, XOP_4V, VEX_W, Sched<[sched]>, FoldGenData<NAME#rrr>;
|
2016-03-24 19:52:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
let ExeDomain = SSEPackedInt in {
|
2018-05-03 00:25:41 +08:00
|
|
|
defm VPPERM : xop4op<0xA3, "vpperm", X86vpperm, v16i8,
|
|
|
|
SchedWriteVarShuffle.XMM>;
|
2016-03-24 19:52:43 +08:00
|
|
|
}
|
|
|
|
|
2011-12-13 03:37:49 +08:00
|
|
|
// Instruction where either second or third source can be memory
|
2017-02-19 05:50:58 +08:00
|
|
|
multiclass xop4op_int<bits<8> opc, string OpcodeStr, RegisterClass RC,
|
2018-05-03 00:25:41 +08:00
|
|
|
X86MemOperand x86memop, ValueType VT,
|
|
|
|
X86FoldableSchedWrite sched> {
|
2017-02-19 05:50:58 +08:00
|
|
|
def rrr : IXOPi8Reg<opc, MRMSrcReg, (outs RC:$dst),
|
|
|
|
(ins RC:$src1, RC:$src2, RC:$src3),
|
2016-03-25 00:31:30 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
2017-02-19 05:50:58 +08:00
|
|
|
[(set RC:$dst, (VT (or (and RC:$src3, RC:$src1),
|
2017-11-21 20:02:18 +08:00
|
|
|
(X86andnp RC:$src3, RC:$src2))))]>, XOP_4V,
|
2018-05-03 00:25:41 +08:00
|
|
|
Sched<[sched]>;
|
2018-10-27 01:21:26 +08:00
|
|
|
// FIXME: This pattern can't match.
|
2017-02-19 05:50:58 +08:00
|
|
|
def rrm : IXOPi8Reg<opc, MRMSrcMemOp4, (outs RC:$dst),
|
|
|
|
(ins RC:$src1, RC:$src2, x86memop:$src3),
|
2016-03-25 00:31:30 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
2017-02-19 05:50:58 +08:00
|
|
|
[(set RC:$dst, (VT (or (and (load addr:$src3), RC:$src1),
|
|
|
|
(X86andnp (load addr:$src3), RC:$src2))))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP_4V, VEX_W, Sched<[sched.Folded, sched.ReadAfterFold, sched.ReadAfterFold]>;
|
2017-02-19 05:50:58 +08:00
|
|
|
def rmr : IXOPi8Reg<opc, MRMSrcMem, (outs RC:$dst),
|
|
|
|
(ins RC:$src1, x86memop:$src2, RC:$src3),
|
2016-03-25 00:31:30 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
2017-02-19 05:50:58 +08:00
|
|
|
[(set RC:$dst, (VT (or (and RC:$src3, RC:$src1),
|
|
|
|
(X86andnp RC:$src3, (load addr:$src2)))))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
XOP_4V, Sched<[sched.Folded, sched.ReadAfterFold,
|
2018-03-30 06:03:05 +08:00
|
|
|
// x86memop:$src2
|
|
|
|
ReadDefault, ReadDefault, ReadDefault, ReadDefault,
|
|
|
|
ReadDefault,
|
|
|
|
// RC::$src3
|
2018-10-06 01:57:29 +08:00
|
|
|
sched.ReadAfterFold]>;
|
2016-02-20 14:20:17 +08:00
|
|
|
// For disassembler
|
|
|
|
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
2017-02-19 05:50:58 +08:00
|
|
|
def rrr_REV : IXOPi8Reg<opc, MRMSrcRegOp4, (outs RC:$dst),
|
|
|
|
(ins RC:$src1, RC:$src2, RC:$src3),
|
2016-03-25 00:31:30 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
|
2018-05-03 00:25:41 +08:00
|
|
|
[]>, XOP_4V, VEX_W, Sched<[sched]>, FoldGenData<NAME#rrr>;
|
2011-12-13 03:37:49 +08:00
|
|
|
}
|
|
|
|
|
2016-03-24 23:28:02 +08:00
|
|
|
let ExeDomain = SSEPackedInt in {
|
2018-05-03 00:25:41 +08:00
|
|
|
defm VPCMOV : xop4op_int<0xA2, "vpcmov", VR128, i128mem, v2i64,
|
|
|
|
SchedWriteShuffle.XMM>;
|
|
|
|
defm VPCMOVY : xop4op_int<0xA2, "vpcmov", VR256, i256mem, v4i64,
|
|
|
|
SchedWriteShuffle.YMM>, VEX_L;
|
2015-11-04 04:27:01 +08:00
|
|
|
}
|
|
|
|
|
2018-10-27 01:21:26 +08:00
|
|
|
let Predicates = [HasXOP] in {
|
|
|
|
def : Pat<(v16i8 (or (and VR128:$src3, VR128:$src1),
|
|
|
|
(X86andnp VR128:$src3, VR128:$src2))),
|
|
|
|
(VPCMOVrrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
|
|
|
def : Pat<(v8i16 (or (and VR128:$src3, VR128:$src1),
|
|
|
|
(X86andnp VR128:$src3, VR128:$src2))),
|
|
|
|
(VPCMOVrrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
|
|
|
def : Pat<(v4i32 (or (and VR128:$src3, VR128:$src1),
|
|
|
|
(X86andnp VR128:$src3, VR128:$src2))),
|
|
|
|
(VPCMOVrrr VR128:$src1, VR128:$src2, VR128:$src3)>;
|
|
|
|
|
|
|
|
def : Pat<(or (and VR128:$src3, VR128:$src1),
|
|
|
|
(X86andnp VR128:$src3, (bc_v16i8 (loadv2i64 addr:$src2)))),
|
|
|
|
(VPCMOVrmr VR128:$src1, addr:$src2, VR128:$src3)>;
|
|
|
|
def : Pat<(or (and VR128:$src3, VR128:$src1),
|
|
|
|
(X86andnp VR128:$src3, (bc_v8i16 (loadv2i64 addr:$src2)))),
|
|
|
|
(VPCMOVrmr VR128:$src1, addr:$src2, VR128:$src3)>;
|
|
|
|
def : Pat<(or (and VR128:$src3, VR128:$src1),
|
|
|
|
(X86andnp VR128:$src3, (bc_v4i32 (loadv2i64 addr:$src2)))),
|
|
|
|
(VPCMOVrmr VR128:$src1, addr:$src2, VR128:$src3)>;
|
|
|
|
|
|
|
|
def : Pat<(v32i8 (or (and VR256:$src3, VR256:$src1),
|
|
|
|
(X86andnp VR256:$src3, VR256:$src2))),
|
|
|
|
(VPCMOVYrrr VR256:$src1, VR256:$src2, VR256:$src3)>;
|
|
|
|
def : Pat<(v16i16 (or (and VR256:$src3, VR256:$src1),
|
|
|
|
(X86andnp VR256:$src3, VR256:$src2))),
|
|
|
|
(VPCMOVYrrr VR256:$src1, VR256:$src2, VR256:$src3)>;
|
|
|
|
def : Pat<(v8i32 (or (and VR256:$src3, VR256:$src1),
|
|
|
|
(X86andnp VR256:$src3, VR256:$src2))),
|
|
|
|
(VPCMOVYrrr VR256:$src1, VR256:$src2, VR256:$src3)>;
|
|
|
|
|
|
|
|
def : Pat<(or (and VR256:$src3, VR256:$src1),
|
|
|
|
(X86andnp VR256:$src3, (bc_v32i8 (loadv4i64 addr:$src2)))),
|
|
|
|
(VPCMOVYrmr VR256:$src1, addr:$src2, VR256:$src3)>;
|
|
|
|
def : Pat<(or (and VR256:$src3, VR256:$src1),
|
|
|
|
(X86andnp VR256:$src3, (bc_v16i16 (loadv4i64 addr:$src2)))),
|
|
|
|
(VPCMOVYrmr VR256:$src1, addr:$src2, VR256:$src3)>;
|
|
|
|
def : Pat<(or (and VR256:$src3, VR256:$src1),
|
|
|
|
(X86andnp VR256:$src3, (bc_v8i32 (loadv4i64 addr:$src2)))),
|
|
|
|
(VPCMOVYrmr VR256:$src1, addr:$src2, VR256:$src3)>;
|
|
|
|
}
|
|
|
|
|
2017-02-19 06:53:43 +08:00
|
|
|
multiclass xop_vpermil2<bits<8> Opc, string OpcodeStr, RegisterClass RC,
|
|
|
|
X86MemOperand intmemop, X86MemOperand fpmemop,
|
2018-05-03 00:25:41 +08:00
|
|
|
ValueType VT, PatFrag FPLdFrag, PatFrag IntLdFrag,
|
|
|
|
X86FoldableSchedWrite sched> {
|
2017-02-19 06:53:43 +08:00
|
|
|
def rr : IXOP5<Opc, MRMSrcReg, (outs RC:$dst),
|
2019-08-07 13:34:27 +08:00
|
|
|
(ins RC:$src1, RC:$src2, RC:$src3, u4imm:$src4),
|
2011-12-13 03:37:49 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
2017-02-19 06:53:43 +08:00
|
|
|
[(set RC:$dst,
|
2019-09-20 00:26:14 +08:00
|
|
|
(VT (X86vpermil2 RC:$src1, RC:$src2, RC:$src3, (i8 timm:$src4))))]>,
|
2018-05-03 00:25:41 +08:00
|
|
|
Sched<[sched]>;
|
2017-02-19 06:53:43 +08:00
|
|
|
def rm : IXOP5<Opc, MRMSrcMemOp4, (outs RC:$dst),
|
2019-08-07 13:34:27 +08:00
|
|
|
(ins RC:$src1, RC:$src2, intmemop:$src3, u4imm:$src4),
|
2011-12-13 03:37:49 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
2017-02-19 06:53:43 +08:00
|
|
|
[(set RC:$dst,
|
2018-10-23 06:14:05 +08:00
|
|
|
(VT (X86vpermil2 RC:$src1, RC:$src2, (IntLdFrag addr:$src3),
|
2019-09-20 00:26:14 +08:00
|
|
|
(i8 timm:$src4))))]>, VEX_W,
|
2018-10-06 01:57:29 +08:00
|
|
|
Sched<[sched.Folded, sched.ReadAfterFold, sched.ReadAfterFold]>;
|
2017-02-19 06:53:43 +08:00
|
|
|
def mr : IXOP5<Opc, MRMSrcMem, (outs RC:$dst),
|
2019-08-07 13:34:27 +08:00
|
|
|
(ins RC:$src1, fpmemop:$src2, RC:$src3, u4imm:$src4),
|
2011-12-13 03:37:49 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
2017-02-19 06:53:43 +08:00
|
|
|
[(set RC:$dst,
|
|
|
|
(VT (X86vpermil2 RC:$src1, (FPLdFrag addr:$src2),
|
2019-09-20 00:26:14 +08:00
|
|
|
RC:$src3, (i8 timm:$src4))))]>,
|
2018-10-06 01:57:29 +08:00
|
|
|
Sched<[sched.Folded, sched.ReadAfterFold,
|
2018-03-30 06:03:05 +08:00
|
|
|
// fpmemop:$src2
|
|
|
|
ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault,
|
|
|
|
// RC:$src3
|
2018-10-06 01:57:29 +08:00
|
|
|
sched.ReadAfterFold]>;
|
2016-02-20 14:20:17 +08:00
|
|
|
// For disassembler
|
|
|
|
let isCodeGenOnly = 1, ForceDisassemble = 1, hasSideEffects = 0 in
|
2017-02-19 06:53:43 +08:00
|
|
|
def rr_REV : IXOP5<Opc, MRMSrcRegOp4, (outs RC:$dst),
|
2019-08-07 13:34:27 +08:00
|
|
|
(ins RC:$src1, RC:$src2, RC:$src3, u4imm:$src4),
|
2016-02-20 14:20:17 +08:00
|
|
|
!strconcat(OpcodeStr,
|
|
|
|
"\t{$src4, $src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3, $src4}"),
|
2018-05-03 00:25:41 +08:00
|
|
|
[]>, VEX_W, Sched<[sched]>, FoldGenData<NAME#rr>;
|
2011-12-13 03:37:49 +08:00
|
|
|
}
|
|
|
|
|
2017-02-19 06:53:43 +08:00
|
|
|
let ExeDomain = SSEPackedDouble in {
|
|
|
|
defm VPERMIL2PD : xop_vpermil2<0x49, "vpermil2pd", VR128, i128mem, f128mem,
|
2018-05-03 00:25:41 +08:00
|
|
|
v2f64, loadv2f64, loadv2i64,
|
|
|
|
SchedWriteFVarShuffle.XMM>;
|
2017-02-19 06:53:43 +08:00
|
|
|
defm VPERMIL2PDY : xop_vpermil2<0x49, "vpermil2pd", VR256, i256mem, f256mem,
|
2018-05-03 00:25:41 +08:00
|
|
|
v4f64, loadv4f64, loadv4i64,
|
|
|
|
SchedWriteFVarShuffle.YMM>, VEX_L;
|
2017-02-19 06:53:43 +08:00
|
|
|
}
|
2015-02-15 06:40:46 +08:00
|
|
|
|
2017-02-19 06:53:43 +08:00
|
|
|
let ExeDomain = SSEPackedSingle in {
|
|
|
|
defm VPERMIL2PS : xop_vpermil2<0x48, "vpermil2ps", VR128, i128mem, f128mem,
|
2018-10-23 06:14:05 +08:00
|
|
|
v4f32, loadv4f32, loadv4i32,
|
2018-05-03 00:25:41 +08:00
|
|
|
SchedWriteFVarShuffle.XMM>;
|
2017-02-19 06:53:43 +08:00
|
|
|
defm VPERMIL2PSY : xop_vpermil2<0x48, "vpermil2ps", VR256, i256mem, f256mem,
|
2018-10-23 06:14:05 +08:00
|
|
|
v8f32, loadv8f32, loadv8i32,
|
2018-05-03 00:25:41 +08:00
|
|
|
SchedWriteFVarShuffle.YMM>, VEX_L;
|
2017-02-19 06:53:43 +08:00
|
|
|
}
|
2012-01-11 23:20:20 +08:00
|
|
|
|