1//===-- RISCVInstrInfoZvk.td - RISC-V 'Zvk' instructions -------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the RISC-V instructions from the standard 'Zvk',
10// Vector Cryptography Instructions extension, version 1.0.0-rc1.
11//
12//===----------------------------------------------------------------------===//
13
14//===----------------------------------------------------------------------===//
15// Operand and SDNode transformation definitions.
16//===----------------------------------------------------------------------===//
17
18def RnumArg_0_7 : AsmOperandClass {
19  let Name = "RnumArg_0_7";
20  let RenderMethod = "addImmOperands";
21  let DiagnosticType = "InvalidRnumArg_0_7";
22}
23
24def RnumArg_1_10 : AsmOperandClass {
25  let Name = "RnumArg_1_10";
26  let RenderMethod = "addImmOperands";
27  let DiagnosticType = "InvalidRnumArg_1_10";
28}
29
30def RnumArg_2_14 : AsmOperandClass {
31  let Name = "RnumArg_2_14";
32  let RenderMethod = "addImmOperands";
33  let DiagnosticType = "InvalidRnumArg_2_14";
34}
35
36def rnum_0_7 : Operand<XLenVT>, ImmLeaf<XLenVT,
37                                         [{return (0 <= Imm && Imm <= 7);}]> {
38  let ParserMatchClass = RnumArg_0_7;
39  let DecoderMethod = "decodeUImmOperand<5>";
40  let OperandType = "OPERAND_RVKRNUM_0_7";
41  let OperandNamespace = "RISCVOp";
42}
43
44def rnum_1_10 : Operand<XLenVT>, ImmLeaf<XLenVT,
45                                         [{return (1 <= Imm && Imm <= 10);}]> {
46  let ParserMatchClass = RnumArg_1_10;
47  let DecoderMethod = "decodeUImmOperand<5>";
48  let OperandType = "OPERAND_RVKRNUM_1_10";
49  let OperandNamespace = "RISCVOp";
50}
51
52def rnum_2_14 : Operand<XLenVT>, ImmLeaf<XLenVT,
53                                         [{return (2 <= Imm && Imm <= 14);}]> {
54  let ParserMatchClass = RnumArg_2_14;
55  let DecoderMethod = "decodeUImmOperand<5>";
56  let OperandType = "OPERAND_RVKRNUM_2_14";
57  let OperandNamespace = "RISCVOp";
58}
59
60//===----------------------------------------------------------------------===//
61// Instruction class templates
62//===----------------------------------------------------------------------===//
63
64let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
65multiclass VCLMUL_MV_V_X<string opcodestr, bits<6> funct6> {
66  def V  : VALUVV<funct6, OPMVV, opcodestr # "." # "vv">,
67           Sched<[WriteVIALUV_WorstCase, ReadVIALUV_WorstCase,
68                  ReadVIALUV_WorstCase, ReadVMask]>;
69  def X  : VALUVX<funct6, OPMVX, opcodestr # "." # "vx">,
70           Sched<[WriteVIALUX_WorstCase, ReadVIALUV_WorstCase,
71                  ReadVIALUX_WorstCase, ReadVMask]>;
72}
73
74class RVInstIVI_VROR<bits<6> funct6, dag outs, dag ins, string opcodestr,
75                     string argstr>
76    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
77  bits<5> vs2;
78  bits<6> imm;
79  bits<5> vd;
80  bit vm;
81
82  let Inst{31-27} = funct6{5-1};
83  let Inst{26} = imm{5};
84  let Inst{25} = vm;
85  let Inst{24-20} = vs2;
86  let Inst{19-15} = imm{4-0};
87  let Inst{14-12} = OPIVI.Value;
88  let Inst{11-7} = vd;
89  let Inst{6-0} = OPC_OP_V.Value;
90
91  let Uses = [VTYPE, VL];
92  let RVVConstraint = VMConstraint;
93}
94
95multiclass VROR_IV_V_X_I<string opcodestr, bits<6> funct6>
96    : VALU_IV_V_X<opcodestr, funct6> {
97  def I : RVInstIVI_VROR<funct6, (outs VR:$vd),
98              (ins VR:$vs2, uimm6:$imm, VMaskOp:$vm),
99              opcodestr # ".vi", "$vd, $vs2, $imm$vm">,
100         Sched<[WriteVIALUI_WorstCase, ReadVIALUV_WorstCase,
101                ReadVMask]>;
102}
103
104// op vd, vs2, vs1
105class PALUVVNoVm<bits<6> funct6, RISCVVFormat opv, string opcodestr>
106    : VALUVVNoVm<funct6, opv, opcodestr> {
107  let Inst{6-0} = OPC_OP_P.Value;
108}
109
110// op vd, vs2, imm, vm
111class PALUVINoVm<bits<6> funct6, string opcodestr, Operand optype = simm5>
112    : VALUVINoVm<funct6, opcodestr, optype> {
113  let Inst{6-0} = OPC_OP_P.Value;
114  let Inst{14-12} = OPMVV.Value;
115}
116
117// op vd, vs2 (use vs1 as instruction encoding)
118class PALUVs2NoVm<bits<6> funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr>
119    : VALUVs2NoVm<funct6, vs1, opv, opcodestr> {
120  let Inst{6-0} = OPC_OP_P.Value;
121}
122
123multiclass VAES_MV_V_S<bits<6> funct6_vv, bits<6> funct6_vs, bits<5> vs1,
124                         RISCVVFormat opv, string opcodestr> {
125  def NAME # _VV : PALUVs2NoVm<funct6_vv, vs1, opv, opcodestr # ".vv">;
126  def NAME # _VS : PALUVs2NoVm<funct6_vs, vs1, opv, opcodestr # ".vs">;
127}
128
129// vaeskf1.vi and vaeskf2.vi uses different opcode and format, we need
130// to customize one for them.
131class VAESKF_MV_I<bits<6> funct6, string opcodestr, Operand optype>
132    : VALUVINoVm<funct6, opcodestr, optype> {
133  let Inst{6-0} = OPC_OP_P.Value;
134  let Inst{14-12} = OPMVV.Value;
135}
136} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
137
138//===----------------------------------------------------------------------===//
139// Instructions
140//===----------------------------------------------------------------------===//
141
142let Predicates = [HasStdExtZvbb] in {
143  defm VANDN_V  : VALU_IV_V_X<"vandn", 0b000001>;
144  def  VBREV8_V : VALUVs2<0b010010, 0b01000, OPMVV, "vbrev8.v">;
145  def  VBREV_V  : VALUVs2<0b010010, 0b01010, OPMVV, "vbrev.v">;
146  def  VCLZ_V   : VALUVs2<0b010010, 0b01100, OPMVV, "vclz.v">;
147  def  VCPOP_V  : VALUVs2<0b010010, 0b01110, OPMVV, "vcpop.v">;
148  def  VCTZ_V   : VALUVs2<0b010010, 0b01101, OPMVV, "vctz.v">;
149  def  VREV8_V  : VALUVs2<0b010010, 0b01001, OPMVV, "vrev8.v">;
150  defm VROL_V   : VALU_IV_V_X<"vrol", 0b010101>;
151  defm VROR_V   : VROR_IV_V_X_I<"vror", 0b010100>;
152  let Constraints = "@earlyclobber $vd", RVVConstraint = WidenV in
153  defm VWSLL_V  : VSHT_IV_V_X_I<"vwsll", 0b110101>;
154} // Predicates = [HasStdExtZvbb]
155
156let Predicates = [HasStdExtZvbc] in {
157  defm VCLMUL_V  : VCLMUL_MV_V_X<"vclmul", 0b001100>;
158  defm VCLMULH_V : VCLMUL_MV_V_X<"vclmulh", 0b001101>;
159} // Predicates = [HasStdExtZvbc]
160
161let Predicates = [HasStdExtZvkg], RVVConstraint = NoConstraint in {
162  def VGHSH_VV : PALUVVNoVm<0b101100, OPMVV, "vghsh.vv">;
163  def VGMUL_VV : PALUVs2NoVm<0b101000, 0b10001, OPMVV, "vgmul.vv">;
164} // Predicates = [HasStdExtZvkg]
165
166let Predicates = [HasStdExtZvknha], RVVConstraint = NoConstraint in {
167  def VSHA2CH_VV : PALUVVNoVm<0b101110, OPMVV, "vsha2ch.vv">;
168  def VSHA2CL_VV : PALUVVNoVm<0b101111, OPMVV, "vsha2cl.vv">;
169  def VSHA2MS_VV : PALUVVNoVm<0b101101, OPMVV, "vsha2ms.vv">;
170} // Predicates = [HasStdExtZvknha]
171
172let Predicates = [HasStdExtZvkned], RVVConstraint = NoConstraint in {
173  defm VAESDF     : VAES_MV_V_S<0b101000, 0b101001, 0b00001, OPMVV, "vaesdf">;
174  defm VAESDM     : VAES_MV_V_S<0b101000, 0b101001, 0b00000, OPMVV, "vaesdm">;
175  defm VAESEF     : VAES_MV_V_S<0b101000, 0b101001, 0b00011, OPMVV, "vaesef">;
176  defm VAESEM     : VAES_MV_V_S<0b101000, 0b101001, 0b00010, OPMVV, "vaesem">;
177  def  VAESKF1_VI : VAESKF_MV_I<0b100010, "vaeskf1.vi", uimm5>;
178  def  VAESKF2_VI : VAESKF_MV_I<0b101010, "vaeskf2.vi", uimm5>;
179  def  VAESZ_VS   : PALUVs2NoVm<0b101001, 0b00111, OPMVV, "vaesz.vs">;
180} // Predicates = [HasStdExtZvkned]
181
182let Predicates = [HasStdExtZvksed], RVVConstraint = NoConstraint in {
183  def  VSM4K_VI : PALUVINoVm<0b100001, "vsm4k.vi", uimm5>;
184  defm VSM4R    : VAES_MV_V_S<0b101000, 0b101001, 0b10000, OPMVV, "vsm4r">;
185} // Predicates = [HasStdExtZvksed]
186
187let Predicates = [HasStdExtZvksh], RVVConstraint = NoConstraint in {
188  def VSM3C_VI  : PALUVINoVm<0b101011, "vsm3c.vi", uimm5>;
189  def VSM3ME_VV : PALUVVNoVm<0b100000, OPMVV, "vsm3me.vv">;
190} // Predicates = [HasStdExtZvksh]
191
192//===----------------------------------------------------------------------===//
193// Pseudo instructions
194//===----------------------------------------------------------------------===//
195
196defm PseudoVANDN : VPseudoVALU_VV_VX;
197
198multiclass VPseudoUnaryV_V {
199  foreach m = MxList in {
200    let VLMul = m.value in {
201      def "_V_" # m.MX : VPseudoUnaryNoMask<m.vrclass, m.vrclass>;
202      def "_V_" # m.MX # "_MASK" : VPseudoUnaryMask<m.vrclass, m.vrclass>,
203                                   RISCVMaskedPseudo<MaskIdx=2>;
204    }
205  }
206}
207
208defm PseudoVBREV : VPseudoUnaryV_V;
209defm PseudoVREV8 : VPseudoUnaryV_V;
210defm PseudoVCLZ : VPseudoUnaryV_V;
211defm PseudoVCTZ : VPseudoUnaryV_V;
212defm PseudoVCPOP : VPseudoUnaryV_V;
213
214defm PseudoVROL : VPseudoVALU_VV_VX;
215defm PseudoVROR : VPseudoVALU_VV_VX_VI<uimm6>;
216
217//===----------------------------------------------------------------------===//
218// SDNode patterns
219//===----------------------------------------------------------------------===//
220
221multiclass VPatUnarySDNode_V<SDPatternOperator op, string instruction_name> {
222  foreach vti = AllIntegerVectors in {
223    let Predicates = !listconcat([HasStdExtZvbb],
224                                 GetVTypePredicates<vti>.Predicates) in {
225      def : Pat<(vti.Vector (op (vti.Vector vti.RegClass:$rs1))),
226                (!cast<Instruction>(instruction_name#"_V_"#vti.LMul.MX)
227                   (vti.Vector (IMPLICIT_DEF)),
228                   vti.RegClass:$rs1,
229                   vti.AVL, vti.Log2SEW, TA_MA)>;
230    }
231  }
232}
233
234// Helpers for detecting splats since we preprocess splat_vector to vmv.v.x
235// This should match the logic in RISCVDAGToDAGISel::selectVSplat
236def riscv_splat_vector : PatFrag<(ops node:$rs1),
237                                 (riscv_vmv_v_x_vl undef, node:$rs1, srcvalue)>;
238def riscv_vnot : PatFrag<(ops node:$rs1), (xor node:$rs1,
239                                               (riscv_splat_vector -1))>;
240
241foreach vti = AllIntegerVectors in {
242  let Predicates = !listconcat([HasStdExtZvbb],
243                               GetVTypePredicates<vti>.Predicates) in {
244    def : Pat<(vti.Vector (and (riscv_vnot vti.RegClass:$rs1),
245                               vti.RegClass:$rs2)),
246              (!cast<Instruction>("PseudoVANDN_VV_"#vti.LMul.MX)
247                 (vti.Vector (IMPLICIT_DEF)),
248                 vti.RegClass:$rs2,
249                 vti.RegClass:$rs1,
250                 vti.AVL, vti.Log2SEW, TA_MA)>;
251    def : Pat<(vti.Vector (and (riscv_splat_vector
252                                 (not vti.ScalarRegClass:$rs1)),
253                               vti.RegClass:$rs2)),
254              (!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX)
255                 (vti.Vector (IMPLICIT_DEF)),
256                 vti.RegClass:$rs2,
257                 vti.ScalarRegClass:$rs1,
258                 vti.AVL, vti.Log2SEW, TA_MA)>;
259  }
260}
261
262defm : VPatUnarySDNode_V<bitreverse, "PseudoVBREV">;
263defm : VPatUnarySDNode_V<bswap, "PseudoVREV8">;
264defm : VPatUnarySDNode_V<ctlz, "PseudoVCLZ">;
265defm : VPatUnarySDNode_V<cttz, "PseudoVCTZ">;
266defm : VPatUnarySDNode_V<ctpop, "PseudoVCPOP">;
267
268defm : VPatBinarySDNode_VV_VX<rotl, "PseudoVROL">;
269
270def NegImm64 : SDNodeXForm<imm, [{
271  return CurDAG->getTargetConstant(0x3f & (64 - N->getZExtValue()), SDLoc(N),
272                                   N->getValueType(0));
273}]>;
274
275// Although there is no vrol.vi, an immediate rotate left can be achieved by
276// negating the immediate in vror.vi
277foreach vti = AllIntegerVectors in {
278  let Predicates = !listconcat([HasStdExtZvbb],
279                               GetVTypePredicates<vti>.Predicates) in {
280    def : Pat<(vti.Vector (rotl vti.RegClass:$rs2,
281                                (vti.Vector (SplatPat_uimm6 uimm6:$rs1)))),
282              (!cast<Instruction>("PseudoVROR_VI_"#vti.LMul.MX)
283                 (vti.Vector (IMPLICIT_DEF)),
284                 vti.RegClass:$rs2,
285                 (NegImm64 uimm6:$rs1),
286                 vti.AVL, vti.Log2SEW, TA_MA)>;
287  }
288}
289defm : VPatBinarySDNode_VV_VX_VI<rotr, "PseudoVROR", uimm6>;
290
291//===----------------------------------------------------------------------===//
292// VL patterns
293//===----------------------------------------------------------------------===//
294
295multiclass VPatUnaryVL_V<SDPatternOperator op, string instruction_name> {
296  foreach vti = AllIntegerVectors in {
297    let Predicates = !listconcat([HasStdExtZvbb],
298                                 GetVTypePredicates<vti>.Predicates) in {
299      def : Pat<(vti.Vector (op (vti.Vector vti.RegClass:$rs1),
300                                (vti.Vector vti.RegClass:$merge),
301                                (vti.Mask V0),
302                                VLOpFrag)),
303                (!cast<Instruction>(instruction_name#"_V_"#vti.LMul.MX#"_MASK")
304                   vti.RegClass:$merge,
305                   vti.RegClass:$rs1,
306                   (vti.Mask V0),
307                   GPR:$vl,
308                   vti.Log2SEW,
309                   TAIL_AGNOSTIC)>;
310    }
311  }
312}
313
314foreach vti = AllIntegerVectors in {
315  let Predicates = !listconcat([HasStdExtZvbb],
316                               GetVTypePredicates<vti>.Predicates) in {
317    def : Pat<(vti.Vector (riscv_and_vl (riscv_xor_vl
318                                           (vti.Vector vti.RegClass:$rs1),
319                                           (riscv_splat_vector -1),
320                                           (vti.Vector vti.RegClass:$merge),
321                                           (vti.Mask V0),
322                                           VLOpFrag),
323                                        (vti.Vector vti.RegClass:$rs2),
324                                        (vti.Vector vti.RegClass:$merge),
325                                        (vti.Mask V0),
326                                        VLOpFrag)),
327              (!cast<Instruction>("PseudoVANDN_VV_"#vti.LMul.MX#"_MASK")
328                 vti.RegClass:$merge,
329                 vti.RegClass:$rs2,
330                 vti.RegClass:$rs1,
331                 (vti.Mask V0),
332                 GPR:$vl,
333                 vti.Log2SEW,
334                 TAIL_AGNOSTIC)>;
335
336    def : Pat<(vti.Vector (riscv_and_vl (riscv_splat_vector
337                                           (not vti.ScalarRegClass:$rs1)),
338                                        (vti.Vector vti.RegClass:$rs2),
339                                        (vti.Vector vti.RegClass:$merge),
340                                        (vti.Mask V0),
341                                        VLOpFrag)),
342              (!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX#"_MASK")
343                 vti.RegClass:$merge,
344                 vti.RegClass:$rs2,
345                 vti.ScalarRegClass:$rs1,
346                 (vti.Mask V0),
347                 GPR:$vl,
348                 vti.Log2SEW,
349                 TAIL_AGNOSTIC)>;
350  }
351}
352
353defm : VPatUnaryVL_V<riscv_bitreverse_vl, "PseudoVBREV">;
354defm : VPatUnaryVL_V<riscv_bswap_vl, "PseudoVREV8">;
355defm : VPatUnaryVL_V<riscv_ctlz_vl, "PseudoVCLZ">;
356defm : VPatUnaryVL_V<riscv_cttz_vl, "PseudoVCTZ">;
357defm : VPatUnaryVL_V<riscv_ctpop_vl, "PseudoVCPOP">;
358