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/// version 1.0.
12///
13/// This file is included from and depends upon RISCVInstrInfoVPseudos.td
14///
15/// Note: the patterns for RVV intrinsics are found in
16/// RISCVInstrInfoVPseudos.td.
17///
18//===----------------------------------------------------------------------===//
19
20//===----------------------------------------------------------------------===//
21// Helpers to define the SDNode patterns.
22//===----------------------------------------------------------------------===//
23
24def rvv_vnot : PatFrag<(ops node:$in),
25                       (xor node:$in, (riscv_vmset_vl (XLenVT srcvalue)))>;
26
27multiclass VPatUSLoadStoreSDNode<ValueType type,
28                                 int log2sew,
29                                 LMULInfo vlmul,
30                                 OutPatFrag avl,
31                                 VReg reg_class,
32                                 int sew = !shl(1, log2sew)>
33{
34  defvar load_instr = !cast<Instruction>("PseudoVLE"#sew#"_V_"#vlmul.MX);
35  defvar store_instr = !cast<Instruction>("PseudoVSE"#sew#"_V_"#vlmul.MX);
36  // Load
37  def : Pat<(type (load GPR:$rs1)),
38            (load_instr GPR:$rs1, avl, log2sew)>;
39  // Store
40  def : Pat<(store type:$rs2, GPR:$rs1),
41            (store_instr reg_class:$rs2, GPR:$rs1, avl, log2sew)>;
42}
43
44multiclass VPatUSLoadStoreWholeVRSDNode<ValueType type,
45                                        int log2sew,
46                                        LMULInfo vlmul,
47                                        VReg reg_class,
48                                        int sew = !shl(1, log2sew)>
49{
50  defvar load_instr =
51    !cast<Instruction>("VL"#!substr(vlmul.MX, 1)#"RE"#sew#"_V");
52  defvar store_instr =
53    !cast<Instruction>("VS"#!substr(vlmul.MX, 1)#"R_V");
54
55  // Load
56  def : Pat<(type (load GPR:$rs1)),
57            (load_instr GPR:$rs1)>;
58  // Store
59  def : Pat<(store type:$rs2, GPR:$rs1),
60            (store_instr reg_class:$rs2, GPR:$rs1)>;
61}
62
63multiclass VPatUSLoadStoreMaskSDNode<MTypeInfo m>
64{
65  defvar load_instr = !cast<Instruction>("PseudoVLM_V_"#m.BX);
66  defvar store_instr = !cast<Instruction>("PseudoVSM_V_"#m.BX);
67  // Load
68  def : Pat<(m.Mask (load GPR:$rs1)),
69            (load_instr GPR:$rs1, m.AVL, m.Log2SEW)>;
70  // Store
71  def : Pat<(store m.Mask:$rs2, GPR:$rs1),
72            (store_instr VR:$rs2, GPR:$rs1, m.AVL, m.Log2SEW)>;
73}
74
75class VPatBinarySDNode_VV<SDNode vop,
76                          string instruction_name,
77                          ValueType result_type,
78                          ValueType op_type,
79                          int sew,
80                          LMULInfo vlmul,
81                          OutPatFrag avl,
82                          VReg op_reg_class> :
83    Pat<(result_type (vop
84                     (op_type op_reg_class:$rs1),
85                     (op_type op_reg_class:$rs2))),
86        (!cast<Instruction>(instruction_name#"_VV_"# vlmul.MX)
87                     op_reg_class:$rs1,
88                     op_reg_class:$rs2,
89                     avl, sew)>;
90
91class VPatBinarySDNode_XI<SDNode vop,
92                          string instruction_name,
93                          string suffix,
94                          ValueType result_type,
95                          ValueType vop_type,
96                          int sew,
97                          LMULInfo vlmul,
98                          OutPatFrag avl,
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  foreach vti = AllIntegerVectors in {
112    def : VPatBinarySDNode_VV<vop, instruction_name,
113                              vti.Vector, vti.Vector, vti.Log2SEW,
114                              vti.LMul, vti.AVL, vti.RegClass>;
115    def : VPatBinarySDNode_XI<vop, instruction_name, "VX",
116                              vti.Vector, vti.Vector, vti.Log2SEW,
117                              vti.LMul, vti.AVL, vti.RegClass,
118                              SplatPat, GPR>;
119  }
120}
121
122multiclass VPatBinarySDNode_VV_VX_VI<SDNode vop, string instruction_name,
123                                     Operand ImmType = simm5>
124    : VPatBinarySDNode_VV_VX<vop, instruction_name> {
125  foreach vti = AllIntegerVectors in {
126    def : VPatBinarySDNode_XI<vop, instruction_name, "VI",
127                              vti.Vector, vti.Vector, vti.Log2SEW,
128                              vti.LMul, vti.AVL, vti.RegClass,
129                              !cast<ComplexPattern>(SplatPat#_#ImmType),
130                              ImmType>;
131  }
132}
133
134class VPatBinarySDNode_VF<SDNode vop,
135                          string instruction_name,
136                          ValueType result_type,
137                          ValueType vop_type,
138                          ValueType xop_type,
139                          int sew,
140                          LMULInfo vlmul,
141                          OutPatFrag avl,
142                          VReg vop_reg_class,
143                          DAGOperand xop_kind> :
144    Pat<(result_type (vop (vop_type vop_reg_class:$rs1),
145                          (vop_type (SplatFPOp xop_kind:$rs2)))),
146        (!cast<Instruction>(instruction_name#"_"#vlmul.MX)
147                     vop_reg_class:$rs1,
148                     (xop_type xop_kind:$rs2),
149                     avl, sew)>;
150
151multiclass VPatBinaryFPSDNode_VV_VF<SDNode vop, string instruction_name> {
152  foreach vti = AllFloatVectors in {
153    def : VPatBinarySDNode_VV<vop, instruction_name,
154                              vti.Vector, vti.Vector, vti.Log2SEW,
155                              vti.LMul, vti.AVL, vti.RegClass>;
156    def : VPatBinarySDNode_VF<vop, instruction_name#"_V"#vti.ScalarSuffix,
157                              vti.Vector, vti.Vector, vti.Scalar,
158                              vti.Log2SEW, vti.LMul, vti.AVL, vti.RegClass,
159                              vti.ScalarRegClass>;
160  }
161}
162
163multiclass VPatBinaryFPSDNode_R_VF<SDNode vop, string instruction_name> {
164  foreach fvti = AllFloatVectors in
165    def : Pat<(fvti.Vector (vop (fvti.Vector (SplatFPOp fvti.Scalar:$rs2)),
166                                (fvti.Vector fvti.RegClass:$rs1))),
167              (!cast<Instruction>(instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
168                           fvti.RegClass:$rs1,
169                           (fvti.Scalar fvti.ScalarRegClass:$rs2),
170                           fvti.AVL, fvti.Log2SEW)>;
171}
172
173multiclass VPatIntegerSetCCSDNode_VV<string instruction_name,
174                                     CondCode cc> {
175  foreach vti = AllIntegerVectors in {
176    defvar instruction = !cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX);
177    def : Pat<(vti.Mask (setcc (vti.Vector vti.RegClass:$rs1),
178                               (vti.Vector vti.RegClass:$rs2), cc)),
179              (instruction vti.RegClass:$rs1, vti.RegClass:$rs2, vti.AVL,
180              vti.Log2SEW)>;
181  }
182}
183
184multiclass VPatIntegerSetCCSDNode_VV_Swappable<string instruction_name,
185                                               CondCode cc, CondCode invcc>
186    : VPatIntegerSetCCSDNode_VV<instruction_name, cc> {
187  foreach vti = AllIntegerVectors in {
188    defvar instruction = !cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX);
189    def : Pat<(vti.Mask (setcc (vti.Vector vti.RegClass:$rs2),
190                               (vti.Vector vti.RegClass:$rs1), invcc)),
191              (instruction vti.RegClass:$rs1, vti.RegClass:$rs2, vti.AVL,
192              vti.Log2SEW)>;
193  }
194}
195
196multiclass VPatIntegerSetCCSDNode_XI<
197                                     string instruction_name,
198                                     CondCode cc,
199                                     string kind,
200                                     ComplexPattern SplatPatKind,
201                                     DAGOperand xop_kind> {
202  foreach vti = AllIntegerVectors in {
203    defvar instruction = !cast<Instruction>(instruction_name#_#kind#_#vti.LMul.MX);
204    def : Pat<(vti.Mask (setcc (vti.Vector vti.RegClass:$rs1),
205                               (vti.Vector (SplatPatKind xop_kind:$rs2)), cc)),
206              (instruction vti.RegClass:$rs1, xop_kind:$rs2, vti.AVL, vti.Log2SEW)>;
207  }
208}
209
210multiclass VPatIntegerSetCCSDNode_XI_Swappable<string instruction_name,
211                                               CondCode cc, CondCode invcc,
212                                               string kind,
213                                               ComplexPattern SplatPatKind,
214                                               DAGOperand xop_kind>
215    : VPatIntegerSetCCSDNode_XI<instruction_name, cc, kind, SplatPatKind,
216                                xop_kind> {
217  foreach vti = AllIntegerVectors in {
218    defvar instruction = !cast<Instruction>(instruction_name#_#kind#_#vti.LMul.MX);
219    def : Pat<(vti.Mask (setcc (vti.Vector vti.RegClass:$rs1),
220                               (vti.Vector (SplatPatKind xop_kind:$rs2)), cc)),
221              (instruction vti.RegClass:$rs1, xop_kind:$rs2, vti.AVL, vti.Log2SEW)>;
222    def : Pat<(vti.Mask (setcc (vti.Vector (SplatPatKind xop_kind:$rs2)),
223                               (vti.Vector vti.RegClass:$rs1), invcc)),
224              (instruction vti.RegClass:$rs1, xop_kind:$rs2, vti.AVL, vti.Log2SEW)>;
225  }
226}
227
228multiclass VPatIntegerSetCCSDNode_VX_Swappable<string instruction_name,
229                                               CondCode cc, CondCode invcc>
230    : VPatIntegerSetCCSDNode_XI_Swappable<instruction_name, cc, invcc, "VX",
231                                          SplatPat, GPR>;
232
233multiclass VPatIntegerSetCCSDNode_VI<string instruction_name, CondCode cc>
234    : VPatIntegerSetCCSDNode_XI<instruction_name, cc, "VI", SplatPat_simm5, simm5>;
235
236multiclass VPatIntegerSetCCSDNode_VIPlus1<string instruction_name, CondCode cc,
237                                          ComplexPattern splatpat_kind> {
238  foreach vti = AllIntegerVectors in {
239    defvar instruction = !cast<Instruction>(instruction_name#"_VI_"#vti.LMul.MX);
240    def : Pat<(vti.Mask (setcc (vti.Vector vti.RegClass:$rs1),
241                               (vti.Vector (splatpat_kind simm5:$rs2)),
242                               cc)),
243              (instruction vti.RegClass:$rs1, (DecImm simm5:$rs2),
244                           vti.AVL, vti.Log2SEW)>;
245  }
246}
247
248multiclass VPatFPSetCCSDNode_VV_VF_FV<CondCode cc,
249                                      string inst_name,
250                                      string swapped_op_inst_name> {
251  foreach fvti = AllFloatVectors in {
252    def : Pat<(fvti.Mask (setcc (fvti.Vector fvti.RegClass:$rs1),
253                                (fvti.Vector fvti.RegClass:$rs2),
254                                cc)),
255              (!cast<Instruction>(inst_name#"_VV_"#fvti.LMul.MX)
256                  fvti.RegClass:$rs1, fvti.RegClass:$rs2, fvti.AVL, fvti.Log2SEW)>;
257    def : Pat<(fvti.Mask (setcc (fvti.Vector fvti.RegClass:$rs1),
258                                (SplatFPOp fvti.ScalarRegClass:$rs2),
259                                cc)),
260              (!cast<Instruction>(inst_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
261                  fvti.RegClass:$rs1, fvti.ScalarRegClass:$rs2,
262                  fvti.AVL, fvti.Log2SEW)>;
263    def : Pat<(fvti.Mask (setcc (SplatFPOp fvti.ScalarRegClass:$rs2),
264                                (fvti.Vector fvti.RegClass:$rs1),
265                                cc)),
266              (!cast<Instruction>(swapped_op_inst_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
267                  fvti.RegClass:$rs1, fvti.ScalarRegClass:$rs2,
268                  fvti.AVL, fvti.Log2SEW)>;
269  }
270}
271
272multiclass VPatExtendSDNode_V<list<SDNode> ops, string inst_name, string suffix,
273                              list <VTypeInfoToFraction> fraction_list> {
274  foreach vtiTofti = fraction_list in {
275    defvar vti = vtiTofti.Vti;
276    defvar fti = vtiTofti.Fti;
277    foreach op = ops in
278      def : Pat<(vti.Vector (op (fti.Vector fti.RegClass:$rs2))),
279                (!cast<Instruction>(inst_name#"_"#suffix#"_"#vti.LMul.MX)
280                    fti.RegClass:$rs2, fti.AVL, vti.Log2SEW)>;
281  }
282}
283
284multiclass VPatConvertI2FPSDNode_V<SDNode vop, string instruction_name> {
285  foreach fvti = AllFloatVectors in {
286    defvar ivti = GetIntVTypeInfo<fvti>.Vti;
287    def : Pat<(fvti.Vector (vop (ivti.Vector ivti.RegClass:$rs1))),
288              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX)
289                  ivti.RegClass:$rs1, fvti.AVL, fvti.Log2SEW)>;
290  }
291}
292
293multiclass VPatConvertFP2ISDNode_V<SDNode vop, string instruction_name> {
294  foreach fvti = AllFloatVectors in {
295    defvar ivti = GetIntVTypeInfo<fvti>.Vti;
296    def : Pat<(ivti.Vector (vop (fvti.Vector fvti.RegClass:$rs1))),
297              (!cast<Instruction>(instruction_name#"_"#ivti.LMul.MX)
298                  fvti.RegClass:$rs1, ivti.AVL, ivti.Log2SEW)>;
299  }
300}
301
302multiclass VPatWConvertI2FPSDNode_V<SDNode vop, string instruction_name> {
303  foreach vtiToWti = AllWidenableIntToFloatVectors in {
304    defvar ivti = vtiToWti.Vti;
305    defvar fwti = vtiToWti.Wti;
306    def : Pat<(fwti.Vector (vop (ivti.Vector ivti.RegClass:$rs1))),
307              (!cast<Instruction>(instruction_name#"_"#ivti.LMul.MX)
308                  ivti.RegClass:$rs1, ivti.AVL, ivti.Log2SEW)>;
309  }
310}
311
312multiclass VPatWConvertFP2ISDNode_V<SDNode vop, string instruction_name> {
313  foreach fvtiToFWti = AllWidenableFloatVectors in {
314    defvar fvti = fvtiToFWti.Vti;
315    defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti;
316    def : Pat<(iwti.Vector (vop (fvti.Vector fvti.RegClass:$rs1))),
317              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX)
318                  fvti.RegClass:$rs1, fvti.AVL, fvti.Log2SEW)>;
319  }
320}
321
322multiclass VPatNConvertI2FPSDNode_V<SDNode vop, string instruction_name> {
323  foreach fvtiToFWti = AllWidenableFloatVectors in {
324    defvar fvti = fvtiToFWti.Vti;
325    defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti;
326    def : Pat<(fvti.Vector (vop (iwti.Vector iwti.RegClass:$rs1))),
327              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX)
328                  iwti.RegClass:$rs1, fvti.AVL, fvti.Log2SEW)>;
329  }
330}
331
332multiclass VPatNConvertFP2ISDNode_V<SDNode vop, string instruction_name> {
333  foreach vtiToWti = AllWidenableIntToFloatVectors in {
334    defvar vti = vtiToWti.Vti;
335    defvar fwti = vtiToWti.Wti;
336    def : Pat<(vti.Vector (vop (fwti.Vector fwti.RegClass:$rs1))),
337              (!cast<Instruction>(instruction_name#"_"#vti.LMul.MX)
338                  fwti.RegClass:$rs1, vti.AVL, vti.Log2SEW)>;
339  }
340}
341
342multiclass VPatWidenBinarySDNode_VV_VX<SDNode op, PatFrags extop1, PatFrags extop2,
343                                       string instruction_name> {
344  foreach vtiToWti = AllWidenableIntVectors in {
345    defvar vti = vtiToWti.Vti;
346    defvar wti = vtiToWti.Wti;
347    def : Pat<(op (wti.Vector (extop1 (vti.Vector vti.RegClass:$rs2))),
348                  (wti.Vector (extop2 (vti.Vector vti.RegClass:$rs1)))),
349              (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
350                 vti.RegClass:$rs2, vti.RegClass:$rs1, vti.AVL, vti.Log2SEW)>;
351    def : Pat<(op (wti.Vector (extop1 (vti.Vector vti.RegClass:$rs2))),
352                  (wti.Vector (extop2 (vti.Vector (SplatPat GPR:$rs1))))),
353              (!cast<Instruction>(instruction_name#"_VX_"#vti.LMul.MX)
354                 vti.RegClass:$rs2, GPR:$rs1, vti.AVL, vti.Log2SEW)>;
355  }
356}
357
358multiclass VPatWidenBinarySDNode_WV_WX<SDNode op, PatFrags extop,
359                                       string instruction_name> {
360  foreach vtiToWti = AllWidenableIntVectors in {
361    defvar vti = vtiToWti.Vti;
362    defvar wti = vtiToWti.Wti;
363    def : Pat<(op (wti.Vector wti.RegClass:$rs2),
364                  (wti.Vector (extop (vti.Vector vti.RegClass:$rs1)))),
365              (!cast<Instruction>(instruction_name#"_WV_"#vti.LMul.MX)
366                 wti.RegClass:$rs2, vti.RegClass:$rs1, vti.AVL, vti.Log2SEW)>;
367    def : Pat<(op (wti.Vector wti.RegClass:$rs2),
368                  (wti.Vector (extop (vti.Vector (SplatPat GPR:$rs1))))),
369              (!cast<Instruction>(instruction_name#"_WX_"#vti.LMul.MX)
370                 wti.RegClass:$rs2, GPR:$rs1, vti.AVL, vti.Log2SEW)>;
371  }
372}
373
374multiclass VPatWidenBinarySDNode_VV_VX_WV_WX<SDNode op, PatFrags extop,
375                                             string instruction_name> {
376  defm : VPatWidenBinarySDNode_VV_VX<op, extop, extop, instruction_name>;
377  defm : VPatWidenBinarySDNode_WV_WX<op, extop, instruction_name>;
378}
379
380multiclass VPatWidenMulAddSDNode_VV<PatFrags extop1, PatFrags extop2, string instruction_name> {
381  foreach vtiToWti = AllWidenableIntVectors in {
382    defvar vti = vtiToWti.Vti;
383    defvar wti = vtiToWti.Wti;
384    def : Pat<
385      (add (wti.Vector wti.RegClass:$rd),
386        (mul_oneuse (wti.Vector (extop1 (vti.Vector vti.RegClass:$rs1))),
387                    (wti.Vector (extop2 (vti.Vector vti.RegClass:$rs2))))),
388      (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
389        wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
390        vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC
391      )>;
392  }
393}
394multiclass VPatWidenMulAddSDNode_VX<PatFrags extop1, PatFrags extop2, string instruction_name> {
395  foreach vtiToWti = AllWidenableIntVectors in {
396    defvar vti = vtiToWti.Vti;
397    defvar wti = vtiToWti.Wti;
398    def : Pat<
399      (add (wti.Vector wti.RegClass:$rd),
400        (mul_oneuse (wti.Vector (extop1 (vti.Vector (SplatPat GPR:$rs1)))),
401                    (wti.Vector (extop2 (vti.Vector vti.RegClass:$rs2))))),
402      (!cast<Instruction>(instruction_name#"_VX_"#vti.LMul.MX)
403        wti.RegClass:$rd, GPR:$rs1, vti.RegClass:$rs2,
404        vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC
405      )>;
406  }
407}
408
409multiclass VPatWidenBinaryFPSDNode_VV_VF<SDNode op, string instruction_name> {
410  foreach vtiToWti = AllWidenableFloatVectors in {
411    defvar vti = vtiToWti.Vti;
412    defvar wti = vtiToWti.Wti;
413    def : Pat<(op (wti.Vector (riscv_fpextend_vl_oneuse
414                                   (vti.Vector vti.RegClass:$rs2),
415                                   (vti.Mask true_mask), (XLenVT srcvalue))),
416                  (wti.Vector (riscv_fpextend_vl_oneuse
417                                   (vti.Vector vti.RegClass:$rs1),
418                                   (vti.Mask true_mask), (XLenVT srcvalue)))),
419              (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
420                 vti.RegClass:$rs2, vti.RegClass:$rs1, vti.AVL, vti.Log2SEW)>;
421    def : Pat<(op (wti.Vector (riscv_fpextend_vl_oneuse
422                                   (vti.Vector vti.RegClass:$rs2),
423                                   (vti.Mask true_mask), (XLenVT srcvalue))),
424                  (wti.Vector (riscv_fpextend_vl_oneuse
425                                   (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
426                                   (vti.Mask true_mask), (XLenVT srcvalue)))),
427              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
428                 vti.RegClass:$rs2, vti.ScalarRegClass:$rs1, vti.AVL, vti.Log2SEW)>;
429    def : Pat<(op (wti.Vector (riscv_fpextend_vl_oneuse
430                                   (vti.Vector vti.RegClass:$rs2),
431                                   (vti.Mask true_mask), (XLenVT srcvalue))),
432                  (wti.Vector (SplatFPOp (fpext_oneuse vti.ScalarRegClass:$rs1)))),
433              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
434                 vti.RegClass:$rs2, vti.ScalarRegClass:$rs1, vti.AVL, vti.Log2SEW)>;
435  }
436}
437
438multiclass VPatWidenBinaryFPSDNode_WV_WF<SDNode op, string instruction_name> {
439  foreach vtiToWti = AllWidenableFloatVectors in {
440    defvar vti = vtiToWti.Vti;
441    defvar wti = vtiToWti.Wti;
442    def : Pat<(op (wti.Vector wti.RegClass:$rs2),
443                  (wti.Vector (riscv_fpextend_vl_oneuse
444                                   (vti.Vector vti.RegClass:$rs1),
445                                   (vti.Mask true_mask), (XLenVT srcvalue)))),
446              (!cast<Instruction>(instruction_name#"_WV_"#vti.LMul.MX)
447                 wti.RegClass:$rs2, vti.RegClass:$rs1, vti.AVL, vti.Log2SEW)>;
448    def : Pat<(op (wti.Vector wti.RegClass:$rs2),
449                  (wti.Vector (riscv_fpextend_vl_oneuse
450                                   (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
451                                   (vti.Mask true_mask), (XLenVT srcvalue)))),
452              (!cast<Instruction>(instruction_name#"_W"#vti.ScalarSuffix#"_"#vti.LMul.MX)
453                 wti.RegClass:$rs2, vti.ScalarRegClass:$rs1, vti.AVL, vti.Log2SEW)>;
454    def : Pat<(op (wti.Vector wti.RegClass:$rs2),
455                  (wti.Vector (SplatFPOp (fpext_oneuse vti.ScalarRegClass:$rs1)))),
456              (!cast<Instruction>(instruction_name#"_W"#vti.ScalarSuffix#"_"#vti.LMul.MX)
457                 wti.RegClass:$rs2, vti.ScalarRegClass:$rs1, vti.AVL, vti.Log2SEW)>;
458  }
459}
460
461multiclass VPatWidenBinaryFPSDNode_VV_VF_WV_WF<SDNode op, string instruction_name> {
462  defm : VPatWidenBinaryFPSDNode_VV_VF<op, instruction_name>;
463  defm : VPatWidenBinaryFPSDNode_WV_WF<op, instruction_name>;
464}
465
466multiclass VPatWidenFPMulAccSDNode_VV_VF<string instruction_name> {
467  foreach vtiToWti = AllWidenableFloatVectors in {
468    defvar vti = vtiToWti.Vti;
469    defvar wti = vtiToWti.Wti;
470    def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse
471                                    (vti.Vector vti.RegClass:$rs1),
472                                    (vti.Mask true_mask), (XLenVT srcvalue))),
473                   (wti.Vector (riscv_fpextend_vl_oneuse
474                                    (vti.Vector vti.RegClass:$rs2),
475                                    (vti.Mask true_mask), (XLenVT srcvalue))),
476                   (wti.Vector wti.RegClass:$rd)),
477              (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
478                 wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
479                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
480    def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse
481                                    (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
482                                    (vti.Mask true_mask), (XLenVT srcvalue))),
483                   (wti.Vector (riscv_fpextend_vl_oneuse
484                                    (vti.Vector vti.RegClass:$rs2),
485                                    (vti.Mask true_mask), (XLenVT srcvalue))),
486                   (wti.Vector wti.RegClass:$rd)),
487              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
488                 wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
489                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
490  }
491}
492
493multiclass VPatWidenFPNegMulAccSDNode_VV_VF<string instruction_name> {
494  foreach vtiToWti = AllWidenableFloatVectors in {
495    defvar vti = vtiToWti.Vti;
496    defvar wti = vtiToWti.Wti;
497    def : Pat<(fma (fneg (wti.Vector (riscv_fpextend_vl_oneuse
498                                          (vti.Vector vti.RegClass:$rs1),
499                                          (vti.Mask true_mask), (XLenVT srcvalue)))),
500                   (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2),
501                                             (vti.Mask true_mask), (XLenVT srcvalue)),
502                   (fneg wti.RegClass:$rd)),
503              (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
504                 wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
505                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
506    def : Pat<(fma (riscv_fpextend_vl_oneuse
507                        (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
508                        (vti.Mask true_mask), (XLenVT srcvalue)),
509                   (fneg (wti.Vector (riscv_fpextend_vl_oneuse
510                                          (vti.Vector vti.RegClass:$rs2),
511                                          (vti.Mask true_mask), (XLenVT srcvalue)))),
512                   (fneg wti.RegClass:$rd)),
513              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
514                 wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
515                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
516    def : Pat<(fma (fneg (wti.Vector (riscv_fpextend_vl_oneuse
517                                          (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
518                                          (vti.Mask true_mask), (XLenVT srcvalue)))),
519                   (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2),
520                                             (vti.Mask true_mask), (XLenVT srcvalue)),
521                   (fneg wti.RegClass:$rd)),
522              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
523                 wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
524                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
525  }
526}
527
528multiclass VPatWidenFPMulSacSDNode_VV_VF<string instruction_name> {
529  foreach vtiToWti = AllWidenableFloatVectors in {
530    defvar vti = vtiToWti.Vti;
531    defvar wti = vtiToWti.Wti;
532    def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse
533                                    (vti.Vector vti.RegClass:$rs1),
534                                    (vti.Mask true_mask), (XLenVT srcvalue))),
535                   (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2),
536                                             (vti.Mask true_mask), (XLenVT srcvalue)),
537                   (fneg wti.RegClass:$rd)),
538              (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
539                 wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
540                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
541    def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse
542                                    (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
543                                    (vti.Mask true_mask), (XLenVT srcvalue))),
544                   (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2),
545                                             (vti.Mask true_mask), (XLenVT srcvalue)),
546                   (fneg wti.RegClass:$rd)),
547              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
548                 wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
549                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
550  }
551}
552
553multiclass VPatWidenFPNegMulSacSDNode_VV_VF<string instruction_name> {
554  foreach vtiToWti = AllWidenableFloatVectors in {
555    defvar vti = vtiToWti.Vti;
556    defvar wti = vtiToWti.Wti;
557    def : Pat<(fma (fneg (wti.Vector (riscv_fpextend_vl_oneuse
558                                          (vti.Vector vti.RegClass:$rs1),
559                                          (vti.Mask true_mask), (XLenVT srcvalue)))),
560                   (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2),
561                                             (vti.Mask true_mask), (XLenVT srcvalue)),
562                   wti.RegClass:$rd),
563              (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX)
564                 wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
565                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
566    def : Pat<(fma (wti.Vector (riscv_fpextend_vl_oneuse
567                                    (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
568                                    (vti.Mask true_mask), (XLenVT srcvalue))),
569                   (fneg (wti.Vector (riscv_fpextend_vl_oneuse
570                                          (vti.Vector vti.RegClass:$rs2),
571                                          (vti.Mask true_mask), (XLenVT srcvalue)))),
572                   wti.RegClass:$rd),
573              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
574                 wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
575                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
576    def : Pat<(fma (fneg (wti.Vector (riscv_fpextend_vl_oneuse
577                                          (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
578                                          (vti.Mask true_mask), (XLenVT srcvalue)))),
579                   (riscv_fpextend_vl_oneuse (vti.Vector vti.RegClass:$rs2),
580                                             (vti.Mask true_mask), (XLenVT srcvalue)),
581                   wti.RegClass:$rd),
582              (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
583                 wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
584                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
585  }
586}
587
588multiclass VPatMultiplyAddSDNode_VV_VX<SDNode op, string instruction_name> {
589  foreach vti = AllIntegerVectors in {
590    defvar suffix = vti.LMul.MX;
591    // NOTE: We choose VMADD because it has the most commuting freedom. So it
592    // works best with how TwoAddressInstructionPass tries commuting.
593    def : Pat<(vti.Vector (op vti.RegClass:$rs2,
594                              (mul_oneuse vti.RegClass:$rs1, vti.RegClass:$rd))),
595              (!cast<Instruction>(instruction_name#"_VV_"# suffix)
596                 vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
597                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
598    // The choice of VMADD here is arbitrary, vmadd.vx and vmacc.vx are equally
599    // commutable.
600    def : Pat<(vti.Vector (op vti.RegClass:$rs2,
601                              (mul_oneuse (SplatPat XLenVT:$rs1), vti.RegClass:$rd))),
602              (!cast<Instruction>(instruction_name#"_VX_" # suffix)
603                 vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
604                 vti.AVL, vti.Log2SEW, TAIL_AGNOSTIC)>;
605  }
606}
607
608//===----------------------------------------------------------------------===//
609// Patterns.
610//===----------------------------------------------------------------------===//
611
612let Predicates = [HasVInstructions] in {
613
614// 7.4. Vector Unit-Stride Instructions
615foreach vti = !listconcat(FractionalGroupIntegerVectors,
616                          FractionalGroupFloatVectors) in
617  defm : VPatUSLoadStoreSDNode<vti.Vector, vti.Log2SEW, vti.LMul,
618                               vti.AVL, vti.RegClass>;
619foreach vti = [VI8M1, VI16M1, VI32M1, VI64M1, VF16M1, VF32M1, VF64M1] in
620  defm : VPatUSLoadStoreWholeVRSDNode<vti.Vector, vti.Log2SEW, vti.LMul,
621                                      vti.RegClass>;
622foreach vti = !listconcat(GroupIntegerVectors, GroupFloatVectors) in
623  defm : VPatUSLoadStoreWholeVRSDNode<vti.Vector, vti.Log2SEW, vti.LMul,
624                                      vti.RegClass>;
625foreach mti = AllMasks in
626  defm : VPatUSLoadStoreMaskSDNode<mti>;
627
628// 12.1. Vector Single-Width Integer Add and Subtract
629defm : VPatBinarySDNode_VV_VX_VI<add, "PseudoVADD">;
630defm : VPatBinarySDNode_VV_VX<sub, "PseudoVSUB">;
631// Handle VRSUB specially since it's the only integer binary op with reversed
632// pattern operands
633foreach vti = AllIntegerVectors in {
634  def : Pat<(sub (vti.Vector (SplatPat GPR:$rs2)),
635                 (vti.Vector vti.RegClass:$rs1)),
636            (!cast<Instruction>("PseudoVRSUB_VX_"# vti.LMul.MX)
637                 vti.RegClass:$rs1, GPR:$rs2, vti.AVL, vti.Log2SEW)>;
638  def : Pat<(sub (vti.Vector (SplatPat_simm5 simm5:$rs2)),
639                 (vti.Vector vti.RegClass:$rs1)),
640            (!cast<Instruction>("PseudoVRSUB_VI_"# vti.LMul.MX)
641                 vti.RegClass:$rs1, simm5:$rs2, vti.AVL, vti.Log2SEW)>;
642}
643
644// 12.2. Vector Widening Integer Add and Subtract
645defm : VPatWidenBinarySDNode_VV_VX_WV_WX<add, sext_oneuse, "PseudoVWADD">;
646defm : VPatWidenBinarySDNode_VV_VX_WV_WX<add, zext_oneuse, "PseudoVWADDU">;
647defm : VPatWidenBinarySDNode_VV_VX_WV_WX<add, anyext_oneuse, "PseudoVWADDU">;
648
649defm : VPatWidenBinarySDNode_VV_VX_WV_WX<sub, sext_oneuse, "PseudoVWSUB">;
650defm : VPatWidenBinarySDNode_VV_VX_WV_WX<sub, zext_oneuse, "PseudoVWSUBU">;
651defm : VPatWidenBinarySDNode_VV_VX_WV_WX<sub, anyext_oneuse, "PseudoVWSUBU">;
652
653// 12.3. Vector Integer Extension
654defm : VPatExtendSDNode_V<[zext, anyext], "PseudoVZEXT", "VF2",
655                          AllFractionableVF2IntVectors>;
656defm : VPatExtendSDNode_V<[sext],         "PseudoVSEXT", "VF2",
657                          AllFractionableVF2IntVectors>;
658defm : VPatExtendSDNode_V<[zext, anyext], "PseudoVZEXT", "VF4",
659                          AllFractionableVF4IntVectors>;
660defm : VPatExtendSDNode_V<[sext],         "PseudoVSEXT", "VF4",
661                          AllFractionableVF4IntVectors>;
662defm : VPatExtendSDNode_V<[zext, anyext], "PseudoVZEXT", "VF8",
663                          AllFractionableVF8IntVectors>;
664defm : VPatExtendSDNode_V<[sext],         "PseudoVSEXT", "VF8",
665                          AllFractionableVF8IntVectors>;
666
667// 12.5. Vector Bitwise Logical Instructions
668defm : VPatBinarySDNode_VV_VX_VI<and, "PseudoVAND">;
669defm : VPatBinarySDNode_VV_VX_VI<or, "PseudoVOR">;
670defm : VPatBinarySDNode_VV_VX_VI<xor, "PseudoVXOR">;
671
672// 12.6. Vector Single-Width Bit Shift Instructions
673defm : VPatBinarySDNode_VV_VX_VI<shl, "PseudoVSLL", uimm5>;
674defm : VPatBinarySDNode_VV_VX_VI<srl, "PseudoVSRL", uimm5>;
675defm : VPatBinarySDNode_VV_VX_VI<sra, "PseudoVSRA", uimm5>;
676
677foreach vti = AllIntegerVectors in {
678  // Emit shift by 1 as an add since it might be faster.
679  def : Pat<(shl (vti.Vector vti.RegClass:$rs1),
680                 (vti.Vector (riscv_vmv_v_x_vl (vti.Vector undef), 1, (XLenVT srcvalue)))),
681            (!cast<Instruction>("PseudoVADD_VV_"# vti.LMul.MX)
682                 vti.RegClass:$rs1, vti.RegClass:$rs1, vti.AVL, vti.Log2SEW)>;
683
684}
685
686// 12.8. Vector Integer Comparison Instructions
687defm : VPatIntegerSetCCSDNode_VV<"PseudoVMSEQ", SETEQ>;
688defm : VPatIntegerSetCCSDNode_VV<"PseudoVMSNE", SETNE>;
689
690defm : VPatIntegerSetCCSDNode_VV_Swappable<"PseudoVMSLT",  SETLT, SETGT>;
691defm : VPatIntegerSetCCSDNode_VV_Swappable<"PseudoVMSLTU", SETULT, SETUGT>;
692defm : VPatIntegerSetCCSDNode_VV_Swappable<"PseudoVMSLE",  SETLE,  SETGE>;
693defm : VPatIntegerSetCCSDNode_VV_Swappable<"PseudoVMSLEU", SETULE, SETUGE>;
694
695defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSEQ",  SETEQ,  SETEQ>;
696defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSNE",  SETNE,  SETNE>;
697defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSLT",  SETLT,  SETGT>;
698defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSLTU", SETULT, SETUGT>;
699defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSLE",  SETLE,  SETGE>;
700defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSLEU", SETULE, SETUGE>;
701defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSGT",  SETGT,  SETLT>;
702defm : VPatIntegerSetCCSDNode_VX_Swappable<"PseudoVMSGTU", SETUGT, SETULT>;
703// There is no VMSGE(U)_VX instruction
704
705defm : VPatIntegerSetCCSDNode_VI<"PseudoVMSEQ",  SETEQ>;
706defm : VPatIntegerSetCCSDNode_VI<"PseudoVMSNE",  SETNE>;
707defm : VPatIntegerSetCCSDNode_VI<"PseudoVMSLE",  SETLE>;
708defm : VPatIntegerSetCCSDNode_VI<"PseudoVMSLEU", SETULE>;
709defm : VPatIntegerSetCCSDNode_VI<"PseudoVMSGT",  SETGT>;
710defm : VPatIntegerSetCCSDNode_VI<"PseudoVMSGTU", SETUGT>;
711
712defm : VPatIntegerSetCCSDNode_VIPlus1<"PseudoVMSLE", SETLT,
713                                      SplatPat_simm5_plus1_nonzero>;
714defm : VPatIntegerSetCCSDNode_VIPlus1<"PseudoVMSLEU", SETULT,
715                                      SplatPat_simm5_plus1_nonzero>;
716defm : VPatIntegerSetCCSDNode_VIPlus1<"PseudoVMSGT", SETGE,
717                                      SplatPat_simm5_plus1>;
718defm : VPatIntegerSetCCSDNode_VIPlus1<"PseudoVMSGTU", SETUGE,
719                                      SplatPat_simm5_plus1_nonzero>;
720
721// 12.9. Vector Integer Min/Max Instructions
722defm : VPatBinarySDNode_VV_VX<umin, "PseudoVMINU">;
723defm : VPatBinarySDNode_VV_VX<smin, "PseudoVMIN">;
724defm : VPatBinarySDNode_VV_VX<umax, "PseudoVMAXU">;
725defm : VPatBinarySDNode_VV_VX<smax, "PseudoVMAX">;
726
727// 12.10. Vector Single-Width Integer Multiply Instructions
728defm : VPatBinarySDNode_VV_VX<mul, "PseudoVMUL">;
729defm : VPatBinarySDNode_VV_VX<mulhs, "PseudoVMULH">;
730defm : VPatBinarySDNode_VV_VX<mulhu, "PseudoVMULHU">;
731
732// 12.11. Vector Integer Divide Instructions
733defm : VPatBinarySDNode_VV_VX<udiv, "PseudoVDIVU">;
734defm : VPatBinarySDNode_VV_VX<sdiv, "PseudoVDIV">;
735defm : VPatBinarySDNode_VV_VX<urem, "PseudoVREMU">;
736defm : VPatBinarySDNode_VV_VX<srem, "PseudoVREM">;
737
738// 12.12. Vector Widening Integer Multiply Instructions
739defm : VPatWidenBinarySDNode_VV_VX<mul, sext_oneuse, sext_oneuse,
740                                   "PseudoVWMUL">;
741defm : VPatWidenBinarySDNode_VV_VX<mul, zext_oneuse, zext_oneuse,
742                                   "PseudoVWMULU">;
743defm : VPatWidenBinarySDNode_VV_VX<mul, anyext_oneuse, anyext_oneuse,
744                                   "PseudoVWMULU">;
745defm : VPatWidenBinarySDNode_VV_VX<mul, zext_oneuse, anyext_oneuse,
746                                   "PseudoVWMULU">;
747defm : VPatWidenBinarySDNode_VV_VX<mul, sext_oneuse, zext_oneuse,
748                                   "PseudoVWMULSU">;
749defm : VPatWidenBinarySDNode_VV_VX<mul, sext_oneuse, anyext_oneuse,
750                                   "PseudoVWMULSU">;
751
752// 12.13 Vector Single-Width Integer Multiply-Add Instructions.
753defm : VPatMultiplyAddSDNode_VV_VX<add, "PseudoVMADD">;
754defm : VPatMultiplyAddSDNode_VV_VX<sub, "PseudoVNMSUB">;
755
756// 12.14 Vector Widening Integer Multiply-Add Instructions
757defm : VPatWidenMulAddSDNode_VV<sext_oneuse, sext_oneuse, "PseudoVWMACC">;
758defm : VPatWidenMulAddSDNode_VX<sext_oneuse, sext_oneuse, "PseudoVWMACC">;
759defm : VPatWidenMulAddSDNode_VV<zext_oneuse, zext_oneuse, "PseudoVWMACCU">;
760defm : VPatWidenMulAddSDNode_VX<zext_oneuse, zext_oneuse, "PseudoVWMACCU">;
761defm : VPatWidenMulAddSDNode_VV<sext_oneuse, zext_oneuse, "PseudoVWMACCSU">;
762defm : VPatWidenMulAddSDNode_VX<sext_oneuse, zext_oneuse, "PseudoVWMACCSU">;
763defm : VPatWidenMulAddSDNode_VX<zext_oneuse, sext_oneuse, "PseudoVWMACCUS">;
764
765// 12.15. Vector Integer Merge Instructions
766foreach vti = AllIntegerVectors in {
767  def : Pat<(vti.Vector (vselect (vti.Mask V0), vti.RegClass:$rs1,
768                                                      vti.RegClass:$rs2)),
769            (!cast<Instruction>("PseudoVMERGE_VVM_"#vti.LMul.MX)
770                 vti.RegClass:$rs2, vti.RegClass:$rs1, (vti.Mask V0),
771                 vti.AVL, vti.Log2SEW)>;
772
773  def : Pat<(vti.Vector (vselect (vti.Mask V0), (SplatPat XLenVT:$rs1),
774                                                      vti.RegClass:$rs2)),
775            (!cast<Instruction>("PseudoVMERGE_VXM_"#vti.LMul.MX)
776                 vti.RegClass:$rs2, GPR:$rs1, (vti.Mask V0), vti.AVL, vti.Log2SEW)>;
777
778  def : Pat<(vti.Vector (vselect (vti.Mask V0), (SplatPat_simm5 simm5:$rs1),
779                                                      vti.RegClass:$rs2)),
780            (!cast<Instruction>("PseudoVMERGE_VIM_"#vti.LMul.MX)
781                 vti.RegClass:$rs2, simm5:$rs1, (vti.Mask V0), vti.AVL, vti.Log2SEW)>;
782}
783
784// 12.1. Vector Single-Width Saturating Add and Subtract
785defm : VPatBinarySDNode_VV_VX_VI<saddsat, "PseudoVSADD">;
786defm : VPatBinarySDNode_VV_VX_VI<uaddsat, "PseudoVSADDU">;
787defm : VPatBinarySDNode_VV_VX<ssubsat, "PseudoVSSUB">;
788defm : VPatBinarySDNode_VV_VX<usubsat, "PseudoVSSUBU">;
789
790// 16.1. Vector Mask-Register Logical Instructions
791foreach mti = AllMasks in {
792  def : Pat<(mti.Mask (and VR:$rs1, VR:$rs2)),
793            (!cast<Instruction>("PseudoVMAND_MM_"#mti.LMul.MX)
794                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
795  def : Pat<(mti.Mask (or VR:$rs1, VR:$rs2)),
796            (!cast<Instruction>("PseudoVMOR_MM_"#mti.LMul.MX)
797                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
798  def : Pat<(mti.Mask (xor VR:$rs1, VR:$rs2)),
799            (!cast<Instruction>("PseudoVMXOR_MM_"#mti.LMul.MX)
800                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
801
802  def : Pat<(mti.Mask (rvv_vnot (and VR:$rs1, VR:$rs2))),
803            (!cast<Instruction>("PseudoVMNAND_MM_"#mti.LMul.MX)
804                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
805  def : Pat<(mti.Mask (rvv_vnot (or VR:$rs1, VR:$rs2))),
806            (!cast<Instruction>("PseudoVMNOR_MM_"#mti.LMul.MX)
807                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
808  def : Pat<(mti.Mask (rvv_vnot (xor VR:$rs1, VR:$rs2))),
809            (!cast<Instruction>("PseudoVMXNOR_MM_"#mti.LMul.MX)
810                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
811
812  def : Pat<(mti.Mask (and VR:$rs1, (rvv_vnot VR:$rs2))),
813            (!cast<Instruction>("PseudoVMANDN_MM_"#mti.LMul.MX)
814                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
815  def : Pat<(mti.Mask (or VR:$rs1, (rvv_vnot VR:$rs2))),
816            (!cast<Instruction>("PseudoVMORN_MM_"#mti.LMul.MX)
817                 VR:$rs1, VR:$rs2, mti.AVL, mti.Log2SEW)>;
818
819  // Handle rvv_vnot the same as the vmnot.m pseudoinstruction.
820  def : Pat<(mti.Mask (rvv_vnot VR:$rs)),
821            (!cast<Instruction>("PseudoVMNAND_MM_"#mti.LMul.MX)
822                 VR:$rs, VR:$rs, mti.AVL, mti.Log2SEW)>;
823}
824
825} // Predicates = [HasVInstructions]
826
827let Predicates = [HasVInstructionsAnyF] in {
828
829// 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions
830defm : VPatBinaryFPSDNode_VV_VF<fadd, "PseudoVFADD">;
831defm : VPatBinaryFPSDNode_VV_VF<fsub, "PseudoVFSUB">;
832defm : VPatBinaryFPSDNode_R_VF<fsub, "PseudoVFRSUB">;
833
834// 14.3. Vector Widening Floating-Point Add/Subtract Instructions
835defm : VPatWidenBinaryFPSDNode_VV_VF_WV_WF<fadd, "PseudoVFWADD">;
836defm : VPatWidenBinaryFPSDNode_VV_VF_WV_WF<fsub, "PseudoVFWSUB">;
837
838// 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions
839defm : VPatBinaryFPSDNode_VV_VF<fmul, "PseudoVFMUL">;
840defm : VPatBinaryFPSDNode_VV_VF<fdiv, "PseudoVFDIV">;
841defm : VPatBinaryFPSDNode_R_VF<fdiv, "PseudoVFRDIV">;
842
843// 14.5. Vector Widening Floating-Point Multiply Instructions
844defm : VPatWidenBinaryFPSDNode_VV_VF<fmul, "PseudoVFWMUL">;
845
846// 14.6 Vector Single-Width Floating-Point Fused Multiply-Add Instructions.
847foreach fvti = AllFloatVectors in {
848  // NOTE: We choose VFMADD because it has the most commuting freedom. So it
849  // works best with how TwoAddressInstructionPass tries commuting.
850  defvar suffix = fvti.LMul.MX;
851  def : Pat<(fvti.Vector (fma fvti.RegClass:$rs1, fvti.RegClass:$rd,
852                              fvti.RegClass:$rs2)),
853            (!cast<Instruction>("PseudoVFMADD_VV_"# suffix)
854                 fvti.RegClass:$rd, fvti.RegClass:$rs1, fvti.RegClass:$rs2,
855                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
856  def : Pat<(fvti.Vector (fma fvti.RegClass:$rs1, fvti.RegClass:$rd,
857                              (fneg fvti.RegClass:$rs2))),
858            (!cast<Instruction>("PseudoVFMSUB_VV_"# suffix)
859                 fvti.RegClass:$rd, fvti.RegClass:$rs1, fvti.RegClass:$rs2,
860                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
861  def : Pat<(fvti.Vector (fma (fneg fvti.RegClass:$rs1), fvti.RegClass:$rd,
862                              (fneg fvti.RegClass:$rs2))),
863            (!cast<Instruction>("PseudoVFNMADD_VV_"# suffix)
864                 fvti.RegClass:$rd, fvti.RegClass:$rs1, fvti.RegClass:$rs2,
865                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
866  def : Pat<(fvti.Vector (fma (fneg fvti.RegClass:$rs1), fvti.RegClass:$rd,
867                              fvti.RegClass:$rs2)),
868            (!cast<Instruction>("PseudoVFNMSUB_VV_"# suffix)
869                 fvti.RegClass:$rd, fvti.RegClass:$rs1, fvti.RegClass:$rs2,
870                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
871
872  // The choice of VFMADD here is arbitrary, vfmadd.vf and vfmacc.vf are equally
873  // commutable.
874  def : Pat<(fvti.Vector (fma (SplatFPOp fvti.ScalarRegClass:$rs1),
875                              fvti.RegClass:$rd, fvti.RegClass:$rs2)),
876            (!cast<Instruction>("PseudoVFMADD_V" # fvti.ScalarSuffix # "_" # suffix)
877                 fvti.RegClass:$rd, fvti.ScalarRegClass:$rs1, fvti.RegClass:$rs2,
878                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
879  def : Pat<(fvti.Vector (fma (SplatFPOp fvti.ScalarRegClass:$rs1),
880                              fvti.RegClass:$rd, (fneg fvti.RegClass:$rs2))),
881            (!cast<Instruction>("PseudoVFMSUB_V" # fvti.ScalarSuffix # "_" # suffix)
882                 fvti.RegClass:$rd, fvti.ScalarRegClass:$rs1, fvti.RegClass:$rs2,
883                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
884
885  def : Pat<(fvti.Vector (fma (SplatFPOp fvti.ScalarRegClass:$rs1),
886                              (fneg fvti.RegClass:$rd), (fneg fvti.RegClass:$rs2))),
887            (!cast<Instruction>("PseudoVFNMADD_V" # fvti.ScalarSuffix # "_" # suffix)
888                 fvti.RegClass:$rd, fvti.ScalarRegClass:$rs1, fvti.RegClass:$rs2,
889                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
890  def : Pat<(fvti.Vector (fma (SplatFPOp fvti.ScalarRegClass:$rs1),
891                              (fneg fvti.RegClass:$rd), fvti.RegClass:$rs2)),
892            (!cast<Instruction>("PseudoVFNMSUB_V" # fvti.ScalarSuffix # "_" # suffix)
893                 fvti.RegClass:$rd, fvti.ScalarRegClass:$rs1, fvti.RegClass:$rs2,
894                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
895
896  // The splat might be negated.
897  def : Pat<(fvti.Vector (fma (fneg (SplatFPOp fvti.ScalarRegClass:$rs1)),
898                              fvti.RegClass:$rd, (fneg fvti.RegClass:$rs2))),
899            (!cast<Instruction>("PseudoVFNMADD_V" # fvti.ScalarSuffix # "_" # suffix)
900                 fvti.RegClass:$rd, fvti.ScalarRegClass:$rs1, fvti.RegClass:$rs2,
901                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
902  def : Pat<(fvti.Vector (fma (fneg (SplatFPOp fvti.ScalarRegClass:$rs1)),
903                              fvti.RegClass:$rd, fvti.RegClass:$rs2)),
904            (!cast<Instruction>("PseudoVFNMSUB_V" # fvti.ScalarSuffix # "_" # suffix)
905                 fvti.RegClass:$rd, fvti.ScalarRegClass:$rs1, fvti.RegClass:$rs2,
906                 fvti.AVL, fvti.Log2SEW, TAIL_AGNOSTIC)>;
907}
908
909// 14.7. Vector Widening Floating-Point Fused Multiply-Add Instructions
910defm : VPatWidenFPMulAccSDNode_VV_VF<"PseudoVFWMACC">;
911defm : VPatWidenFPNegMulAccSDNode_VV_VF<"PseudoVFWNMACC">;
912defm : VPatWidenFPMulSacSDNode_VV_VF<"PseudoVFWMSAC">;
913defm : VPatWidenFPNegMulSacSDNode_VV_VF<"PseudoVFWNMSAC">;
914
915foreach vti = AllFloatVectors in {
916  // 14.8. Vector Floating-Point Square-Root Instruction
917  def : Pat<(fsqrt (vti.Vector vti.RegClass:$rs2)),
918            (!cast<Instruction>("PseudoVFSQRT_V_"# vti.LMul.MX)
919                 vti.RegClass:$rs2, vti.AVL, vti.Log2SEW)>;
920
921  // 14.12. Vector Floating-Point Sign-Injection Instructions
922  def : Pat<(fabs (vti.Vector vti.RegClass:$rs)),
923            (!cast<Instruction>("PseudoVFSGNJX_VV_"# vti.LMul.MX)
924                 vti.RegClass:$rs, vti.RegClass:$rs, vti.AVL, vti.Log2SEW)>;
925  // Handle fneg with VFSGNJN using the same input for both operands.
926  def : Pat<(fneg (vti.Vector vti.RegClass:$rs)),
927            (!cast<Instruction>("PseudoVFSGNJN_VV_"# vti.LMul.MX)
928                 vti.RegClass:$rs, vti.RegClass:$rs, vti.AVL, vti.Log2SEW)>;
929
930  def : Pat<(vti.Vector (fcopysign (vti.Vector vti.RegClass:$rs1),
931                                   (vti.Vector vti.RegClass:$rs2))),
932            (!cast<Instruction>("PseudoVFSGNJ_VV_"# vti.LMul.MX)
933                 vti.RegClass:$rs1, vti.RegClass:$rs2, vti.AVL, vti.Log2SEW)>;
934  def : Pat<(vti.Vector (fcopysign (vti.Vector vti.RegClass:$rs1),
935                                   (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs2)))),
936            (!cast<Instruction>("PseudoVFSGNJ_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
937                 vti.RegClass:$rs1, vti.ScalarRegClass:$rs2, vti.AVL, vti.Log2SEW)>;
938
939  def : Pat<(vti.Vector (fcopysign (vti.Vector vti.RegClass:$rs1),
940                                   (vti.Vector (fneg vti.RegClass:$rs2)))),
941            (!cast<Instruction>("PseudoVFSGNJN_VV_"# vti.LMul.MX)
942                 vti.RegClass:$rs1, vti.RegClass:$rs2, vti.AVL, vti.Log2SEW)>;
943  def : Pat<(vti.Vector (fcopysign (vti.Vector vti.RegClass:$rs1),
944                                   (vti.Vector (fneg (SplatFPOp vti.ScalarRegClass:$rs2))))),
945            (!cast<Instruction>("PseudoVFSGNJN_V"#vti.ScalarSuffix#"_"#vti.LMul.MX)
946                 vti.RegClass:$rs1, vti.ScalarRegClass:$rs2, vti.AVL, vti.Log2SEW)>;
947}
948
949// 14.11. Vector Floating-Point MIN/MAX Instructions
950defm : VPatBinaryFPSDNode_VV_VF<fminnum, "PseudoVFMIN">;
951defm : VPatBinaryFPSDNode_VV_VF<fmaxnum, "PseudoVFMAX">;
952
953// 14.13. Vector Floating-Point Compare Instructions
954defm : VPatFPSetCCSDNode_VV_VF_FV<SETEQ,  "PseudoVMFEQ", "PseudoVMFEQ">;
955defm : VPatFPSetCCSDNode_VV_VF_FV<SETOEQ, "PseudoVMFEQ", "PseudoVMFEQ">;
956
957defm : VPatFPSetCCSDNode_VV_VF_FV<SETNE,  "PseudoVMFNE", "PseudoVMFNE">;
958defm : VPatFPSetCCSDNode_VV_VF_FV<SETUNE, "PseudoVMFNE", "PseudoVMFNE">;
959
960defm : VPatFPSetCCSDNode_VV_VF_FV<SETLT,  "PseudoVMFLT", "PseudoVMFGT">;
961defm : VPatFPSetCCSDNode_VV_VF_FV<SETOLT, "PseudoVMFLT", "PseudoVMFGT">;
962
963defm : VPatFPSetCCSDNode_VV_VF_FV<SETLE,  "PseudoVMFLE", "PseudoVMFGE">;
964defm : VPatFPSetCCSDNode_VV_VF_FV<SETOLE, "PseudoVMFLE", "PseudoVMFGE">;
965
966// Floating-point vselects:
967// 12.15. Vector Integer Merge Instructions
968// 14.15. Vector Floating-Point Merge Instruction
969foreach fvti = AllFloatVectors in {
970  def : Pat<(fvti.Vector (vselect (fvti.Mask V0), fvti.RegClass:$rs1,
971                                                        fvti.RegClass:$rs2)),
972            (!cast<Instruction>("PseudoVMERGE_VVM_"#fvti.LMul.MX)
973                 fvti.RegClass:$rs2, fvti.RegClass:$rs1, (fvti.Mask V0),
974                 fvti.AVL, fvti.Log2SEW)>;
975
976  def : Pat<(fvti.Vector (vselect (fvti.Mask V0),
977                                  (SplatFPOp fvti.ScalarRegClass:$rs1),
978                                  fvti.RegClass:$rs2)),
979            (!cast<Instruction>("PseudoVFMERGE_V"#fvti.ScalarSuffix#"M_"#fvti.LMul.MX)
980                 fvti.RegClass:$rs2,
981                 (fvti.Scalar fvti.ScalarRegClass:$rs1),
982                 (fvti.Mask V0), fvti.AVL, fvti.Log2SEW)>;
983
984  def : Pat<(fvti.Vector (vselect (fvti.Mask V0),
985                                  (SplatFPOp (fvti.Scalar fpimm0)),
986                                  fvti.RegClass:$rs2)),
987            (!cast<Instruction>("PseudoVMERGE_VIM_"#fvti.LMul.MX)
988                 fvti.RegClass:$rs2, 0, (fvti.Mask V0), fvti.AVL, fvti.Log2SEW)>;
989}
990
991// 14.17. Vector Single-Width Floating-Point/Integer Type-Convert Instructions
992defm : VPatConvertFP2ISDNode_V<fp_to_sint, "PseudoVFCVT_RTZ_X_F_V">;
993defm : VPatConvertFP2ISDNode_V<fp_to_uint, "PseudoVFCVT_RTZ_XU_F_V">;
994defm : VPatConvertI2FPSDNode_V<sint_to_fp, "PseudoVFCVT_F_X_V">;
995defm : VPatConvertI2FPSDNode_V<uint_to_fp, "PseudoVFCVT_F_XU_V">;
996
997// 14.18. Widening Floating-Point/Integer Type-Convert Instructions
998defm : VPatWConvertFP2ISDNode_V<fp_to_sint, "PseudoVFWCVT_RTZ_X_F_V">;
999defm : VPatWConvertFP2ISDNode_V<fp_to_uint, "PseudoVFWCVT_RTZ_XU_F_V">;
1000defm : VPatWConvertI2FPSDNode_V<sint_to_fp, "PseudoVFWCVT_F_X_V">;
1001defm : VPatWConvertI2FPSDNode_V<uint_to_fp, "PseudoVFWCVT_F_XU_V">;
1002
1003// 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions
1004defm : VPatNConvertFP2ISDNode_V<fp_to_sint, "PseudoVFNCVT_RTZ_X_F_W">;
1005defm : VPatNConvertFP2ISDNode_V<fp_to_uint, "PseudoVFNCVT_RTZ_XU_F_W">;
1006defm : VPatNConvertI2FPSDNode_V<sint_to_fp, "PseudoVFNCVT_F_X_W">;
1007defm : VPatNConvertI2FPSDNode_V<uint_to_fp, "PseudoVFNCVT_F_XU_W">;
1008foreach fvtiToFWti = AllWidenableFloatVectors in {
1009  defvar fvti = fvtiToFWti.Vti;
1010  defvar fwti = fvtiToFWti.Wti;
1011  def : Pat<(fvti.Vector (fpround (fwti.Vector fwti.RegClass:$rs1))),
1012            (!cast<Instruction>("PseudoVFNCVT_F_F_W_"#fvti.LMul.MX)
1013                fwti.RegClass:$rs1, fvti.AVL, fvti.Log2SEW)>;
1014}
1015} // Predicates = [HasVInstructionsAnyF]
1016
1017//===----------------------------------------------------------------------===//
1018// Vector Splats
1019//===----------------------------------------------------------------------===//
1020
1021let Predicates = [HasVInstructionsAnyF] in {
1022foreach fvti = AllFloatVectors in {
1023  def : Pat<(fvti.Vector (SplatFPOp fvti.ScalarRegClass:$rs1)),
1024            (!cast<Instruction>("PseudoVFMV_V_"#fvti.ScalarSuffix#"_"#fvti.LMul.MX)
1025              (fvti.Scalar fvti.ScalarRegClass:$rs1),
1026              fvti.AVL, fvti.Log2SEW)>;
1027
1028  def : Pat<(fvti.Vector (SplatFPOp (fvti.Scalar fpimm0))),
1029            (!cast<Instruction>("PseudoVMV_V_I_"#fvti.LMul.MX)
1030              0, fvti.AVL, fvti.Log2SEW)>;
1031}
1032} // Predicates = [HasVInstructionsAnyF]
1033
1034//===----------------------------------------------------------------------===//
1035// Vector Element Extracts
1036//===----------------------------------------------------------------------===//
1037let Predicates = [HasVInstructionsAnyF] in
1038foreach vti = AllFloatVectors in {
1039  // Fold store of vmv.f.s to a vse with VL=1.
1040  defvar store_instr = !cast<Instruction>("PseudoVSE"#vti.SEW#"_V_"#vti.LMul.MX);
1041
1042  let AddedComplexity = 2 in {
1043  // Add complexity to increase the priority of this pattern being matched.
1044  def : Pat<(store (vti.Scalar (int_riscv_vfmv_f_s (vti.Vector vti.RegClass:$rs2))), GPR:$rs1),
1045            (store_instr vti.RegClass:$rs2, GPR:$rs1, 1, vti.Log2SEW)>;
1046  def : Pat<(store (extractelt (vti.Vector vti.RegClass:$rs2), 0), GPR:$rs1),
1047            (store_instr vti.RegClass:$rs2, GPR:$rs1, 1, vti.Log2SEW)>;
1048  }
1049
1050  defvar vmv_f_s_inst = !cast<Instruction>(!strconcat("PseudoVFMV_",
1051                                                       vti.ScalarSuffix,
1052                                                       "_S_", vti.LMul.MX));
1053  // Only pattern-match extract-element operations where the index is 0. Any
1054  // other index will have been custom-lowered to slide the vector correctly
1055  // into place.
1056  def : Pat<(vti.Scalar (extractelt (vti.Vector vti.RegClass:$rs2), 0)),
1057            (vmv_f_s_inst vti.RegClass:$rs2, vti.Log2SEW)>;
1058}
1059