1//===- RISCVInstrInfoVSDPatterns.td - RVV SDNode patterns --*- 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 contains the required infrastructure and SDNode patterns to
10/// support code generation for the standard 'V' (Vector) extension, version
11/// 0.10.  This version is still experimental as the 'V' extension hasn't been
12/// ratified yet.
13///
14/// This file is included from and depends upon RISCVInstrInfoVPseudos.td
15///
16/// Note: the patterns for RVV intrinsics are found in
17/// RISCVInstrInfoVPseudos.td.
18///
19//===----------------------------------------------------------------------===//
20
21//===----------------------------------------------------------------------===//
22// Helpers to define the SDNode patterns.
23//===----------------------------------------------------------------------===//
24
25def SDTSplatI64 : SDTypeProfile<1, 1, [
26  SDTCVecEltisVT<0, i64>, SDTCisVT<1, i32>
27]>;
28
29def rv32_splat_i64 : SDNode<"RISCVISD::SPLAT_VECTOR_I64", SDTSplatI64>;
30
31def riscv_trunc_vector : SDNode<"RISCVISD::TRUNCATE_VECTOR",
32                                SDTypeProfile<1, 1,
33                                 [SDTCisVec<0>, SDTCisVec<1>]>>;
34
35// Penalize the generic form with Complexity=1 to give the simm5/uimm5 variants
36// precedence
37def SplatPat       : ComplexPattern<vAny, 1, "selectVSplat", [], [], 1>;
38
39def SplatPat_simm5 : ComplexPattern<vAny, 1, "selectVSplatSimm5", []>;
40def SplatPat_uimm5 : ComplexPattern<vAny, 1, "selectVSplatUimm5", []>;
41
42class SwapHelper<dag Prefix, dag A, dag B, dag Suffix, bit swap> {
43   dag Value = !con(Prefix, !if(swap, B, A), !if(swap, A, B), Suffix);
44}
45
46multiclass VPatUSLoadStoreSDNode<LLVMType type,
47                                 LLVMType mask_type,
48                                 int sew,
49                                 LMULInfo vlmul,
50                                 OutPatFrag avl,
51                                 RegisterClass reg_rs1,
52                                 VReg reg_class>
53{
54  defvar load_instr = !cast<Instruction>("PseudoVLE"#sew#"_V_"#vlmul.MX);
55  defvar store_instr = !cast<Instruction>("PseudoVSE"#sew#"_V_"#vlmul.MX);
56  // Load
57  def : Pat<(type (load reg_rs1:$rs1)),
58            (load_instr reg_rs1:$rs1, avl, sew)>;
59  // Store
60  def : Pat<(store type:$rs2, reg_rs1:$rs1),
61            (store_instr reg_class:$rs2, reg_rs1:$rs1, avl, sew)>;
62}
63
64multiclass VPatUSLoadStoreSDNodes<RegisterClass reg_rs1> {
65  foreach vti = AllVectors in
66    defm "" : VPatUSLoadStoreSDNode<vti.Vector, vti.Mask, vti.SEW, vti.LMul,
67                                    vti.AVL, reg_rs1, vti.RegClass>;
68}
69
70class VPatBinarySDNode_VV<SDNode vop,
71                          string instruction_name,
72                          ValueType result_type,
73                          ValueType op_type,
74                          ValueType mask_type,
75                          int sew,
76                          LMULInfo vlmul,
77                          OutPatFrag avl,
78                          VReg RetClass,
79                          VReg op_reg_class> :
80    Pat<(result_type (vop
81                     (op_type op_reg_class:$rs1),
82                     (op_type op_reg_class:$rs2))),
83        (!cast<Instruction>(instruction_name#"_VV_"# vlmul.MX)
84                     op_reg_class:$rs1,
85                     op_reg_class:$rs2,
86                     avl, sew)>;
87
88class VPatBinarySDNode_XI<SDNode vop,
89                          string instruction_name,
90                          string suffix,
91                          ValueType result_type,
92                          ValueType vop_type,
93                          ValueType xop_type,
94                          ValueType mask_type,
95                          int sew,
96                          LMULInfo vlmul,
97                          OutPatFrag avl,
98                          VReg RetClass,
99                          VReg vop_reg_class,
100                          ComplexPattern SplatPatKind,
101                          DAGOperand xop_kind> :
102    Pat<(result_type (vop
103                     (vop_type vop_reg_class:$rs1),
104                     (vop_type (SplatPatKind xop_kind:$rs2)))),
105        (!cast<Instruction>(instruction_name#_#suffix#_# vlmul.MX)
106                     vop_reg_class:$rs1,
107                     xop_kind:$rs2,
108                     avl, sew)>;
109
110multiclass VPatBinarySDNode_VV_VX<SDNode vop, string instruction_name>
111{
112  foreach vti = AllIntegerVectors in {
113    def : VPatBinarySDNode_VV<vop, instruction_name,
114                              vti.Vector, vti.Vector, vti.Mask, vti.SEW,
115                              vti.LMul, vti.AVL, vti.RegClass, vti.RegClass>;
116    def : VPatBinarySDNode_XI<vop, instruction_name, "VX",
117                              vti.Vector, vti.Vector, XLenVT, vti.Mask, vti.SEW,
118                              vti.LMul, vti.AVL, vti.RegClass, vti.RegClass,
119                              SplatPat, GPR>;
120  }
121}
122
123multiclass VPatBinarySDNode_VV_VX_VI<SDNode vop, string instruction_name,
124                                     Operand ImmType = simm5>
125{
126  foreach vti = AllIntegerVectors in {
127    def : VPatBinarySDNode_VV<vop, instruction_name,
128                              vti.Vector, vti.Vector, vti.Mask, vti.SEW,
129                              vti.LMul, vti.AVL, vti.RegClass, vti.RegClass>;
130    def : VPatBinarySDNode_XI<vop, instruction_name, "VX",
131                              vti.Vector, vti.Vector, XLenVT, vti.Mask, vti.SEW,
132                              vti.LMul, vti.AVL, vti.RegClass, vti.RegClass,
133                              SplatPat, GPR>;
134    def : VPatBinarySDNode_XI<vop, instruction_name, "VI",
135                              vti.Vector, vti.Vector, XLenVT, vti.Mask, vti.SEW,
136                              vti.LMul, vti.AVL, vti.RegClass, vti.RegClass,
137                              !cast<ComplexPattern>(SplatPat#_#ImmType),
138                              ImmType>;
139  }
140}
141
142class VPatBinarySDNode_VF<SDNode vop,
143                          string instruction_name,
144                          ValueType result_type,
145                          ValueType vop_type,
146                          ValueType xop_type,
147                          ValueType mask_type,
148                          int sew,
149                          LMULInfo vlmul,
150                          OutPatFrag avl,
151                          VReg RetClass,
152                          VReg vop_reg_class,
153                          DAGOperand xop_kind> :
154    Pat<(result_type (vop (vop_type vop_reg_class:$rs1),
155                          (vop_type (splat_vector xop_kind:$rs2)))),
156        (!cast<Instruction>(instruction_name#"_"#vlmul.MX)
157                     vop_reg_class:$rs1,
158                     (xop_type xop_kind:$rs2),
159                     avl, sew)>;
160
161multiclass VPatBinaryFPSDNode_VV_VF<SDNode vop, string instruction_name> {
162  foreach vti = AllFloatVectors in {
163    def : VPatBinarySDNode_VV<vop, instruction_name,
164                              vti.Vector, vti.Vector, vti.Mask, vti.SEW,
165                              vti.LMul, vti.AVL, vti.RegClass, vti.RegClass>;
166    def : VPatBinarySDNode_VF<vop, instruction_name#"_V"#vti.ScalarSuffix,
167                              vti.Vector, vti.Vector, vti.Scalar, vti.Mask,
168                              vti.SEW, vti.LMul, vti.AVL, vti.RegClass, vti.RegClass,
169                              vti.ScalarRegClass>;
170  }
171}
172
173multiclass VPatBinaryFPSDNode_R_VF<SDNode vop, string instruction_name> {
174  foreach fvti = AllFloatVectors in
175    def : Pat<(fvti.Vector (vop (fvti.Vector (splat_vector fvti.Scalar:$rs2)),
176                                (fvti.Vector fvti.RegClass:$rs1))),
177              (!cast<Instruction>(instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
178                           fvti.RegClass:$rs1,
179                           (fvti.Scalar fvti.ScalarRegClass:$rs2),
180                           fvti.AVL, fvti.SEW)>;
181}
182
183multiclass VPatIntegerSetCCSDNode_VV<CondCode cc,
184                                     string instruction_name,
185                                     bit swap = 0> {
186  foreach vti = AllIntegerVectors in {
187    defvar instruction = !cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX);
188    def : Pat<(vti.Mask (setcc (vti.Vector vti.RegClass:$rs1),
189                               (vti.Vector vti.RegClass:$rs2), cc)),
190              SwapHelper<(instruction),
191                         (instruction vti.RegClass:$rs1),
192                         (instruction vti.RegClass:$rs2),
193                         (instruction vti.AVL, vti.SEW),
194                         swap>.Value>;
195  }
196}
197
198multiclass VPatIntegerSetCCSDNode_XI<CondCode cc,
199                                     string instruction_name,
200                                     string kind,
201                                     ComplexPattern SplatPatKind,
202                                     DAGOperand xop_kind,
203                                     bit swap = 0> {
204  foreach vti = AllIntegerVectors in {
205    defvar instruction = !cast<Instruction>(instruction_name#_#kind#_#vti.LMul.MX);
206    def : Pat<(vti.Mask (setcc (vti.Vector vti.RegClass:$rs1),
207                               (vti.Vector (SplatPatKind xop_kind:$rs2)), cc)),
208              SwapHelper<(instruction),
209                         (instruction vti.RegClass:$rs1),
210                         (instruction xop_kind:$rs2),
211                         (instruction vti.AVL, vti.SEW),
212                         swap>.Value>;
213  }
214}
215
216multiclass VPatIntegerSetCCSDNode_VV_VX_VI<CondCode cc,
217                                           string instruction_name,
218                                           bit swap = 0> {
219  defm : VPatIntegerSetCCSDNode_VV<cc, instruction_name, swap>;
220  defm : VPatIntegerSetCCSDNode_XI<cc, instruction_name, "VX",
221                                   SplatPat, GPR, swap>;
222  defm : VPatIntegerSetCCSDNode_XI<cc, instruction_name, "VI",
223                                   SplatPat_simm5, simm5, swap>;
224}
225
226multiclass VPatIntegerSetCCSDNode_VV_VX<CondCode cc,
227                                        string instruction_name,
228                                        bit swap = 0> {
229  defm : VPatIntegerSetCCSDNode_VV<cc, instruction_name, swap>;
230  defm : VPatIntegerSetCCSDNode_XI<cc, instruction_name, "VX",
231                                   SplatPat, GPR, swap>;
232}
233
234multiclass VPatIntegerSetCCSDNode_VX_VI<CondCode cc,
235                                        string instruction_name,
236                                        bit swap = 0> {
237  defm : VPatIntegerSetCCSDNode_XI<cc, instruction_name, "VX",
238                                   SplatPat, GPR, swap>;
239  defm : VPatIntegerSetCCSDNode_XI<cc, instruction_name, "VI",
240                                   SplatPat_simm5, simm5, swap>;
241}
242
243multiclass VPatFPSetCCSDNode_VV<CondCode cc, string instruction_name> {
244  foreach fvti = AllFloatVectors in
245    def : Pat<(fvti.Mask (setcc (fvti.Vector fvti.RegClass:$rs1),
246                                (fvti.Vector fvti.RegClass:$rs2),
247                                cc)),
248              (!cast<Instruction>(instruction_name#"_VV_"#fvti.LMul.MX)
249                  fvti.RegClass:$rs1, fvti.RegClass:$rs2, fvti.AVL, fvti.SEW)>;
250}
251
252multiclass VPatFPSetCCSDNode_VF<CondCode cc, string instruction_name> {
253  foreach fvti = AllFloatVectors in
254    def : Pat<(fvti.Mask (setcc (fvti.Vector fvti.RegClass:$rs1),
255                                (fvti.Vector (splat_vector fvti.ScalarRegClass:$rs2)),
256                                cc)),
257              (!cast<Instruction>(instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
258                  fvti.RegClass:$rs1,
259                  (fvti.Scalar fvti.ScalarRegClass:$rs2),
260                  fvti.AVL, fvti.SEW)>;
261}
262
263multiclass VPatFPSetCCSDNode_FV<CondCode cc, string swapped_op_instruction_name> {
264  foreach fvti = AllFloatVectors in
265    def : Pat<(fvti.Mask (setcc (fvti.Vector (splat_vector fvti.ScalarRegClass:$rs2)),
266                                (fvti.Vector fvti.RegClass:$rs1),
267                                cc)),
268              (!cast<Instruction>(swapped_op_instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
269                  fvti.RegClass:$rs1,
270                  (fvti.Scalar fvti.ScalarRegClass:$rs2),
271                  fvti.AVL, fvti.SEW)>;
272}
273
274multiclass VPatFPSetCCSDNode_VV_VF_FV<CondCode cc,
275                                      string inst_name,
276                                      string swapped_op_inst_name> {
277  defm : VPatFPSetCCSDNode_VV<cc, inst_name>;
278  defm : VPatFPSetCCSDNode_VF<cc, inst_name>;
279  defm : VPatFPSetCCSDNode_FV<cc, swapped_op_inst_name>;
280}
281
282multiclass VPatExtendSDNode_V<list<SDNode> ops, string inst_name, string suffix,
283                              list <VTypeInfoToFraction> fraction_list> {
284  foreach vtiTofti = fraction_list in {
285    defvar vti = vtiTofti.Vti;
286    defvar fti = vtiTofti.Fti;
287    foreach op = ops in
288      def : Pat<(vti.Vector (op (fti.Vector fti.RegClass:$rs2))),
289                (!cast<Instruction>(inst_name#"_"#suffix#"_"#vti.LMul.MX)
290                    fti.RegClass:$rs2, fti.AVL, vti.SEW)>;
291  }
292}
293
294//===----------------------------------------------------------------------===//
295// Patterns.
296//===----------------------------------------------------------------------===//
297
298let Predicates = [HasStdExtV] in {
299
300// 7.4. Vector Unit-Stride Instructions
301defm "" : VPatUSLoadStoreSDNodes<GPR>;
302defm "" : VPatUSLoadStoreSDNodes<AddrFI>;
303
304// 12.1. Vector Single-Width Integer Add and Subtract
305defm "" : VPatBinarySDNode_VV_VX_VI<add, "PseudoVADD">;
306defm "" : VPatBinarySDNode_VV_VX<sub, "PseudoVSUB">;
307// Handle VRSUB specially since it's the only integer binary op with reversed
308// pattern operands
309foreach vti = AllIntegerVectors in {
310  def : Pat<(sub (vti.Vector (SplatPat XLenVT:$rs2)),
311                 (vti.Vector vti.RegClass:$rs1)),
312            (!cast<Instruction>("PseudoVRSUB_VX_"# vti.LMul.MX)
313                 vti.RegClass:$rs1, GPR:$rs2, vti.AVL, vti.SEW)>;
314  def : Pat<(sub (vti.Vector (SplatPat_simm5 XLenVT:$rs2)),
315                 (vti.Vector vti.RegClass:$rs1)),
316            (!cast<Instruction>("PseudoVRSUB_VI_"# vti.LMul.MX)
317                 vti.RegClass:$rs1, simm5:$rs2, vti.AVL, vti.SEW)>;
318}
319
320// 12.3. Vector Integer Extension
321defm "" : VPatExtendSDNode_V<[zext, anyext], "PseudoVZEXT", "VF2",
322                             AllFractionableVF2IntVectors>;
323defm "" : VPatExtendSDNode_V<[sext],         "PseudoVSEXT", "VF2",
324                             AllFractionableVF2IntVectors>;
325defm "" : VPatExtendSDNode_V<[zext, anyext], "PseudoVZEXT", "VF4",
326                             AllFractionableVF4IntVectors>;
327defm "" : VPatExtendSDNode_V<[sext],         "PseudoVSEXT", "VF4",
328                             AllFractionableVF4IntVectors>;
329defm "" : VPatExtendSDNode_V<[zext, anyext], "PseudoVZEXT", "VF8",
330                             AllFractionableVF8IntVectors>;
331defm "" : VPatExtendSDNode_V<[sext],         "PseudoVSEXT", "VF8",
332                             AllFractionableVF8IntVectors>;
333
334// 12.5. Vector Bitwise Logical Instructions
335defm "" : VPatBinarySDNode_VV_VX_VI<and, "PseudoVAND">;
336defm "" : VPatBinarySDNode_VV_VX_VI<or, "PseudoVOR">;
337defm "" : VPatBinarySDNode_VV_VX_VI<xor, "PseudoVXOR">;
338
339// 12.6. Vector Single-Width Bit Shift Instructions
340defm "" : VPatBinarySDNode_VV_VX_VI<shl, "PseudoVSLL", uimm5>;
341defm "" : VPatBinarySDNode_VV_VX_VI<srl, "PseudoVSRL", uimm5>;
342defm "" : VPatBinarySDNode_VV_VX_VI<sra, "PseudoVSRA", uimm5>;
343
344// 12.7. Vector Narrowing Integer Right Shift Instructions
345foreach vtiTofti = AllFractionableVF2IntVectors in {
346  defvar vti = vtiTofti.Vti;
347  defvar fti = vtiTofti.Fti;
348  def : Pat<(fti.Vector (riscv_trunc_vector (vti.Vector vti.RegClass:$rs1))),
349            (!cast<Instruction>("PseudoVNSRL_WI_"#fti.LMul.MX)
350                vti.RegClass:$rs1, 0, fti.AVL, fti.SEW)>;
351}
352
353// 12.8. Vector Integer Comparison Instructions
354defm "" : VPatIntegerSetCCSDNode_VV_VX_VI<SETEQ,  "PseudoVMSEQ">;
355defm "" : VPatIntegerSetCCSDNode_VV_VX_VI<SETNE,  "PseudoVMSNE">;
356
357// FIXME: Support immediate forms of these by choosing SLE decrementing the
358// immediate
359defm "" : VPatIntegerSetCCSDNode_VV_VX<SETLT,  "PseudoVMSLT">;
360defm "" : VPatIntegerSetCCSDNode_VV_VX<SETULT, "PseudoVMSLTU">;
361
362defm "" : VPatIntegerSetCCSDNode_VV<SETGT,  "PseudoVMSLT", /*swap*/1>;
363defm "" : VPatIntegerSetCCSDNode_VV<SETUGT, "PseudoVMSLTU", /*swap*/1>;
364defm "" : VPatIntegerSetCCSDNode_VX_VI<SETGT,  "PseudoVMSGT">;
365defm "" : VPatIntegerSetCCSDNode_VX_VI<SETUGT, "PseudoVMSGTU">;
366
367defm "" : VPatIntegerSetCCSDNode_VV_VX_VI<SETLE,  "PseudoVMSLE">;
368defm "" : VPatIntegerSetCCSDNode_VV_VX_VI<SETULE, "PseudoVMSLEU">;
369
370// FIXME: Support immediate forms of these by choosing SGT and decrementing the
371// immediate
372defm "" : VPatIntegerSetCCSDNode_VV<SETGE,  "PseudoVMSLE", /*swap*/1>;
373defm "" : VPatIntegerSetCCSDNode_VV<SETUGE, "PseudoVMSLEU", /*swap*/1>;
374
375// 12.9. Vector Integer Min/Max Instructions
376defm "" : VPatBinarySDNode_VV_VX<umin, "PseudoVMINU">;
377defm "" : VPatBinarySDNode_VV_VX<smin, "PseudoVMIN">;
378defm "" : VPatBinarySDNode_VV_VX<umax, "PseudoVMAXU">;
379defm "" : VPatBinarySDNode_VV_VX<smax, "PseudoVMAX">;
380
381// 12.10. Vector Single-Width Integer Multiply Instructions
382defm "" : VPatBinarySDNode_VV_VX<mul, "PseudoVMUL">;
383defm "" : VPatBinarySDNode_VV_VX<mulhs, "PseudoVMULH">;
384defm "" : VPatBinarySDNode_VV_VX<mulhu, "PseudoVMULHU">;
385
386// 12.11. Vector Integer Divide Instructions
387defm "" : VPatBinarySDNode_VV_VX<udiv, "PseudoVDIVU">;
388defm "" : VPatBinarySDNode_VV_VX<sdiv, "PseudoVDIV">;
389defm "" : VPatBinarySDNode_VV_VX<urem, "PseudoVREMU">;
390defm "" : VPatBinarySDNode_VV_VX<srem, "PseudoVREM">;
391
392// 12.16. Vector Integer Merge Instructions
393foreach vti = AllIntegerVectors in {
394  def : Pat<(vti.Vector (vselect (vti.Mask VMV0:$vm), vti.RegClass:$rs1,
395                                                      vti.RegClass:$rs2)),
396            (!cast<Instruction>("PseudoVMERGE_VVM_"#vti.LMul.MX)
397                 vti.RegClass:$rs2, vti.RegClass:$rs1, VMV0:$vm,
398                 vti.AVL, vti.SEW)>;
399
400  def : Pat<(vti.Vector (vselect (vti.Mask VMV0:$vm), (SplatPat XLenVT:$rs1),
401                                                      vti.RegClass:$rs2)),
402            (!cast<Instruction>("PseudoVMERGE_VXM_"#vti.LMul.MX)
403                 vti.RegClass:$rs2, GPR:$rs1, VMV0:$vm, vti.AVL, vti.SEW)>;
404
405  def : Pat<(vti.Vector (vselect (vti.Mask VMV0:$vm), (SplatPat_simm5 simm5:$rs1),
406                                                      vti.RegClass:$rs2)),
407            (!cast<Instruction>("PseudoVMERGE_VIM_"#vti.LMul.MX)
408                 vti.RegClass:$rs2, simm5:$rs1, VMV0:$vm, vti.AVL, vti.SEW)>;
409}
410
411// 16.1. Vector Mask-Register Logical Instructions
412foreach mti = AllMasks in {
413  def : Pat<(mti.Mask (and VR:$rs1, VR:$rs2)),
414            (!cast<Instruction>("PseudoVMAND_MM_"#mti.LMul.MX)
415                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
416  def : Pat<(mti.Mask (or VR:$rs1, VR:$rs2)),
417            (!cast<Instruction>("PseudoVMOR_MM_"#mti.LMul.MX)
418                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
419  def : Pat<(mti.Mask (xor VR:$rs1, VR:$rs2)),
420            (!cast<Instruction>("PseudoVMXOR_MM_"#mti.LMul.MX)
421                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
422
423  def : Pat<(mti.Mask (vnot (and VR:$rs1, VR:$rs2))),
424            (!cast<Instruction>("PseudoVMNAND_MM_"#mti.LMul.MX)
425                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
426  def : Pat<(mti.Mask (vnot (or VR:$rs1, VR:$rs2))),
427            (!cast<Instruction>("PseudoVMNOR_MM_"#mti.LMul.MX)
428                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
429  def : Pat<(mti.Mask (vnot (xor VR:$rs1, VR:$rs2))),
430            (!cast<Instruction>("PseudoVMXNOR_MM_"#mti.LMul.MX)
431                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
432
433  def : Pat<(mti.Mask (and VR:$rs1, (vnot VR:$rs2))),
434            (!cast<Instruction>("PseudoVMANDNOT_MM_"#mti.LMul.MX)
435                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
436  def : Pat<(mti.Mask (or VR:$rs1, (vnot VR:$rs2))),
437            (!cast<Instruction>("PseudoVMORNOT_MM_"#mti.LMul.MX)
438                 VR:$rs1, VR:$rs2, mti.AVL, mti.SEW)>;
439}
440
441} // Predicates = [HasStdExtV]
442
443let Predicates = [HasStdExtV, HasStdExtF] in {
444
445// 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions
446defm "" : VPatBinaryFPSDNode_VV_VF<fadd, "PseudoVFADD">;
447defm "" : VPatBinaryFPSDNode_VV_VF<fsub, "PseudoVFSUB">;
448defm "" : VPatBinaryFPSDNode_R_VF<fsub, "PseudoVFRSUB">;
449
450// 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions
451defm "" : VPatBinaryFPSDNode_VV_VF<fmul, "PseudoVFMUL">;
452defm "" : VPatBinaryFPSDNode_VV_VF<fdiv, "PseudoVFDIV">;
453defm "" : VPatBinaryFPSDNode_R_VF<fdiv, "PseudoVFRDIV">;
454
455// 14.11. Vector Floating-Point Compare Instructions
456defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETEQ,  "PseudoVMFEQ", "PseudoVMFEQ">;
457defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETOEQ, "PseudoVMFEQ", "PseudoVMFEQ">;
458
459defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETNE,  "PseudoVMFNE", "PseudoVMFNE">;
460defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETUNE, "PseudoVMFNE", "PseudoVMFNE">;
461
462defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETLT,  "PseudoVMFLT", "PseudoVMFGT">;
463defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETOLT, "PseudoVMFLT", "PseudoVMFGT">;
464
465defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETLE,  "PseudoVMFLE", "PseudoVMFGE">;
466defm "" : VPatFPSetCCSDNode_VV_VF_FV<SETOLE, "PseudoVMFLE", "PseudoVMFGE">;
467
468// Floating-point vselects:
469// 12.16. Vector Integer Merge Instructions
470// 14.13. Vector Floating-Point Merge Instruction
471foreach fvti = AllFloatVectors in {
472  def : Pat<(fvti.Vector (vselect (fvti.Mask VMV0:$vm), fvti.RegClass:$rs1,
473                                                        fvti.RegClass:$rs2)),
474            (!cast<Instruction>("PseudoVMERGE_VVM_"#fvti.LMul.MX)
475                 fvti.RegClass:$rs2, fvti.RegClass:$rs1, VMV0:$vm,
476                 fvti.AVL, fvti.SEW)>;
477
478  def : Pat<(fvti.Vector (vselect (fvti.Mask VMV0:$vm),
479                                  (splat_vector fvti.ScalarRegClass:$rs1),
480                                  fvti.RegClass:$rs2)),
481            (!cast<Instruction>("PseudoVFMERGE_V"#fvti.ScalarSuffix#"M_"#fvti.LMul.MX)
482                 fvti.RegClass:$rs2,
483                 (fvti.Scalar fvti.ScalarRegClass:$rs1),
484                 VMV0:$vm, fvti.AVL, fvti.SEW)>;
485
486  def : Pat<(fvti.Vector (vselect (fvti.Mask VMV0:$vm),
487                                  (splat_vector (fvti.Scalar fpimm0)),
488                                  fvti.RegClass:$rs2)),
489            (!cast<Instruction>("PseudoVMERGE_VIM_"#fvti.LMul.MX)
490                 fvti.RegClass:$rs2, 0, VMV0:$vm, fvti.AVL, fvti.SEW)>;
491}
492} // Predicates = [HasStdExtV, HasStdExtF]
493
494//===----------------------------------------------------------------------===//
495// Vector Splats
496//===----------------------------------------------------------------------===//
497
498let Predicates = [HasStdExtV] in {
499foreach vti = AllIntegerVectors in {
500  def : Pat<(vti.Vector (splat_vector GPR:$rs1)),
501            (!cast<Instruction>("PseudoVMV_V_X_" # vti.LMul.MX)
502              GPR:$rs1, vti.AVL, vti.SEW)>;
503  def : Pat<(vti.Vector (splat_vector simm5:$rs1)),
504            (!cast<Instruction>("PseudoVMV_V_I_" # vti.LMul.MX)
505              simm5:$rs1, vti.AVL, vti.SEW)>;
506}
507
508foreach mti = AllMasks in {
509  def : Pat<(mti.Mask immAllOnesV),
510            (!cast<Instruction>("PseudoVMSET_M_"#mti.BX) mti.AVL, mti.SEW)>;
511  def : Pat<(mti.Mask immAllZerosV),
512            (!cast<Instruction>("PseudoVMCLR_M_"#mti.BX) mti.AVL, mti.SEW)>;
513}
514} // Predicates = [HasStdExtV]
515
516let Predicates = [HasStdExtV, IsRV32] in {
517foreach vti = AllIntegerVectors in {
518  if !eq(vti.SEW, 64) then {
519    def : Pat<(vti.Vector (rv32_splat_i64 GPR:$rs1)),
520              (!cast<Instruction>("PseudoVMV_V_X_" # vti.LMul.MX)
521                GPR:$rs1, vti.AVL, vti.SEW)>;
522    def : Pat<(vti.Vector (rv32_splat_i64 simm5:$rs1)),
523              (!cast<Instruction>("PseudoVMV_V_I_" # vti.LMul.MX)
524                simm5:$rs1, vti.AVL, vti.SEW)>;
525  }
526}
527} // Predicates = [HasStdExtV, IsRV32]
528
529let Predicates = [HasStdExtV, HasStdExtF] in {
530foreach fvti = AllFloatVectors in {
531  def : Pat<(fvti.Vector (splat_vector fvti.ScalarRegClass:$rs1)),
532            (!cast<Instruction>("PseudoVFMV_V_"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
533              (fvti.Scalar fvti.ScalarRegClass:$rs1),
534              fvti.AVL, fvti.SEW)>;
535
536  def : Pat<(fvti.Vector (splat_vector (fvti.Scalar fpimm0))),
537            (!cast<Instruction>("PseudoVMV_V_I_"#fvti.LMul.MX)
538              0, fvti.AVL, fvti.SEW)>;
539}
540} // Predicates = [HasStdExtV, HasStdExtF]
541
542//===----------------------------------------------------------------------===//
543// Vector Element Inserts/Extracts
544//===----------------------------------------------------------------------===//
545
546// The built-in TableGen 'extractelt' and 'insertelt' nodes must return the
547// same type as the vector element type. On RISC-V, XLenVT is the only legal
548// integer type, so for integer inserts/extracts we use a custom node which
549// returns XLenVT.
550def riscv_insert_vector_elt
551    : SDNode<"ISD::INSERT_VECTOR_ELT",
552             SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisVT<2, XLenVT>,
553                                  SDTCisPtrTy<3>]>, []>;
554def riscv_extract_vector_elt
555    : SDNode<"ISD::EXTRACT_VECTOR_ELT",
556             SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>, SDTCisPtrTy<2>]>, []>;
557
558multiclass VPatInsertExtractElt_XI_Idx<bit IsFloat> {
559  defvar vtilist = !if(IsFloat, AllFloatVectors, AllIntegerVectors);
560  defvar insertelt_node = !if(IsFloat, insertelt, riscv_insert_vector_elt);
561  defvar extractelt_node = !if(IsFloat, extractelt, riscv_extract_vector_elt);
562  foreach vti = vtilist in {
563    defvar MX = vti.LMul.MX;
564    defvar vmv_xf_s_inst = !cast<Instruction>(!strconcat("PseudoV",
565                                                         !if(IsFloat, "F", ""),
566                                                         "MV_",
567                                                         vti.ScalarSuffix,
568                                                         "_S_", MX));
569    defvar vmv_s_xf_inst = !cast<Instruction>(!strconcat("PseudoV",
570                                                         !if(IsFloat, "F", ""),
571                                                         "MV_S_",
572                                                         vti.ScalarSuffix,
573                                                         "_", MX));
574    // Only pattern-match insert/extract-element operations where the index is
575    // 0. Any other index will have been custom-lowered to slide the vector
576    // correctly into place (and, in the case of insert, slide it back again
577    // afterwards).
578    def : Pat<(vti.Scalar (extractelt_node (vti.Vector vti.RegClass:$rs2), 0)),
579              (vmv_xf_s_inst vti.RegClass:$rs2, vti.SEW)>;
580
581    def : Pat<(vti.Vector (insertelt_node (vti.Vector vti.RegClass:$merge),
582                                          vti.ScalarRegClass:$rs1, 0)),
583              (vmv_s_xf_inst vti.RegClass:$merge,
584                      (vti.Scalar vti.ScalarRegClass:$rs1),
585                      vti.AVL, vti.SEW)>;
586  }
587}
588
589let Predicates = [HasStdExtV] in
590defm "" : VPatInsertExtractElt_XI_Idx</*IsFloat*/0>;
591let Predicates = [HasStdExtV, HasStdExtF] in
592defm "" : VPatInsertExtractElt_XI_Idx</*IsFloat*/1>;
593
594//===----------------------------------------------------------------------===//
595// Miscellaneous RISCVISD SDNodes
596//===----------------------------------------------------------------------===//
597
598def riscv_vid
599    : SDNode<"RISCVISD::VID", SDTypeProfile<1, 0, [SDTCisVec<0>]>, []>;
600
601def SDTRVVSlide : SDTypeProfile<1, 3, [
602  SDTCisVec<0>, SDTCisSameAs<1, 0>, SDTCisSameAs<2, 0>, SDTCisVT<3, XLenVT>
603]>;
604
605def riscv_slideup : SDNode<"RISCVISD::VSLIDEUP", SDTRVVSlide, []>;
606def riscv_slidedown : SDNode<"RISCVISD::VSLIDEDOWN", SDTRVVSlide, []>;
607
608let Predicates = [HasStdExtV] in {
609
610foreach vti = AllIntegerVectors in
611  def : Pat<(vti.Vector riscv_vid),
612            (!cast<Instruction>("PseudoVID_V_"#vti.LMul.MX) vti.AVL, vti.SEW)>;
613
614foreach vti = !listconcat(AllIntegerVectors, AllFloatVectors) in {
615    def : Pat<(vti.Vector (riscv_slideup (vti.Vector vti.RegClass:$rs3),
616                                         (vti.Vector vti.RegClass:$rs1),
617                                         uimm5:$rs2)),
618              (!cast<Instruction>("PseudoVSLIDEUP_VI_"#vti.LMul.MX)
619                  vti.RegClass:$rs3, vti.RegClass:$rs1, uimm5:$rs2,
620                  vti.AVL, vti.SEW)>;
621
622    def : Pat<(vti.Vector (riscv_slideup (vti.Vector vti.RegClass:$rs3),
623                                         (vti.Vector vti.RegClass:$rs1),
624                                         GPR:$rs2)),
625              (!cast<Instruction>("PseudoVSLIDEUP_VX_"#vti.LMul.MX)
626                  vti.RegClass:$rs3, vti.RegClass:$rs1, GPR:$rs2,
627                  vti.AVL, vti.SEW)>;
628
629    def : Pat<(vti.Vector (riscv_slidedown (vti.Vector vti.RegClass:$rs3),
630                                           (vti.Vector vti.RegClass:$rs1),
631                                           uimm5:$rs2)),
632              (!cast<Instruction>("PseudoVSLIDEDOWN_VI_"#vti.LMul.MX)
633                  vti.RegClass:$rs3, vti.RegClass:$rs1, uimm5:$rs2,
634                  vti.AVL, vti.SEW)>;
635
636    def : Pat<(vti.Vector (riscv_slidedown (vti.Vector vti.RegClass:$rs3),
637                                           (vti.Vector vti.RegClass:$rs1),
638                                           GPR:$rs2)),
639              (!cast<Instruction>("PseudoVSLIDEDOWN_VX_"#vti.LMul.MX)
640                  vti.RegClass:$rs3, vti.RegClass:$rs1, GPR:$rs2,
641                  vti.AVL, vti.SEW)>;
642}
643} // Predicates = [HasStdExtV]
644