xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td (revision 700637cbb5e582861067a11aaca4d053546871d2)
1//===- RISCVInstrInfoVVLPatterns.td - RVV VL 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 VL 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// Splats an 64-bit value that has been split into two i32 parts. This is
21// expanded late to two scalar stores and a stride 0 vector load.
22// The first operand is passthru operand.
23//
24// This is only present to generate the correct TableGen SDNode description,
25// it is lowered before instruction selection.
26// FIXME: I'm not sure the types here are entirely correct.
27// Returns a vector. Operand 0 is a passthru, operand 1 and 2 are i32 scalars, operand 3 is VL
28def riscv_splat_vector_split_i64_vl : RVSDNode<"SPLAT_VECTOR_SPLIT_I64_VL",
29                                               SDTypeProfile<1, 4, [SDTCisVec<0>,
30                                                                    SDTCVecEltisVT<0, i64>,
31                                                                    SDTCisSameAs<1, 0>,
32                                                                    SDTCisVT<2, i32>,
33                                                                    SDTCisVT<3, i32>,
34                                                                    SDTCisVT<4, XLenVT>]>>;
35
36// RISC-V vector tuple type version of INSERT_SUBVECTOR/EXTRACT_SUBVECTOR.
37def riscv_tuple_insert : RVSDNode<"TUPLE_INSERT",
38                                  SDTypeProfile<1, 3, [SDTCisSameAs<1, 0>,
39                                                       SDTCisVec<2>,
40                                                       SDTCisVT<3, i32>]>>;
41def riscv_tuple_extract : RVSDNode<"TUPLE_EXTRACT",
42                                   SDTypeProfile<1, 2, [SDTCisVec<0>,
43                                                        SDTCisVT<2, i32>]>>;
44
45
46//===----------------------------------------------------------------------===//
47// Helpers to define the VL patterns.
48//===----------------------------------------------------------------------===//
49
50def SDT_RISCVIntUnOp_VL : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
51                                               SDTCisSameAs<0, 2>,
52                                               SDTCisVec<0>, SDTCisInt<0>,
53                                               SDTCVecEltisVT<3, i1>,
54                                               SDTCisSameNumEltsAs<0, 3>,
55                                               SDTCisVT<4, XLenVT>]>;
56
57def SDT_RISCVIntBinOp_VL : SDTypeProfile<1, 5, [SDTCisSameAs<0, 1>,
58                                                SDTCisSameAs<0, 2>,
59                                                SDTCisVec<0>, SDTCisInt<0>,
60                                                SDTCisSameAs<0, 3>,
61                                                SDTCVecEltisVT<4, i1>,
62                                                SDTCisSameNumEltsAs<0, 4>,
63                                                SDTCisVT<5, XLenVT>]>;
64
65// Input: (vector, vector/scalar, passthru, mask, roundmode, vl)
66def SDT_RISCVVNBinOp_RM_VL : SDTypeProfile<1, 6, [SDTCisVec<0>, SDTCisInt<0>,
67                                                  SDTCisSameAs<0, 3>,
68                                                  SDTCisSameNumEltsAs<0, 1>,
69                                                  SDTCisVec<1>,
70                                                  SDTCisOpSmallerThanOp<2, 1>,
71                                                  SDTCisSameAs<0, 2>,
72                                                  SDTCisSameNumEltsAs<0, 4>,
73                                                  SDTCVecEltisVT<4, i1>,
74                                                  SDTCisVT<5, XLenVT>,
75                                                  SDTCisVT<6, XLenVT>]>;
76
77def SDT_RISCVFPUnOp_VL : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
78                                              SDTCisVec<0>, SDTCisFP<0>,
79                                              SDTCVecEltisVT<2, i1>,
80                                              SDTCisSameNumEltsAs<0, 2>,
81                                              SDTCisVT<3, XLenVT>]>;
82def SDT_RISCVFPBinOp_VL : SDTypeProfile<1, 5, [SDTCisSameAs<0, 1>,
83                                               SDTCisSameAs<0, 2>,
84                                               SDTCisVec<0>, SDTCisFP<0>,
85                                               SDTCisSameAs<0, 3>,
86                                               SDTCVecEltisVT<4, i1>,
87                                               SDTCisSameNumEltsAs<0, 4>,
88                                               SDTCisVT<5, XLenVT>]>;
89
90def SDT_RISCVCopySign_VL : SDTypeProfile<1, 5, [SDTCisSameAs<0, 1>,
91                                                SDTCisSameAs<0, 2>,
92                                                SDTCisVec<0>, SDTCisFP<0>,
93                                                SDTCisSameAs<0, 3>,
94                                                SDTCVecEltisVT<4, i1>,
95                                                SDTCisSameNumEltsAs<0, 4>,
96                                                SDTCisVT<5, XLenVT>]>;
97
98// VMV_V_V_VL matches the semantics of vmv.v.v but includes an extra operand
99// for the VL value to be used for the operation. The first operand is
100// passthru operand.
101def riscv_vmv_v_v_vl : RVSDNode<"VMV_V_V_VL",
102                                SDTypeProfile<1, 3, [SDTCisVec<0>,
103                                                     SDTCisSameAs<0, 1>,
104                                                     SDTCisSameAs<0, 2>,
105                                                     SDTCisVT<3, XLenVT>]>>;
106
107// VMV_V_X_VL matches the semantics of vmv.v.x but includes an extra operand
108// for the VL value to be used for the operation. The first operand is
109// passthru operand.
110def riscv_vmv_v_x_vl : RVSDNode<"VMV_V_X_VL",
111                                SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisInt<0>,
112                                                     SDTCisSameAs<0, 1>,
113                                                     SDTCisVT<2, XLenVT>,
114                                                     SDTCisVT<3, XLenVT>]>>;
115
116// VFMV_V_F_VL matches the semantics of vfmv.v.f but includes an extra operand
117// for the VL value to be used for the operation. The first operand is
118// passthru operand.
119def riscv_vfmv_v_f_vl : RVSDNode<"VFMV_V_F_VL",
120                                 SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisFP<0>,
121                                                      SDTCisSameAs<0, 1>,
122                                                      SDTCisEltOfVec<2, 0>,
123                                                      SDTCisVT<3, XLenVT>]>>;
124
125// VMV_S_X_VL matches the semantics of vmv.s.x. It carries a VL operand.
126def riscv_vmv_s_x_vl : RVSDNode<"VMV_S_X_VL",
127                                SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
128                                                     SDTCisInt<0>,
129                                                     SDTCisVT<2, XLenVT>,
130                                                     SDTCisVT<3, XLenVT>]>>;
131
132// VFMV_S_F_VL matches the semantics of vfmv.s.f. It carries a VL operand.
133def riscv_vfmv_s_f_vl : RVSDNode<"VFMV_S_F_VL",
134                                 SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
135                                                       SDTCisFP<0>,
136                                                       SDTCisEltOfVec<2, 0>,
137                                                       SDTCisVT<3, XLenVT>]>>;
138
139// Vector binary ops with a passthru as a third operand, a mask as a fourth
140// operand, and VL as a fifth operand.
141let HasPassthruOp = true, HasMaskOp = true in {
142  def riscv_add_vl   : RVSDNode<"ADD_VL",   SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
143  def riscv_sub_vl   : RVSDNode<"SUB_VL",   SDT_RISCVIntBinOp_VL>;
144  def riscv_mul_vl   : RVSDNode<"MUL_VL",   SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
145  def riscv_mulhs_vl : RVSDNode<"MULHS_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
146  def riscv_mulhu_vl : RVSDNode<"MULHU_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
147  def riscv_and_vl   : RVSDNode<"AND_VL",   SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
148  def riscv_or_vl    : RVSDNode<"OR_VL",    SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
149  def riscv_xor_vl   : RVSDNode<"XOR_VL",   SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
150  def riscv_sdiv_vl  : RVSDNode<"SDIV_VL",  SDT_RISCVIntBinOp_VL>;
151  def riscv_srem_vl  : RVSDNode<"SREM_VL",  SDT_RISCVIntBinOp_VL>;
152  def riscv_udiv_vl  : RVSDNode<"UDIV_VL",  SDT_RISCVIntBinOp_VL>;
153  def riscv_urem_vl  : RVSDNode<"UREM_VL",  SDT_RISCVIntBinOp_VL>;
154  def riscv_shl_vl   : RVSDNode<"SHL_VL",   SDT_RISCVIntBinOp_VL>;
155  def riscv_sra_vl   : RVSDNode<"SRA_VL",   SDT_RISCVIntBinOp_VL>;
156  def riscv_srl_vl   : RVSDNode<"SRL_VL",   SDT_RISCVIntBinOp_VL>;
157  def riscv_rotl_vl  : RVSDNode<"ROTL_VL",  SDT_RISCVIntBinOp_VL>;
158  def riscv_rotr_vl  : RVSDNode<"ROTR_VL",  SDT_RISCVIntBinOp_VL>;
159  def riscv_smin_vl  : RVSDNode<"SMIN_VL",  SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
160  def riscv_smax_vl  : RVSDNode<"SMAX_VL",  SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
161  def riscv_umin_vl  : RVSDNode<"UMIN_VL",  SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
162  def riscv_umax_vl  : RVSDNode<"UMAX_VL",  SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
163
164  def riscv_bitreverse_vl : RVSDNode<"BITREVERSE_VL", SDT_RISCVIntUnOp_VL>;
165  def riscv_bswap_vl      : RVSDNode<"BSWAP_VL",      SDT_RISCVIntUnOp_VL>;
166  def riscv_ctlz_vl       : RVSDNode<"CTLZ_VL",       SDT_RISCVIntUnOp_VL>;
167  def riscv_cttz_vl       : RVSDNode<"CTTZ_VL",       SDT_RISCVIntUnOp_VL>;
168  def riscv_ctpop_vl      : RVSDNode<"CTPOP_VL",      SDT_RISCVIntUnOp_VL>;
169
170  // Averaging adds of signed integers.
171  def riscv_avgfloors_vl  : RVSDNode<"AVGFLOORS_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
172  // Averaging adds of unsigned integers.
173  def riscv_avgflooru_vl  : RVSDNode<"AVGFLOORU_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
174  // Rounding averaging adds of signed integers.
175  def riscv_avgceils_vl   : RVSDNode<"AVGCEILS_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
176  // Rounding averaging adds of unsigned integers.
177  def riscv_avgceilu_vl   : RVSDNode<"AVGCEILU_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
178  def riscv_saddsat_vl   : RVSDNode<"SADDSAT_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
179  def riscv_uaddsat_vl   : RVSDNode<"UADDSAT_VL", SDT_RISCVIntBinOp_VL, [SDNPCommutative]>;
180  def riscv_ssubsat_vl   : RVSDNode<"SSUBSAT_VL", SDT_RISCVIntBinOp_VL>;
181  def riscv_usubsat_vl   : RVSDNode<"USUBSAT_VL", SDT_RISCVIntBinOp_VL>;
182
183  def riscv_fadd_vl  : RVSDNode<"FADD_VL",  SDT_RISCVFPBinOp_VL, [SDNPCommutative]>;
184  def riscv_fsub_vl  : RVSDNode<"FSUB_VL",  SDT_RISCVFPBinOp_VL>;
185  def riscv_fmul_vl  : RVSDNode<"FMUL_VL",  SDT_RISCVFPBinOp_VL, [SDNPCommutative]>;
186  def riscv_fdiv_vl  : RVSDNode<"FDIV_VL",  SDT_RISCVFPBinOp_VL>;
187} // let HasPassthruOp = true, HasMaskOp = true
188
189// Vector unary ops with a mask as a second operand and VL as a third operand.
190let HasMaskOp = true in {
191  def riscv_fneg_vl  : RVSDNode<"FNEG_VL",  SDT_RISCVFPUnOp_VL>;
192  def riscv_fabs_vl  : RVSDNode<"FABS_VL",  SDT_RISCVFPUnOp_VL>;
193  def riscv_fsqrt_vl : RVSDNode<"FSQRT_VL", SDT_RISCVFPUnOp_VL>;
194} // let HasMaskOp = true
195
196let HasPassthruOp = true, HasMaskOp = true in {
197  def riscv_fcopysign_vl : RVSDNode<"FCOPYSIGN_VL", SDT_RISCVCopySign_VL>;
198  def riscv_vfmin_vl   : RVSDNode<"VFMIN_VL",  SDT_RISCVFPBinOp_VL, [SDNPCommutative]>;
199  def riscv_vfmax_vl   : RVSDNode<"VFMAX_VL",  SDT_RISCVFPBinOp_VL, [SDNPCommutative]>;
200} // let HasPassthruOp = true, HasMaskOp = true
201
202let IsStrictFP = true, HasPassthruOp = true, HasMaskOp = true in {
203  def riscv_strict_fadd_vl  : RVSDNode<"STRICT_FADD_VL",  SDT_RISCVFPBinOp_VL, [SDNPCommutative, SDNPHasChain]>;
204  def riscv_strict_fsub_vl  : RVSDNode<"STRICT_FSUB_VL",  SDT_RISCVFPBinOp_VL, [SDNPHasChain]>;
205  def riscv_strict_fmul_vl  : RVSDNode<"STRICT_FMUL_VL",  SDT_RISCVFPBinOp_VL, [SDNPCommutative, SDNPHasChain]>;
206  def riscv_strict_fdiv_vl  : RVSDNode<"STRICT_FDIV_VL",  SDT_RISCVFPBinOp_VL, [SDNPHasChain]>;
207} // let IsStrictFP = true, HasPassthruOp = true, HasMaskOp = true
208
209let IsStrictFP = true, HasMaskOp = true in
210def riscv_strict_fsqrt_vl : RVSDNode<"STRICT_FSQRT_VL", SDT_RISCVFPUnOp_VL, [SDNPHasChain]>;
211
212def any_riscv_fadd_vl : PatFrags<(ops node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
213                        [(riscv_fadd_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
214                         (riscv_strict_fadd_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl)]>;
215def any_riscv_fsub_vl : PatFrags<(ops node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
216                        [(riscv_fsub_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
217                         (riscv_strict_fsub_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl)]>;
218def any_riscv_fmul_vl : PatFrags<(ops node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
219                        [(riscv_fmul_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
220                         (riscv_strict_fmul_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl)]>;
221def any_riscv_fdiv_vl : PatFrags<(ops node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
222                        [(riscv_fdiv_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl),
223                         (riscv_strict_fdiv_vl node:$lhs, node:$rhs, node:$passthru, node:$mask, node:$vl)]>;
224def any_riscv_fsqrt_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
225                        [(riscv_fsqrt_vl node:$src, node:$mask, node:$vl),
226                         (riscv_strict_fsqrt_vl node:$src, node:$mask, node:$vl)]>;
227
228let HasMaskOp = true in
229def riscv_fclass_vl : RVSDNode<"FCLASS_VL",
230                               SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisVec<0>,
231                                                    SDTCisFP<1>, SDTCisVec<1>,
232                                                    SDTCisSameSizeAs<0, 1>,
233                                                    SDTCisSameNumEltsAs<0, 1>,
234                                                    SDTCVecEltisVT<2, i1>,
235                                                    SDTCisSameNumEltsAs<0, 2>,
236                                                    SDTCisVT<3, XLenVT>]>>;
237
238def SDT_RISCVVecFMA_VL : SDTypeProfile<1, 5, [SDTCisSameAs<0, 1>,
239                                              SDTCisSameAs<0, 2>,
240                                              SDTCisSameAs<0, 3>,
241                                              SDTCisVec<0>, SDTCisFP<0>,
242                                              SDTCVecEltisVT<4, i1>,
243                                              SDTCisSameNumEltsAs<0, 4>,
244                                              SDTCisVT<5, XLenVT>]>;
245
246let HasMaskOp = true in {
247  // Vector FMA ops with a mask as a fourth operand and VL as a fifth operand.
248  def riscv_vfmadd_vl  : RVSDNode<"VFMADD_VL",  SDT_RISCVVecFMA_VL, [SDNPCommutative]>;
249  def riscv_vfnmadd_vl : RVSDNode<"VFNMADD_VL", SDT_RISCVVecFMA_VL, [SDNPCommutative]>;
250  def riscv_vfmsub_vl  : RVSDNode<"VFMSUB_VL",  SDT_RISCVVecFMA_VL, [SDNPCommutative]>;
251  def riscv_vfnmsub_vl : RVSDNode<"VFNMSUB_VL", SDT_RISCVVecFMA_VL, [SDNPCommutative]>;
252}
253
254def SDT_RISCVWVecFMA_VL : SDTypeProfile<1, 5, [SDTCisVec<0>, SDTCisFP<0>,
255                                               SDTCisVec<1>, SDTCisFP<1>,
256                                               SDTCisOpSmallerThanOp<1, 0>,
257                                               SDTCisSameNumEltsAs<0, 1>,
258                                               SDTCisSameAs<1, 2>,
259                                               SDTCisSameAs<0, 3>,
260                                               SDTCVecEltisVT<4, i1>,
261                                               SDTCisSameNumEltsAs<0, 4>,
262                                               SDTCisVT<5, XLenVT>]>;
263
264let HasMaskOp = true in {
265  // Vector widening FMA ops with a mask as a fourth operand and VL as a fifth
266  // operand.
267  def riscv_vfwmadd_vl  : RVSDNode<"VFWMADD_VL",  SDT_RISCVWVecFMA_VL, [SDNPCommutative]>;
268  def riscv_vfwnmadd_vl : RVSDNode<"VFWNMADD_VL", SDT_RISCVWVecFMA_VL, [SDNPCommutative]>;
269  def riscv_vfwmsub_vl  : RVSDNode<"VFWMSUB_VL",  SDT_RISCVWVecFMA_VL, [SDNPCommutative]>;
270  def riscv_vfwnmsub_vl : RVSDNode<"VFWNMSUB_VL", SDT_RISCVWVecFMA_VL, [SDNPCommutative]>;
271
272  let IsStrictFP = true in {
273    def riscv_strict_vfmadd_vl : RVSDNode<"STRICT_VFMADD_VL", SDT_RISCVVecFMA_VL, [SDNPCommutative, SDNPHasChain]>;
274    def riscv_strict_vfnmadd_vl : RVSDNode<"STRICT_VFNMADD_VL", SDT_RISCVVecFMA_VL, [SDNPCommutative, SDNPHasChain]>;
275    def riscv_strict_vfmsub_vl : RVSDNode<"STRICT_VFMSUB_VL", SDT_RISCVVecFMA_VL, [SDNPCommutative, SDNPHasChain]>;
276    def riscv_strict_vfnmsub_vl : RVSDNode<"STRICT_VFNMSUB_VL", SDT_RISCVVecFMA_VL, [SDNPCommutative, SDNPHasChain]>;
277  } // let IsStrictFP = true
278} // let HasMaskOp = true
279
280def any_riscv_vfmadd_vl : PatFrags<(ops node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
281                        [(riscv_vfmadd_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
282                         (riscv_strict_vfmadd_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl)]>;
283def any_riscv_vfnmadd_vl : PatFrags<(ops node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
284                        [(riscv_vfnmadd_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
285                         (riscv_strict_vfnmadd_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl)]>;
286def any_riscv_vfmsub_vl : PatFrags<(ops node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
287                        [(riscv_vfmsub_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
288                         (riscv_strict_vfmsub_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl)]>;
289def any_riscv_vfnmsub_vl : PatFrags<(ops node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
290                        [(riscv_vfnmsub_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl),
291                         (riscv_strict_vfnmsub_vl node:$rs1, node:$rs2, node:$rs3, node:$mask, node:$vl)]>;
292
293def SDT_RISCVFPRoundOp_VL  : SDTypeProfile<1, 3, [
294  SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1>,
295  SDTCVecEltisVT<2, i1>, SDTCisSameNumEltsAs<1, 2>, SDTCisVT<3, XLenVT>
296]>;
297def SDT_RISCVFPExtendOp_VL  : SDTypeProfile<1, 3, [
298  SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1>,
299  SDTCVecEltisVT<2, i1>, SDTCisSameNumEltsAs<1, 2>, SDTCisVT<3, XLenVT>
300]>;
301
302let HasMaskOp = true in {
303  def riscv_fpround_vl : RVSDNode<"FP_ROUND_VL", SDT_RISCVFPRoundOp_VL>;
304  def riscv_fpextend_vl : RVSDNode<"FP_EXTEND_VL", SDT_RISCVFPExtendOp_VL>;
305
306  // Matches the semantics of the vfcnvt.rod function (Convert double-width
307  // float to single-width float, rounding towards odd). Takes a double-width
308  // float vector and produces a single-width float vector. Also has a mask and
309  // VL operand.
310  def riscv_fncvt_rod_vl : RVSDNode<"VFNCVT_ROD_VL", SDT_RISCVFPRoundOp_VL>;
311
312  let IsStrictFP = true in {
313    def riscv_strict_fpround_vl : RVSDNode<"STRICT_FP_ROUND_VL", SDT_RISCVFPRoundOp_VL, [SDNPHasChain]>;
314    def riscv_strict_fpextend_vl : RVSDNode<"STRICT_FP_EXTEND_VL", SDT_RISCVFPExtendOp_VL, [SDNPHasChain]>;
315    def riscv_strict_fncvt_rod_vl : RVSDNode<"STRICT_VFNCVT_ROD_VL", SDT_RISCVFPRoundOp_VL, [SDNPHasChain]>;
316  } // let IsStrictFP = true
317} // let HasMaskOp = true
318
319def any_riscv_fpround_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
320                            [(riscv_fpround_vl node:$src, node:$mask, node:$vl),
321                             (riscv_strict_fpround_vl node:$src, node:$mask, node:$vl)]>;
322def any_riscv_fpextend_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
323                            [(riscv_fpextend_vl node:$src, node:$mask, node:$vl),
324                             (riscv_strict_fpextend_vl node:$src, node:$mask, node:$vl)]>;
325def any_riscv_fncvt_rod_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
326                            [(riscv_fncvt_rod_vl node:$src, node:$mask, node:$vl),
327                             (riscv_strict_fncvt_rod_vl node:$src, node:$mask, node:$vl)]>;
328
329def SDT_RISCVFP2IOp_VL  : SDTypeProfile<1, 3, [
330  SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1>,
331  SDTCVecEltisVT<2, i1>, SDTCisSameNumEltsAs<1, 2>, SDTCisVT<3, XLenVT>
332]>;
333def SDT_RISCVFP2IOp_RM_VL  : SDTypeProfile<1, 4, [
334  SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1>,
335  SDTCVecEltisVT<2, i1>, SDTCisSameNumEltsAs<1, 2>, SDTCisVT<3, XLenVT>,
336  SDTCisVT<4, XLenVT> // Rounding mode
337]>;
338
339def SDT_RISCVI2FPOp_VL  : SDTypeProfile<1, 3, [
340  SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1>,
341  SDTCVecEltisVT<2, i1>, SDTCisSameNumEltsAs<1, 2>, SDTCisVT<3, XLenVT>
342]>;
343def SDT_RISCVI2FPOp_RM_VL  : SDTypeProfile<1, 4, [
344  SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1>,
345  SDTCVecEltisVT<2, i1>, SDTCisSameNumEltsAs<1, 2>, SDTCisVT<3, XLenVT>,
346  SDTCisVT<4, XLenVT> // Rounding mode
347]>;
348
349def SDT_RISCVSETCCOP_VL : SDTypeProfile<1, 6, [
350  SDTCVecEltisVT<0, i1>, SDTCisVec<1>, SDTCisSameNumEltsAs<0, 1>,
351  SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT>, SDTCisSameAs<0, 4>,
352  SDTCisSameAs<0, 5>, SDTCisVT<6, XLenVT>]>;
353
354// Float -> Int
355
356let HasMaskOp = true in {
357  def riscv_vfcvt_rm_xu_f_vl : RVSDNode<"VFCVT_RM_XU_F_VL", SDT_RISCVFP2IOp_RM_VL>;
358  def riscv_vfcvt_rm_x_f_vl : RVSDNode<"VFCVT_RM_X_F_VL", SDT_RISCVFP2IOp_RM_VL>;
359
360  def riscv_vfcvt_rtz_xu_f_vl : RVSDNode<"VFCVT_RTZ_XU_F_VL", SDT_RISCVFP2IOp_VL>;
361  def riscv_vfcvt_rtz_x_f_vl  : RVSDNode<"VFCVT_RTZ_X_F_VL",  SDT_RISCVFP2IOp_VL>;
362
363  let IsStrictFP = true in {
364    def riscv_strict_vfcvt_rm_x_f_vl : RVSDNode<"STRICT_VFCVT_RM_X_F_VL", SDT_RISCVFP2IOp_RM_VL, [SDNPHasChain]>;
365    def riscv_strict_vfcvt_rtz_xu_f_vl : RVSDNode<"STRICT_VFCVT_RTZ_XU_F_VL", SDT_RISCVFP2IOp_VL, [SDNPHasChain]>;
366    def riscv_strict_vfcvt_rtz_x_f_vl  : RVSDNode<"STRICT_VFCVT_RTZ_X_F_VL",  SDT_RISCVFP2IOp_VL, [SDNPHasChain]>;
367  } // let IsStrictFP = true
368} // let HasMaskOp = true
369
370def any_riscv_vfcvt_rm_x_f_vl : PatFrags<(ops node:$src, node:$mask, node:$vl, node:$rm),
371                            [(riscv_vfcvt_rm_x_f_vl node:$src, node:$mask, node:$vl, node:$rm),
372                             (riscv_strict_vfcvt_rm_x_f_vl node:$src, node:$mask, node:$vl, node:$rm)]>;
373def any_riscv_vfcvt_rtz_xu_f_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
374                            [(riscv_vfcvt_rtz_xu_f_vl node:$src, node:$mask, node:$vl),
375                             (riscv_strict_vfcvt_rtz_xu_f_vl node:$src, node:$mask, node:$vl)]>;
376def any_riscv_vfcvt_rtz_x_f_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
377                            [(riscv_vfcvt_rtz_x_f_vl node:$src, node:$mask, node:$vl),
378                             (riscv_strict_vfcvt_rtz_x_f_vl node:$src, node:$mask, node:$vl)]>;
379
380// Int -> Float
381
382let HasMaskOp = true in {
383  def riscv_sint_to_fp_vl : RVSDNode<"SINT_TO_FP_VL", SDT_RISCVI2FPOp_VL>;
384  def riscv_uint_to_fp_vl : RVSDNode<"UINT_TO_FP_VL", SDT_RISCVI2FPOp_VL>;
385  def riscv_vfcvt_rm_f_xu_vl : RVSDNode<"VFCVT_RM_F_XU_VL", SDT_RISCVI2FPOp_RM_VL>;
386  def riscv_vfcvt_rm_f_x_vl : RVSDNode<"VFCVT_RM_F_X_VL", SDT_RISCVI2FPOp_RM_VL>;
387
388  let IsStrictFP = true in {
389    def riscv_strict_sint_to_fp_vl : RVSDNode<"STRICT_SINT_TO_FP_VL", SDT_RISCVI2FPOp_VL, [SDNPHasChain]>;
390    def riscv_strict_uint_to_fp_vl : RVSDNode<"STRICT_UINT_TO_FP_VL", SDT_RISCVI2FPOp_VL, [SDNPHasChain]>;
391  } // let IsStrictFP = true
392} // let HasMaskOp = true
393
394def any_riscv_sint_to_fp_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
395                            [(riscv_sint_to_fp_vl node:$src, node:$mask, node:$vl),
396                             (riscv_strict_sint_to_fp_vl node:$src, node:$mask, node:$vl)]>;
397def any_riscv_uint_to_fp_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
398                            [(riscv_uint_to_fp_vl node:$src, node:$mask, node:$vl),
399                             (riscv_strict_uint_to_fp_vl node:$src, node:$mask, node:$vl)]>;
400
401let HasMaskOp = true in {
402  def riscv_vfround_noexcept_vl: RVSDNode<"VFROUND_NOEXCEPT_VL", SDT_RISCVFPUnOp_VL>;
403
404  let IsStrictFP = true in
405  def riscv_strict_vfround_noexcept_vl: RVSDNode<"STRICT_VFROUND_NOEXCEPT_VL", SDT_RISCVFPUnOp_VL, [SDNPHasChain]>;
406}
407
408def any_riscv_vfround_noexcept_vl : PatFrags<(ops node:$src, node:$mask, node:$vl),
409                        [(riscv_vfround_noexcept_vl node:$src, node:$mask, node:$vl),
410                         (riscv_strict_vfround_noexcept_vl node:$src, node:$mask, node:$vl)]>;
411
412// Vector compare producing a mask. Fourth operand is input mask. Fifth
413// operand is VL.
414let HasPassthruOp = true, HasMaskOp = true in
415def riscv_setcc_vl : RVSDNode<"SETCC_VL", SDT_RISCVSETCCOP_VL>;
416
417let IsStrictFP = true, HasMaskOp = true in {
418  def riscv_strict_fsetcc_vl : RVSDNode<"STRICT_FSETCC_VL", SDT_RISCVSETCCOP_VL, [SDNPHasChain]>;
419  def riscv_strict_fsetccs_vl : RVSDNode<"STRICT_FSETCCS_VL", SDT_RISCVSETCCOP_VL, [SDNPHasChain]>;
420} // let IsStrictFP = true, HasMaskOp = true
421
422def any_riscv_fsetcc_vl : PatFrags<(ops node:$lhs, node:$rhs, node:$cc, node:$passthru, node:$mask, node:$vl),
423                            [(riscv_setcc_vl node:$lhs, node:$rhs, node:$cc, node:$passthru, node:$mask, node:$vl),
424                             (riscv_strict_fsetcc_vl node:$lhs, node:$rhs, node:$cc, node:$passthru, node:$mask, node:$vl)]>;
425def any_riscv_fsetccs_vl : PatFrags<(ops node:$lhs, node:$rhs, node:$cc, node:$passthru, node:$mask, node:$vl),
426                            [(riscv_setcc_vl node:$lhs, node:$rhs, node:$cc, node:$passthru, node:$mask, node:$vl),
427                             (riscv_strict_fsetccs_vl node:$lhs, node:$rhs, node:$cc, node:$passthru, node:$mask, node:$vl)]>;
428
429let HasMaskOp = true in {
430  // Matches the semantics of vrgather.vx and vrgather.vv with extra operands
431  // for passthru and VL, except that out of bound indices result in a poison
432  // result not zero.  Operands are (src, index, mask, passthru, vl).
433  def riscv_vrgather_vx_vl : RVSDNode<"VRGATHER_VX_VL",
434                                      SDTypeProfile<1, 5, [SDTCisVec<0>,
435                                                          SDTCisSameAs<0, 1>,
436                                                          SDTCisVT<2, XLenVT>,
437                                                          SDTCisSameAs<0, 3>,
438                                                          SDTCVecEltisVT<4, i1>,
439                                                          SDTCisSameNumEltsAs<0, 4>,
440                                                          SDTCisVT<5, XLenVT>]>>;
441  def riscv_vrgather_vv_vl : RVSDNode<"VRGATHER_VV_VL",
442                                      SDTypeProfile<1, 5, [SDTCisVec<0>,
443                                                          SDTCisSameAs<0, 1>,
444                                                          SDTCisInt<2>,
445                                                          SDTCisSameNumEltsAs<0, 2>,
446                                                          SDTCisSameSizeAs<0, 2>,
447                                                          SDTCisSameAs<0, 3>,
448                                                          SDTCVecEltisVT<4, i1>,
449                                                          SDTCisSameNumEltsAs<0, 4>,
450                                                          SDTCisVT<5, XLenVT>]>>;
451  def riscv_vrgatherei16_vv_vl : RVSDNode<"VRGATHEREI16_VV_VL",
452                                          SDTypeProfile<1, 5, [SDTCisVec<0>,
453                                                              SDTCisSameAs<0, 1>,
454                                                              SDTCisInt<2>,
455                                                              SDTCVecEltisVT<2, i16>,
456                                                              SDTCisSameNumEltsAs<0, 2>,
457                                                              SDTCisSameAs<0, 3>,
458                                                              SDTCVecEltisVT<4, i1>,
459                                                              SDTCisSameNumEltsAs<0, 4>,
460                                                              SDTCisVT<5, XLenVT>]>>;
461} // let HasMaskOp = true
462
463def SDT_RISCVVMERGE_VL  : SDTypeProfile<1, 5, [
464  SDTCisVec<0>, SDTCisVec<1>, SDTCisSameNumEltsAs<0, 1>, SDTCVecEltisVT<1, i1>,
465  SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameAs<0, 4>,
466  SDTCisVT<5, XLenVT>
467]>;
468
469// General vmerge node with mask, true, false, passthru, and vl operands.
470// Tail agnostic vselect can be implemented by setting passthru to undef.
471let HasPassthruOp = true in
472def riscv_vmerge_vl : RVSDNode<"VMERGE_VL", SDT_RISCVVMERGE_VL>;
473
474def SDT_RISCVVMSETCLR_VL : SDTypeProfile<1, 1, [SDTCVecEltisVT<0, i1>,
475                                                SDTCisVT<1, XLenVT>]>;
476
477// Set mask vector to all zeros or ones.
478def riscv_vmclr_vl : RVSDNode<"VMCLR_VL", SDT_RISCVVMSETCLR_VL>;
479def riscv_vmset_vl : RVSDNode<"VMSET_VL", SDT_RISCVVMSETCLR_VL>;
480
481def SDT_RISCVMaskBinOp_VL : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
482                                                 SDTCisSameAs<0, 2>,
483                                                 SDTCVecEltisVT<0, i1>,
484                                                 SDTCisVT<3, XLenVT>]>;
485
486// Mask binary operators.
487def riscv_vmand_vl : RVSDNode<"VMAND_VL", SDT_RISCVMaskBinOp_VL, [SDNPCommutative]>;
488def riscv_vmor_vl  : RVSDNode<"VMOR_VL",  SDT_RISCVMaskBinOp_VL, [SDNPCommutative]>;
489def riscv_vmxor_vl : RVSDNode<"VMXOR_VL", SDT_RISCVMaskBinOp_VL, [SDNPCommutative]>;
490
491def true_mask : PatLeaf<(riscv_vmset_vl (XLenVT srcvalue))>;
492
493def riscv_vmnot_vl : PatFrag<(ops node:$rs, node:$vl),
494                             (riscv_vmxor_vl node:$rs, true_mask, node:$vl)>;
495
496let HasMaskOp = true in {
497  //  vcpop.m with additional mask and VL operands.
498  def riscv_vcpop_vl : RVSDNode<"VCPOP_VL",
499                                SDTypeProfile<1, 3, [SDTCisVT<0, XLenVT>,
500                                                    SDTCisVec<1>, SDTCisInt<1>,
501                                                    SDTCVecEltisVT<2, i1>,
502                                                    SDTCisSameNumEltsAs<1, 2>,
503                                                    SDTCisVT<3, XLenVT>]>>;
504
505  //  vfirst.m with additional mask and VL operands.
506  def riscv_vfirst_vl : RVSDNode<"VFIRST_VL",
507                                 SDTypeProfile<1, 3, [SDTCisVT<0, XLenVT>,
508                                                     SDTCisVec<1>, SDTCisInt<1>,
509                                                     SDTCVecEltisVT<2, i1>,
510                                                     SDTCisSameNumEltsAs<1, 2>,
511                                                     SDTCisVT<3, XLenVT>]>>;
512} // let HasMaskOp = true
513
514def SDT_RISCVVEXTEND_VL : SDTypeProfile<1, 3, [SDTCisVec<0>,
515                                               SDTCisSameNumEltsAs<0, 1>,
516                                               SDTCisSameNumEltsAs<1, 2>,
517                                               SDTCVecEltisVT<2, i1>,
518                                               SDTCisVT<3, XLenVT>]>;
519
520let HasMaskOp = true in {
521  // Vector sign/zero extend with additional mask & VL operands.
522  def riscv_sext_vl : RVSDNode<"VSEXT_VL", SDT_RISCVVEXTEND_VL>;
523  def riscv_zext_vl : RVSDNode<"VZEXT_VL", SDT_RISCVVEXTEND_VL>;
524} // let HasMaskOp = true
525
526def riscv_ext_vl : PatFrags<(ops node:$A, node:$B, node:$C),
527                            [(riscv_sext_vl node:$A, node:$B, node:$C),
528                             (riscv_zext_vl node:$A, node:$B, node:$C)]>;
529
530def SDT_RISCVVTRUNCATE_VL : SDTypeProfile<1, 3, [SDTCisVec<0>,
531                                                 SDTCisSameNumEltsAs<0, 1>,
532                                                 SDTCisSameNumEltsAs<0, 2>,
533                                                 SDTCVecEltisVT<2, i1>,
534                                                 SDTCisVT<3, XLenVT>]>;
535
536let HasMaskOp = true in {
537  // Truncates a RVV integer vector by one power-of-two. Carries both an extra
538  // mask and VL operand.
539  def riscv_trunc_vector_vl : RVSDNode<"TRUNCATE_VECTOR_VL",
540                                      SDT_RISCVVTRUNCATE_VL>;
541
542  // Truncates a RVV integer vector by one power-of-two. If the value doesn't
543  // fit in the destination type, the result is saturated. These correspond to
544  // vnclip and vnclipu with a shift of 0. Carries both an extra mask and VL
545  // operand.
546  def riscv_trunc_vector_vl_ssat : RVSDNode<"TRUNCATE_VECTOR_VL_SSAT",
547                                            SDT_RISCVVTRUNCATE_VL>;
548  def riscv_trunc_vector_vl_usat : RVSDNode<"TRUNCATE_VECTOR_VL_USAT",
549                                            SDT_RISCVVTRUNCATE_VL>;
550} // let HasMaskOp = true
551
552def SDT_RISCVVWIntBinOp_VL : SDTypeProfile<1, 5, [SDTCisVec<0>, SDTCisInt<0>,
553                                                  SDTCisInt<1>,
554                                                  SDTCisSameNumEltsAs<0, 1>,
555                                                  SDTCisOpSmallerThanOp<1, 0>,
556                                                  SDTCisSameAs<1, 2>,
557                                                  SDTCisSameAs<0, 3>,
558                                                  SDTCisSameNumEltsAs<1, 4>,
559                                                  SDTCVecEltisVT<4, i1>,
560                                                  SDTCisVT<5, XLenVT>]>;
561
562let HasPassthruOp = true, HasMaskOp = true in {
563  // Widening instructions with a passthru value a third operand, a mask as a
564  // fourth operand, and VL as a fifth operand.
565  def riscv_vwmul_vl   : RVSDNode<"VWMUL_VL",   SDT_RISCVVWIntBinOp_VL, [SDNPCommutative]>;
566  def riscv_vwmulu_vl  : RVSDNode<"VWMULU_VL",  SDT_RISCVVWIntBinOp_VL, [SDNPCommutative]>;
567  def riscv_vwmulsu_vl : RVSDNode<"VWMULSU_VL", SDT_RISCVVWIntBinOp_VL>;
568  def riscv_vwadd_vl   : RVSDNode<"VWADD_VL",   SDT_RISCVVWIntBinOp_VL, [SDNPCommutative]>;
569  def riscv_vwaddu_vl  : RVSDNode<"VWADDU_VL",  SDT_RISCVVWIntBinOp_VL, [SDNPCommutative]>;
570  def riscv_vwsub_vl   : RVSDNode<"VWSUB_VL",   SDT_RISCVVWIntBinOp_VL, []>;
571  def riscv_vwsubu_vl  : RVSDNode<"VWSUBU_VL",  SDT_RISCVVWIntBinOp_VL, []>;
572  def riscv_vwsll_vl   : RVSDNode<"VWSLL_VL",   SDT_RISCVVWIntBinOp_VL, []>;
573} // let HasPassthruOp = true, HasMaskOp = true
574
575def SDT_RISCVVWIntTernOp_VL : SDTypeProfile<1, 5, [SDTCisVec<0>, SDTCisInt<0>,
576                                                   SDTCisInt<1>,
577                                                   SDTCisSameNumEltsAs<0, 1>,
578                                                   SDTCisOpSmallerThanOp<1, 0>,
579                                                   SDTCisSameAs<1, 2>,
580                                                   SDTCisSameAs<0, 3>,
581                                                   SDTCisSameNumEltsAs<1, 4>,
582                                                   SDTCVecEltisVT<4, i1>,
583                                                   SDTCisVT<5, XLenVT>]>;
584
585let HasMaskOp = true in {
586  // Widening ternary operations with a mask as the fourth operand and VL as the
587  // fifth operand.
588  def riscv_vwmacc_vl : RVSDNode<"VWMACC_VL", SDT_RISCVVWIntTernOp_VL, [SDNPCommutative]>;
589  def riscv_vwmaccu_vl : RVSDNode<"VWMACCU_VL", SDT_RISCVVWIntTernOp_VL, [SDNPCommutative]>;
590  def riscv_vwmaccsu_vl : RVSDNode<"VWMACCSU_VL", SDT_RISCVVWIntTernOp_VL, []>;
591} // let HasMaskOp = true
592
593def SDT_RISCVVWFPBinOp_VL : SDTypeProfile<1, 5, [SDTCisVec<0>, SDTCisFP<0>,
594                                                 SDTCisFP<1>,
595                                                 SDTCisSameNumEltsAs<0, 1>,
596                                                 SDTCisOpSmallerThanOp<1, 0>,
597                                                 SDTCisSameAs<1, 2>,
598                                                 SDTCisSameAs<0, 3>,
599                                                 SDTCisSameNumEltsAs<1, 4>,
600                                                 SDTCVecEltisVT<4, i1>,
601                                                 SDTCisVT<5, XLenVT>]>;
602
603let HasPassthruOp = true, HasMaskOp = true in {
604  def riscv_vfwmul_vl : RVSDNode<"VFWMUL_VL", SDT_RISCVVWFPBinOp_VL, [SDNPCommutative]>;
605  def riscv_vfwadd_vl : RVSDNode<"VFWADD_VL", SDT_RISCVVWFPBinOp_VL, [SDNPCommutative]>;
606  def riscv_vfwsub_vl : RVSDNode<"VFWSUB_VL", SDT_RISCVVWFPBinOp_VL, []>;
607} // let HasPassthruOp = true, HasMaskOp = true
608
609def SDT_RISCVVWIntBinOpW_VL : SDTypeProfile<1, 5, [SDTCisVec<0>, SDTCisInt<0>,
610                                                   SDTCisSameAs<0, 1>,
611                                                   SDTCisInt<2>,
612                                                   SDTCisSameNumEltsAs<1, 2>,
613                                                   SDTCisOpSmallerThanOp<2, 1>,
614                                                   SDTCisSameAs<0, 3>,
615                                                   SDTCisSameNumEltsAs<1, 4>,
616                                                   SDTCVecEltisVT<4, i1>,
617                                                   SDTCisVT<5, XLenVT>]>;
618
619let HasPassthruOp = true, HasMaskOp = true in {
620  def riscv_vwadd_w_vl :  RVSDNode<"VWADD_W_VL",  SDT_RISCVVWIntBinOpW_VL>;
621  def riscv_vwaddu_w_vl : RVSDNode<"VWADDU_W_VL", SDT_RISCVVWIntBinOpW_VL>;
622  def riscv_vwsub_w_vl :  RVSDNode<"VWSUB_W_VL",  SDT_RISCVVWIntBinOpW_VL>;
623  def riscv_vwsubu_w_vl : RVSDNode<"VWSUBU_W_VL", SDT_RISCVVWIntBinOpW_VL>;
624} // let HasPassthruOp = true, HasMaskOp = true
625
626def SDT_RISCVVWFPBinOpW_VL : SDTypeProfile<1, 5, [SDTCisVec<0>, SDTCisFP<0>,
627                                                  SDTCisSameAs<0, 1>,
628                                                  SDTCisFP<2>,
629                                                  SDTCisSameNumEltsAs<1, 2>,
630                                                  SDTCisOpSmallerThanOp<2, 1>,
631                                                  SDTCisSameAs<0, 3>,
632                                                  SDTCisSameNumEltsAs<1, 4>,
633                                                  SDTCVecEltisVT<4, i1>,
634                                                  SDTCisVT<5, XLenVT>]>;
635
636let HasPassthruOp = true, HasMaskOp = true in {
637  def riscv_vfwadd_w_vl :  RVSDNode<"VFWADD_W_VL", SDT_RISCVVWFPBinOpW_VL>;
638  def riscv_vfwsub_w_vl :  RVSDNode<"VFWSUB_W_VL", SDT_RISCVVWFPBinOpW_VL>;
639} // let HasPassthruOp = true, HasMaskOp = true
640
641def SDTRVVVecReduce : SDTypeProfile<1, 6, [
642  SDTCisVec<0>, SDTCisVec<1>, SDTCisVec<2>, SDTCisSameAs<0, 3>,
643  SDTCVecEltisVT<4, i1>, SDTCisSameNumEltsAs<2, 4>, SDTCisVT<5, XLenVT>,
644  SDTCisVT<6, XLenVT>
645]>;
646
647let HasOneUse = 1 in {
648  def riscv_add_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
649                                         node:$E),
650                                    (riscv_add_vl node:$A, node:$B, node:$C,
651                                                  node:$D, node:$E)>;
652  def riscv_or_vl_is_add_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
653                                               node:$E),
654                                          (riscv_or_vl node:$A, node:$B, node:$C,
655                                                       node:$D, node:$E), [{
656    return orDisjoint(N);
657  }]>;
658  def riscv_sub_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
659                                         node:$E),
660                                    (riscv_sub_vl node:$A, node:$B, node:$C,
661                                                  node:$D, node:$E)>;
662  def riscv_mul_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
663                                         node:$E),
664                                    (riscv_mul_vl node:$A, node:$B, node:$C,
665                                                  node:$D, node:$E)>;
666  def riscv_vwmul_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
667                                           node:$E),
668                                      (riscv_vwmul_vl node:$A, node:$B, node:$C,
669                                                      node:$D, node:$E)>;
670  def riscv_vwmulu_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
671                                            node:$E),
672                                       (riscv_vwmulu_vl node:$A, node:$B, node:$C,
673                                                        node:$D, node:$E)>;
674  def riscv_vwmulsu_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
675                                             node:$E),
676                                        (riscv_vwmulsu_vl node:$A, node:$B, node:$C,
677                                                          node:$D, node:$E)>;
678  def riscv_sext_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C),
679                             (riscv_sext_vl node:$A, node:$B, node:$C)>;
680  def riscv_zext_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C),
681                             (riscv_zext_vl node:$A, node:$B, node:$C)>;
682  def riscv_ext_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C),
683                            (riscv_ext_vl node:$A, node:$B, node:$C)>;
684  def riscv_fpextend_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C),
685                             (riscv_fpextend_vl node:$A, node:$B, node:$C)>;
686  def riscv_vfmadd_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
687                                            node:$E),
688                                       (riscv_vfmadd_vl node:$A, node:$B,
689                                            node:$C, node:$D, node:$E)>;
690  def riscv_vfnmadd_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
691                                             node:$E),
692                                        (riscv_vfnmadd_vl node:$A, node:$B,
693                                             node:$C, node:$D, node:$E)>;
694  def riscv_vfmsub_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
695                                            node:$E),
696                                       (riscv_vfmsub_vl node:$A, node:$B,
697                                            node:$C, node:$D, node:$E)>;
698  def riscv_vfnmsub_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
699                                             node:$E),
700                                        (riscv_vfnmsub_vl node:$A, node:$B,
701                                             node:$C, node:$D, node:$E)>;
702} // HasOneUse = 1
703
704def riscv_fpextend_vl_sameuser : PatFrag<(ops node:$A, node:$B, node:$C),
705                                 (riscv_fpextend_vl node:$A, node:$B, node:$C), [{
706  return !N->use_empty() && all_equal(N->users());
707}]>;
708
709// These nodes match the semantics of the corresponding RVV vector reduction
710// instructions. They produce a vector result which is the reduction
711// performed over the second vector operand plus the first element of the
712// third vector operand. The first operand is the pass-thru operand. The
713// second operand is an unconstrained vector type, and the result, first, and
714// third operand's types are expected to be the corresponding full-width
715// LMUL=1 type for the second operand:
716//   nxv8i8 = vecreduce_add nxv8i8, nxv32i8, nxv8i8
717//   nxv2i32 = vecreduce_add nxv2i32, nxv8i32, nxv2i32
718// The different in types does introduce extra vsetvli instructions but
719// similarly it reduces the number of registers consumed per reduction.
720// Also has a mask and VL operand.
721let HasMaskOp = true in
722foreach kind = ["ADD", "UMAX", "SMAX", "UMIN", "SMIN", "AND", "OR", "XOR",
723                "FADD", "SEQ_FADD", "FMIN", "FMAX"] in
724  def rvv_vecreduce_#kind#_vl : RVSDNode<"VECREDUCE_"#kind#"_VL", SDTRVVVecReduce>;
725
726// Give explicit Complexity to prefer simm5/uimm5.
727def SplatPat       : ComplexPattern<vAny, 1, "selectVSplat",      [], [], 1>;
728def SplatPat_simm5 : ComplexPattern<vAny, 1, "selectVSplatSimm5", [], [], 3>;
729def SplatPat_uimm5 : ComplexPattern<vAny, 1, "selectVSplatUimmBits<5>", [], [], 3>;
730def SplatPat_uimm6 : ComplexPattern<vAny, 1, "selectVSplatUimmBits<6>", [], [], 3>;
731def SplatPat_simm5_plus1
732    : ComplexPattern<vAny, 1, "selectVSplatSimm5Plus1", [], [], 3>;
733def SplatPat_simm5_plus1_nodec
734    : ComplexPattern<vAny, 1, "selectVSplatSimm5Plus1NoDec", [], [], 3>;
735def SplatPat_simm5_plus1_nonzero
736    : ComplexPattern<vAny, 1, "selectVSplatSimm5Plus1NonZero", [], [], 3>;
737def SplatPat_imm64_neg : ComplexPattern<vAny, 1, "selectVSplatImm64Neg", [], [], 3>;
738
739// Selects extends or truncates of splats where we only care about the lowest 8
740// bits of each element.
741def Low8BitsSplatPat
742    : ComplexPattern<vAny, 1, "selectLow8BitsVSplat", [], [], 2>;
743
744// Ignore the vl operand on vmv_v_f, and vmv_s_f.
745def SplatFPOp : PatFrags<(ops node:$op),
746                         [(riscv_vfmv_v_f_vl undef, node:$op, srcvalue),
747                          (riscv_vfmv_s_f_vl undef, node:$op, srcvalue)]>;
748
749def sew8simm5  : ComplexPattern<XLenVT, 1, "selectRVVSimm5<8>",  []>;
750def sew16simm5 : ComplexPattern<XLenVT, 1, "selectRVVSimm5<16>", []>;
751def sew32simm5 : ComplexPattern<XLenVT, 1, "selectRVVSimm5<32>", []>;
752def sew64simm5 : ComplexPattern<XLenVT, 1, "selectRVVSimm5<64>", []>;
753
754class VPatBinaryVL_V<SDPatternOperator vop,
755                     string instruction_name,
756                     string suffix,
757                     ValueType result_type,
758                     ValueType op1_type,
759                     ValueType op2_type,
760                     ValueType mask_type,
761                     int log2sew,
762                     LMULInfo vlmul,
763                     VReg result_reg_class,
764                     VReg op1_reg_class,
765                     VReg op2_reg_class,
766                     bit isSEWAware = 0>
767    : Pat<(result_type (vop
768                       (op1_type op1_reg_class:$rs1),
769                       (op2_type op2_reg_class:$rs2),
770                       (result_type result_reg_class:$passthru),
771                       (mask_type VMV0:$vm),
772                       VLOpFrag)),
773      (!cast<Instruction>(
774                   !if(isSEWAware,
775                       instruction_name#"_"#suffix#"_"#vlmul.MX#"_E"#!shl(1, log2sew)#"_MASK",
776                       instruction_name#"_"#suffix#"_"#vlmul.MX#"_MASK"))
777                   result_reg_class:$passthru,
778                   op1_reg_class:$rs1,
779                   op2_reg_class:$rs2,
780                   (mask_type VMV0:$vm), GPR:$vl, log2sew, TAIL_AGNOSTIC)>;
781
782class VPatBinaryVL_V_RM<SDPatternOperator vop,
783                        string instruction_name,
784                        string suffix,
785                        ValueType result_type,
786                        ValueType op1_type,
787                        ValueType op2_type,
788                        ValueType mask_type,
789                        int log2sew,
790                        LMULInfo vlmul,
791                        VReg result_reg_class,
792                        VReg op1_reg_class,
793                        VReg op2_reg_class,
794                        bit isSEWAware = 0>
795    : Pat<(result_type (vop
796                       (op1_type op1_reg_class:$rs1),
797                       (op2_type op2_reg_class:$rs2),
798                       (result_type result_reg_class:$passthru),
799                       (mask_type VMV0:$vm),
800                       VLOpFrag)),
801      (!cast<Instruction>(
802                   !if(isSEWAware,
803                       instruction_name#"_"#suffix#"_"#vlmul.MX#"_E"#!shl(1, log2sew)#"_MASK",
804                       instruction_name#"_"#suffix#"_"#vlmul.MX#"_MASK"))
805                   result_reg_class:$passthru,
806                   op1_reg_class:$rs1,
807                   op2_reg_class:$rs2,
808                   (mask_type VMV0:$vm),
809                   // Value to indicate no rounding mode change in
810                   // RISCVInsertReadWriteCSR
811                   FRM_DYN,
812                   GPR:$vl, log2sew, TAIL_AGNOSTIC)>;
813
814multiclass VPatTiedBinaryNoMaskVL_V<SDNode vop,
815                                    string instruction_name,
816                                    string suffix,
817                                    ValueType result_type,
818                                    ValueType op2_type,
819                                    int sew,
820                                    LMULInfo vlmul,
821                                    VReg result_reg_class,
822                                    VReg op2_reg_class> {
823  def : Pat<(result_type (vop
824                         (result_type result_reg_class:$rs1),
825                         (op2_type op2_reg_class:$rs2),
826                         srcvalue,
827                         true_mask,
828                         VLOpFrag)),
829        (!cast<Instruction>(instruction_name#"_"#suffix#"_"# vlmul.MX#"_TIED")
830                     result_reg_class:$rs1,
831                     op2_reg_class:$rs2,
832                     GPR:$vl, sew, TAIL_AGNOSTIC)>;
833  // Tail undisturbed
834  def : Pat<(riscv_vmerge_vl true_mask,
835             (result_type (vop
836                           result_reg_class:$rs1,
837                           (op2_type op2_reg_class:$rs2),
838                           srcvalue,
839                           true_mask,
840                           VLOpFrag)),
841             result_reg_class:$rs1, result_reg_class:$rs1, VLOpFrag),
842            (!cast<Instruction>(instruction_name#"_"#suffix#"_"# vlmul.MX#"_TIED")
843                     result_reg_class:$rs1,
844                     op2_reg_class:$rs2,
845                     GPR:$vl, sew, TU_MU)>;
846}
847
848class VPatTiedBinaryMaskVL_V<SDNode vop,
849                             string instruction_name,
850                             string suffix,
851                             ValueType result_type,
852                             ValueType op2_type,
853                             ValueType mask_type,
854                             int sew,
855                             LMULInfo vlmul,
856                             VReg result_reg_class,
857                             VReg op2_reg_class> :
858  Pat<(result_type (vop
859                   (result_type result_reg_class:$rs1),
860                   (op2_type op2_reg_class:$rs2),
861                   (result_type result_reg_class:$rs1),
862                   (mask_type VMV0:$vm),
863                   VLOpFrag)),
864      (!cast<Instruction>(instruction_name#"_"#suffix#"_"# vlmul.MX#"_MASK_TIED")
865                   result_reg_class:$rs1,
866                   op2_reg_class:$rs2,
867                   (mask_type VMV0:$vm), GPR:$vl, sew, TU_MU)>;
868
869multiclass VPatTiedBinaryNoMaskVL_V_RM<SDNode vop,
870                                       string instruction_name,
871                                       string suffix,
872                                       ValueType result_type,
873                                       ValueType op2_type,
874                                       int log2sew,
875                                       LMULInfo vlmul,
876                                       VReg result_reg_class,
877                                       VReg op2_reg_class,
878                                       bit isSEWAware = 0> {
879  defvar name = !if(isSEWAware,
880                    instruction_name#"_"#suffix#"_"#vlmul.MX#"_E"#!shl(1, log2sew)#"_TIED",
881                    instruction_name#"_"#suffix#"_"#vlmul.MX#"_TIED");
882  def : Pat<(result_type (vop
883                         (result_type result_reg_class:$rs1),
884                         (op2_type op2_reg_class:$rs2),
885                         srcvalue,
886                         true_mask,
887                         VLOpFrag)),
888        (!cast<Instruction>(name)
889                     result_reg_class:$rs1,
890                     op2_reg_class:$rs2,
891                     // Value to indicate no rounding mode change in
892                     // RISCVInsertReadWriteCSR
893                     FRM_DYN,
894                     GPR:$vl, log2sew, TAIL_AGNOSTIC)>;
895  // Tail undisturbed
896  def : Pat<(riscv_vmerge_vl true_mask,
897             (result_type (vop
898                           result_reg_class:$rs1,
899                           (op2_type op2_reg_class:$rs2),
900                           srcvalue,
901                           true_mask,
902                           VLOpFrag)),
903             result_reg_class:$rs1, result_reg_class:$rs1, VLOpFrag),
904            (!cast<Instruction>(name)
905                     result_reg_class:$rs1,
906                     op2_reg_class:$rs2,
907                     // Value to indicate no rounding mode change in
908                     // RISCVInsertReadWriteCSR
909                     FRM_DYN,
910                     GPR:$vl, log2sew, TU_MU)>;
911}
912
913class VPatBinaryVL_XI<SDPatternOperator vop,
914                      string instruction_name,
915                      string suffix,
916                      ValueType result_type,
917                      ValueType vop1_type,
918                      ValueType vop2_type,
919                      ValueType mask_type,
920                      int log2sew,
921                      LMULInfo vlmul,
922                      VReg result_reg_class,
923                      VReg vop_reg_class,
924                      ComplexPattern SplatPatKind,
925                      DAGOperand xop_kind,
926                      bit isSEWAware = 0>
927    : Pat<(result_type (vop
928                   (vop1_type vop_reg_class:$rs1),
929                   (vop2_type (SplatPatKind (XLenVT xop_kind:$rs2))),
930                   (result_type result_reg_class:$passthru),
931                   (mask_type VMV0:$vm),
932                   VLOpFrag)),
933      (!cast<Instruction>(
934                   !if(isSEWAware,
935                       instruction_name#_#suffix#_#vlmul.MX#"_E"#!shl(1, log2sew)#"_MASK",
936                       instruction_name#_#suffix#_#vlmul.MX#"_MASK"))
937                   result_reg_class:$passthru,
938                   vop_reg_class:$rs1,
939                   xop_kind:$rs2,
940                   (mask_type VMV0:$vm), GPR:$vl, log2sew, TAIL_AGNOSTIC)>;
941
942multiclass VPatBinaryVL_VV_VX<SDPatternOperator vop, string instruction_name,
943                              list<VTypeInfo> vtilist = AllIntegerVectors,
944                              bit isSEWAware = 0> {
945  foreach vti = vtilist in {
946    let Predicates = GetVTypePredicates<vti>.Predicates in {
947      def : VPatBinaryVL_V<vop, instruction_name, "VV",
948                           vti.Vector, vti.Vector, vti.Vector, vti.Mask,
949                           vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass,
950                           vti.RegClass, isSEWAware>;
951      def : VPatBinaryVL_XI<vop, instruction_name, "VX",
952                            vti.Vector, vti.Vector, vti.Vector, vti.Mask,
953                            vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass,
954                            SplatPat, GPR, isSEWAware>;
955    }
956  }
957}
958
959multiclass VPatBinaryVL_VV_VX_VI<SDPatternOperator vop, string instruction_name,
960                                 Operand ImmType = simm5>
961    : VPatBinaryVL_VV_VX<vop, instruction_name> {
962  foreach vti = AllIntegerVectors in {
963    let Predicates = GetVTypePredicates<vti>.Predicates in
964    def : VPatBinaryVL_XI<vop, instruction_name, "VI",
965                          vti.Vector, vti.Vector, vti.Vector, vti.Mask,
966                          vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass,
967                          !cast<ComplexPattern>(SplatPat#_#ImmType),
968                          ImmType>;
969  }
970}
971
972multiclass VPatBinaryWVL_VV_VX<SDPatternOperator vop, string instruction_name> {
973  foreach VtiToWti = AllWidenableIntVectors in {
974    defvar vti = VtiToWti.Vti;
975    defvar wti = VtiToWti.Wti;
976    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
977                                 GetVTypePredicates<wti>.Predicates) in {
978      def : VPatBinaryVL_V<vop, instruction_name, "VV",
979                           wti.Vector, vti.Vector, vti.Vector, vti.Mask,
980                           vti.Log2SEW, vti.LMul, wti.RegClass, vti.RegClass,
981                           vti.RegClass>;
982      def : VPatBinaryVL_XI<vop, instruction_name, "VX",
983                            wti.Vector, vti.Vector, vti.Vector, vti.Mask,
984                            vti.Log2SEW, vti.LMul, wti.RegClass, vti.RegClass,
985                            SplatPat, GPR>;
986    }
987  }
988}
989
990multiclass VPatBinaryWVL_VV_VX_WV_WX<SDPatternOperator vop, SDNode vop_w,
991                                     string instruction_name>
992    : VPatBinaryWVL_VV_VX<vop, instruction_name> {
993  foreach VtiToWti = AllWidenableIntVectors in {
994    defvar vti = VtiToWti.Vti;
995    defvar wti = VtiToWti.Wti;
996    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
997                                 GetVTypePredicates<wti>.Predicates) in {
998      defm : VPatTiedBinaryNoMaskVL_V<vop_w, instruction_name, "WV",
999                                      wti.Vector, vti.Vector, vti.Log2SEW,
1000                                      vti.LMul, wti.RegClass, vti.RegClass>;
1001      def : VPatTiedBinaryMaskVL_V<vop_w, instruction_name, "WV",
1002                                   wti.Vector, vti.Vector, wti.Mask,
1003                                   vti.Log2SEW, vti.LMul, wti.RegClass,
1004                                   vti.RegClass>;
1005      def : VPatBinaryVL_V<vop_w, instruction_name, "WV",
1006                           wti.Vector, wti.Vector, vti.Vector, vti.Mask,
1007                           vti.Log2SEW, vti.LMul, wti.RegClass, wti.RegClass,
1008                           vti.RegClass>;
1009      def : VPatBinaryVL_XI<vop_w, instruction_name, "WX",
1010                            wti.Vector, wti.Vector, vti.Vector, vti.Mask,
1011                            vti.Log2SEW, vti.LMul, wti.RegClass, wti.RegClass,
1012                            SplatPat, GPR>;
1013    }
1014  }
1015}
1016
1017class VPatBinaryVL_VF<SDPatternOperator vop,
1018                      string instruction_name,
1019                      ValueType result_type,
1020                      ValueType vop1_type,
1021                      ValueType vop2_type,
1022                      ValueType mask_type,
1023                      int log2sew,
1024                      LMULInfo vlmul,
1025                      VReg result_reg_class,
1026                      VReg vop_reg_class,
1027                      RegisterClass scalar_reg_class,
1028                      bit isSEWAware = 0>
1029    : Pat<(result_type (vop (vop1_type vop_reg_class:$rs1),
1030                       (vop2_type (SplatFPOp scalar_reg_class:$rs2)),
1031                       (result_type result_reg_class:$passthru),
1032                       (mask_type VMV0:$vm),
1033                       VLOpFrag)),
1034      (!cast<Instruction>(
1035                   !if(isSEWAware,
1036                       instruction_name#"_"#vlmul.MX#"_E"#!shl(1, log2sew)#"_MASK",
1037                       instruction_name#"_"#vlmul.MX#"_MASK"))
1038                   result_reg_class:$passthru,
1039                   vop_reg_class:$rs1,
1040                   scalar_reg_class:$rs2,
1041                   (mask_type VMV0:$vm), GPR:$vl, log2sew, TAIL_AGNOSTIC)>;
1042
1043class VPatBinaryVL_VF_RM<SDPatternOperator vop,
1044                      string instruction_name,
1045                      ValueType result_type,
1046                      ValueType vop1_type,
1047                      ValueType vop2_type,
1048                      ValueType mask_type,
1049                      int log2sew,
1050                      LMULInfo vlmul,
1051                      VReg result_reg_class,
1052                      VReg vop_reg_class,
1053                      RegisterClass scalar_reg_class,
1054                      bit isSEWAware = 0>
1055    : Pat<(result_type (vop (vop1_type vop_reg_class:$rs1),
1056                       (vop2_type (SplatFPOp scalar_reg_class:$rs2)),
1057                       (result_type result_reg_class:$passthru),
1058                       (mask_type VMV0:$vm),
1059                       VLOpFrag)),
1060      (!cast<Instruction>(
1061                   !if(isSEWAware,
1062                       instruction_name#"_"#vlmul.MX#"_E"#!shl(1, log2sew)#"_MASK",
1063                       instruction_name#"_"#vlmul.MX#"_MASK"))
1064                   result_reg_class:$passthru,
1065                   vop_reg_class:$rs1,
1066                   scalar_reg_class:$rs2,
1067                   (mask_type VMV0:$vm),
1068                   // Value to indicate no rounding mode change in
1069                   // RISCVInsertReadWriteCSR
1070                   FRM_DYN,
1071                   GPR:$vl, log2sew, TAIL_AGNOSTIC)>;
1072
1073multiclass VPatBinaryFPVL_VV_VF<SDPatternOperator vop, string instruction_name,
1074                                bit isSEWAware = 0> {
1075  foreach vti = AllFloatVectors in {
1076    let Predicates = GetVTypePredicates<vti>.Predicates in {
1077      def : VPatBinaryVL_V<vop, instruction_name, "VV",
1078                           vti.Vector, vti.Vector, vti.Vector, vti.Mask,
1079                           vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass,
1080                           vti.RegClass, isSEWAware>;
1081      def : VPatBinaryVL_VF<vop, instruction_name#"_V"#vti.ScalarSuffix,
1082                            vti.Vector, vti.Vector, vti.Vector, vti.Mask,
1083                            vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass,
1084                            vti.ScalarRegClass, isSEWAware>;
1085    }
1086  }
1087}
1088
1089multiclass VPatBinaryFPVL_VV_VF_RM<SDPatternOperator vop, string instruction_name,
1090                                bit isSEWAware = 0> {
1091  foreach vti = AllFloatVectors in {
1092    let Predicates = GetVTypePredicates<vti>.Predicates in {
1093      def : VPatBinaryVL_V_RM<vop, instruction_name, "VV",
1094                             vti.Vector, vti.Vector, vti.Vector, vti.Mask,
1095                             vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass,
1096                             vti.RegClass, isSEWAware>;
1097      def : VPatBinaryVL_VF_RM<vop, instruction_name#"_V"#vti.ScalarSuffix,
1098                               vti.Vector, vti.Vector, vti.Vector, vti.Mask,
1099                               vti.Log2SEW, vti.LMul, vti.RegClass, vti.RegClass,
1100                               vti.ScalarRegClass, isSEWAware>;
1101      }
1102  }
1103}
1104
1105multiclass VPatBinaryFPVL_R_VF<SDPatternOperator vop, string instruction_name,
1106                               bit isSEWAware = 0> {
1107  foreach fvti = AllFloatVectors in {
1108    let Predicates = GetVTypePredicates<fvti>.Predicates in
1109    def : Pat<(fvti.Vector (vop (SplatFPOp fvti.ScalarRegClass:$rs2),
1110                                fvti.RegClass:$rs1,
1111                                (fvti.Vector fvti.RegClass:$passthru),
1112                                (fvti.Mask VMV0:$vm),
1113                                VLOpFrag)),
1114              (!cast<Instruction>(
1115                           !if(isSEWAware,
1116                               instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK",
1117                               instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX#"_MASK"))
1118                           fvti.RegClass:$passthru,
1119                           fvti.RegClass:$rs1, fvti.ScalarRegClass:$rs2,
1120                           (fvti.Mask VMV0:$vm), GPR:$vl, fvti.Log2SEW, TAIL_AGNOSTIC)>;
1121  }
1122}
1123
1124multiclass VPatBinaryFPVL_R_VF_RM<SDPatternOperator vop, string instruction_name,
1125                                  bit isSEWAware = 0> {
1126  foreach fvti = AllFloatVectors in {
1127    let Predicates = GetVTypePredicates<fvti>.Predicates in
1128    def : Pat<(fvti.Vector (vop (SplatFPOp fvti.ScalarRegClass:$rs2),
1129                                fvti.RegClass:$rs1,
1130                                (fvti.Vector fvti.RegClass:$passthru),
1131                                (fvti.Mask VMV0:$vm),
1132                                VLOpFrag)),
1133              (!cast<Instruction>(
1134                           !if(isSEWAware,
1135                               instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK",
1136                               instruction_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX#"_MASK"))
1137                           fvti.RegClass:$passthru,
1138                           fvti.RegClass:$rs1, fvti.ScalarRegClass:$rs2,
1139                           (fvti.Mask VMV0:$vm),
1140                           // Value to indicate no rounding mode change in
1141                           // RISCVInsertReadWriteCSR
1142                           FRM_DYN,
1143                           GPR:$vl, fvti.Log2SEW, TAIL_AGNOSTIC)>;
1144  }
1145}
1146
1147multiclass VPatIntegerSetCCVL_VV<VTypeInfo vti, string instruction_name,
1148                                 CondCode cc> {
1149  def : Pat<(vti.Mask (riscv_setcc_vl (vti.Vector vti.RegClass:$rs1),
1150                                      vti.RegClass:$rs2, cc,
1151                                      VR:$passthru,
1152                                      (vti.Mask VMV0:$vm),
1153                                      VLOpFrag)),
1154            (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX#"_MASK")
1155                         VR:$passthru,
1156                         vti.RegClass:$rs1,
1157                         vti.RegClass:$rs2,
1158                         (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MU)>;
1159}
1160
1161// Inherits from VPatIntegerSetCCVL_VV and adds a pattern with operands swapped.
1162multiclass VPatIntegerSetCCVL_VV_Swappable<VTypeInfo vti, string instruction_name,
1163                                           CondCode cc, CondCode invcc>
1164    : VPatIntegerSetCCVL_VV<vti, instruction_name, cc> {
1165  def : Pat<(vti.Mask (riscv_setcc_vl (vti.Vector vti.RegClass:$rs2),
1166                                      vti.RegClass:$rs1, invcc,
1167                                      VR:$passthru,
1168                                      (vti.Mask VMV0:$vm),
1169                                      VLOpFrag)),
1170            (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX#"_MASK")
1171                         VR:$passthru, vti.RegClass:$rs1,
1172                         vti.RegClass:$rs2, (vti.Mask VMV0:$vm), GPR:$vl,
1173                         vti.Log2SEW, TA_MU)>;
1174}
1175
1176multiclass VPatIntegerSetCCVL_VX_Swappable<VTypeInfo vti, string instruction_name,
1177                                           CondCode cc, CondCode invcc> {
1178  defvar instruction_masked = !cast<Instruction>(instruction_name#"_VX_"#vti.LMul.MX#"_MASK");
1179  def : Pat<(vti.Mask (riscv_setcc_vl (vti.Vector vti.RegClass:$rs1),
1180                                      (SplatPat (XLenVT GPR:$rs2)), cc,
1181                                      VR:$passthru,
1182                                      (vti.Mask VMV0:$vm),
1183                                      VLOpFrag)),
1184            (instruction_masked VR:$passthru, vti.RegClass:$rs1,
1185                                GPR:$rs2, (vti.Mask VMV0:$vm), GPR:$vl,
1186                                vti.Log2SEW, TA_MU)>;
1187  def : Pat<(vti.Mask (riscv_setcc_vl (SplatPat (XLenVT GPR:$rs2)),
1188                                      (vti.Vector vti.RegClass:$rs1), invcc,
1189                                      VR:$passthru,
1190                                      (vti.Mask VMV0:$vm),
1191                                      VLOpFrag)),
1192            (instruction_masked VR:$passthru, vti.RegClass:$rs1,
1193                                GPR:$rs2, (vti.Mask VMV0:$vm), GPR:$vl,
1194                                vti.Log2SEW, TA_MU)>;
1195}
1196
1197multiclass VPatIntegerSetCCVL_VI_Swappable<VTypeInfo vti, string instruction_name,
1198                                           CondCode cc, CondCode invcc,
1199                                           ComplexPattern splatpat_kind = SplatPat_simm5> {
1200  defvar instruction_masked = !cast<Instruction>(instruction_name#"_VI_"#vti.LMul.MX#"_MASK");
1201  def : Pat<(vti.Mask (riscv_setcc_vl (vti.Vector vti.RegClass:$rs1),
1202                                      (splatpat_kind simm5:$rs2), cc,
1203                                      VR:$passthru,
1204                                      (vti.Mask VMV0:$vm),
1205                                      VLOpFrag)),
1206            (instruction_masked VR:$passthru, vti.RegClass:$rs1,
1207                                XLenVT:$rs2, (vti.Mask VMV0:$vm), GPR:$vl,
1208                                vti.Log2SEW, TA_MU)>;
1209
1210  // FIXME: Can do some canonicalization to remove these patterns.
1211  def : Pat<(vti.Mask (riscv_setcc_vl (splatpat_kind simm5:$rs2),
1212                                      (vti.Vector vti.RegClass:$rs1), invcc,
1213                                      VR:$passthru,
1214                                      (vti.Mask VMV0:$vm),
1215                                      VLOpFrag)),
1216            (instruction_masked VR:$passthru, vti.RegClass:$rs1,
1217                                simm5:$rs2, (vti.Mask VMV0:$vm), GPR:$vl,
1218                                vti.Log2SEW, TA_MU)>;
1219}
1220
1221multiclass VPatFPSetCCVL_VV_VF_FV<SDPatternOperator vop, CondCode cc,
1222                                  string inst_name,
1223                                  string swapped_op_inst_name> {
1224  foreach fvti = AllFloatVectors in {
1225    let Predicates = GetVTypePredicates<fvti>.Predicates in {
1226      def : Pat<(fvti.Mask (vop (fvti.Vector fvti.RegClass:$rs1),
1227                                 fvti.RegClass:$rs2,
1228                                 cc,
1229                                 VR:$passthru,
1230                                 (fvti.Mask VMV0:$vm),
1231                                 VLOpFrag)),
1232                (!cast<Instruction>(inst_name#"_VV_"#fvti.LMul.MX#"_MASK")
1233                    VR:$passthru, fvti.RegClass:$rs1,
1234                    fvti.RegClass:$rs2, (fvti.Mask VMV0:$vm),
1235                    GPR:$vl, fvti.Log2SEW, TA_MU)>;
1236      def : Pat<(fvti.Mask (vop (fvti.Vector fvti.RegClass:$rs1),
1237                                (SplatFPOp fvti.ScalarRegClass:$rs2),
1238                                cc,
1239                                VR:$passthru,
1240                                (fvti.Mask VMV0:$vm),
1241                                VLOpFrag)),
1242                (!cast<Instruction>(inst_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX#"_MASK")
1243                    VR:$passthru, fvti.RegClass:$rs1,
1244                    fvti.ScalarRegClass:$rs2, (fvti.Mask VMV0:$vm),
1245                    GPR:$vl, fvti.Log2SEW, TA_MU)>;
1246      def : Pat<(fvti.Mask (vop (SplatFPOp fvti.ScalarRegClass:$rs2),
1247                                (fvti.Vector fvti.RegClass:$rs1),
1248                                cc,
1249                                VR:$passthru,
1250                                (fvti.Mask VMV0:$vm),
1251                                VLOpFrag)),
1252                (!cast<Instruction>(swapped_op_inst_name#"_V"#fvti.ScalarSuffix#"_"#fvti.LMul.MX#"_MASK")
1253                    VR:$passthru, fvti.RegClass:$rs1,
1254                    fvti.ScalarRegClass:$rs2, (fvti.Mask VMV0:$vm),
1255                    GPR:$vl, fvti.Log2SEW, TA_MU)>;
1256    }
1257  }
1258}
1259
1260multiclass VPatExtendVL_V<SDNode vop, string inst_name, string suffix,
1261                          list <VTypeInfoToFraction> fraction_list> {
1262  foreach vtiTofti = fraction_list in {
1263    defvar vti = vtiTofti.Vti;
1264    defvar fti = vtiTofti.Fti;
1265    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1266                                 GetVTypePredicates<fti>.Predicates) in
1267    def : Pat<(vti.Vector (vop (fti.Vector fti.RegClass:$rs2),
1268                               (fti.Mask VMV0:$vm), VLOpFrag)),
1269              (!cast<Instruction>(inst_name#"_"#suffix#"_"#vti.LMul.MX#"_MASK")
1270                  (vti.Vector (IMPLICIT_DEF)),
1271                  fti.RegClass:$rs2,
1272                  (fti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
1273  }
1274}
1275
1276// Single width converting
1277
1278multiclass VPatConvertFP2IVL_V<SDPatternOperator vop, string instruction_name> {
1279  foreach fvti = AllFloatVectors in {
1280    defvar ivti = GetIntVTypeInfo<fvti>.Vti;
1281    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1282                                 GetVTypePredicates<ivti>.Predicates) in
1283    def : Pat<(ivti.Vector (vop (fvti.Vector fvti.RegClass:$rs1),
1284                                (fvti.Mask VMV0:$vm),
1285                                VLOpFrag)),
1286              (!cast<Instruction>(instruction_name#"_"#ivti.LMul.MX#"_MASK")
1287                  (ivti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1,
1288                  (fvti.Mask VMV0:$vm), GPR:$vl, ivti.Log2SEW, TA_MA)>;
1289  }
1290}
1291
1292
1293multiclass VPatConvertFP2I_RM_VL_V<SDPatternOperator vop, string instruction_name> {
1294  foreach fvti = AllFloatVectors in {
1295    defvar ivti = GetIntVTypeInfo<fvti>.Vti;
1296    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1297                                 GetVTypePredicates<ivti>.Predicates) in
1298    def : Pat<(ivti.Vector (vop (fvti.Vector fvti.RegClass:$rs1),
1299                                (fvti.Mask VMV0:$vm), (XLenVT timm:$frm),
1300                                VLOpFrag)),
1301              (!cast<Instruction>(instruction_name#"_"#ivti.LMul.MX#"_MASK")
1302                  (ivti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1,
1303                  (fvti.Mask VMV0:$vm), timm:$frm, GPR:$vl, ivti.Log2SEW,
1304                  TA_MA)>;
1305  }
1306}
1307
1308multiclass VPatConvertI2FPVL_V_RM<SDPatternOperator vop, string instruction_name> {
1309  foreach fvti = AllFloatVectors in {
1310    defvar ivti = GetIntVTypeInfo<fvti>.Vti;
1311    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1312                                 GetVTypePredicates<ivti>.Predicates) in
1313    def : Pat<(fvti.Vector (vop (ivti.Vector ivti.RegClass:$rs1),
1314                                (ivti.Mask VMV0:$vm),
1315                                VLOpFrag)),
1316              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
1317                  (fvti.Vector (IMPLICIT_DEF)), ivti.RegClass:$rs1,
1318                  (ivti.Mask VMV0:$vm),
1319                  // Value to indicate no rounding mode change in
1320                  // RISCVInsertReadWriteCSR
1321                  FRM_DYN,
1322                  GPR:$vl, fvti.Log2SEW, TA_MA)>;
1323  }
1324}
1325
1326multiclass VPatConvertI2FP_RM_VL_V<SDNode vop, string instruction_name> {
1327  foreach fvti = AllFloatVectors in {
1328    defvar ivti = GetIntVTypeInfo<fvti>.Vti;
1329    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1330                                 GetVTypePredicates<ivti>.Predicates) in
1331    def : Pat<(fvti.Vector (vop (ivti.Vector ivti.RegClass:$rs1),
1332                                (ivti.Mask VMV0:$vm), (XLenVT timm:$frm),
1333                                VLOpFrag)),
1334              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
1335                  (fvti.Vector (IMPLICIT_DEF)), ivti.RegClass:$rs1,
1336                  (ivti.Mask VMV0:$vm), timm:$frm, GPR:$vl, fvti.Log2SEW, TA_MA)>;
1337  }
1338}
1339
1340// Widening converting
1341
1342multiclass VPatWConvertFP2IVL_V<SDPatternOperator vop, string instruction_name> {
1343  foreach fvtiToFWti = AllWidenableFloatVectors in {
1344    defvar fvti = fvtiToFWti.Vti;
1345    defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti;
1346    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1347                                 GetVTypePredicates<iwti>.Predicates) in
1348    def : Pat<(iwti.Vector (vop (fvti.Vector fvti.RegClass:$rs1),
1349                                (fvti.Mask VMV0:$vm),
1350                                VLOpFrag)),
1351              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX#"_MASK")
1352                  (iwti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1,
1353                  (fvti.Mask VMV0:$vm), GPR:$vl, fvti.Log2SEW, TA_MA)>;
1354  }
1355}
1356
1357
1358multiclass VPatWConvertFP2I_RM_VL_V<SDNode vop, string instruction_name> {
1359  foreach fvtiToFWti = AllWidenableFloatVectors in {
1360    defvar fvti = fvtiToFWti.Vti;
1361    defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti;
1362    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1363                                 GetVTypePredicates<iwti>.Predicates) in
1364    def : Pat<(iwti.Vector (vop (fvti.Vector fvti.RegClass:$rs1),
1365                                (fvti.Mask VMV0:$vm), (XLenVT timm:$frm),
1366                                VLOpFrag)),
1367              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX#"_MASK")
1368                  (iwti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1,
1369                  (fvti.Mask VMV0:$vm), timm:$frm, GPR:$vl, fvti.Log2SEW, TA_MA)>;
1370  }
1371}
1372
1373multiclass VPatWConvertI2FPVL_V<SDPatternOperator vop,
1374                                string instruction_name> {
1375  foreach vtiToWti = AllWidenableIntToFloatVectors in {
1376    defvar ivti = vtiToWti.Vti;
1377    defvar fwti = vtiToWti.Wti;
1378    let Predicates = !listconcat(GetVTypePredicates<ivti>.Predicates,
1379                                 GetVTypePredicates<fwti>.Predicates) in
1380    def : Pat<(fwti.Vector (vop (ivti.Vector ivti.RegClass:$rs1),
1381                                (ivti.Mask VMV0:$vm),
1382                                VLOpFrag)),
1383              (!cast<Instruction>(instruction_name#"_"#ivti.LMul.MX#"_E"#ivti.SEW#"_MASK")
1384                  (fwti.Vector (IMPLICIT_DEF)), ivti.RegClass:$rs1,
1385                  (ivti.Mask VMV0:$vm),
1386                  GPR:$vl, ivti.Log2SEW, TA_MA)>;
1387  }
1388}
1389
1390// Narrowing converting
1391
1392multiclass VPatNConvertFP2IVL_W<SDPatternOperator vop,
1393                                string instruction_name> {
1394  // Reuse the same list of types used in the widening nodes, but just swap the
1395  // direction of types around so we're converting from Wti -> Vti
1396  foreach vtiToWti = AllWidenableIntToFloatVectors in {
1397    defvar vti = vtiToWti.Vti;
1398    defvar fwti = vtiToWti.Wti;
1399    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1400                                 GetVTypePredicates<fwti>.Predicates) in
1401    def : Pat<(vti.Vector (vop (fwti.Vector fwti.RegClass:$rs1),
1402                               (fwti.Mask VMV0:$vm),
1403                               VLOpFrag)),
1404              (!cast<Instruction>(instruction_name#"_"#vti.LMul.MX#"_MASK")
1405                  (vti.Vector (IMPLICIT_DEF)), fwti.RegClass:$rs1,
1406                  (fwti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
1407  }
1408}
1409
1410multiclass VPatNConvertFP2I_RM_VL_W<SDNode vop, string instruction_name> {
1411  foreach vtiToWti = AllWidenableIntToFloatVectors in {
1412    defvar vti = vtiToWti.Vti;
1413    defvar fwti = vtiToWti.Wti;
1414    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1415                                 GetVTypePredicates<fwti>.Predicates) in
1416    def : Pat<(vti.Vector (vop (fwti.Vector fwti.RegClass:$rs1),
1417                               (fwti.Mask VMV0:$vm), (XLenVT timm:$frm),
1418                               VLOpFrag)),
1419              (!cast<Instruction>(instruction_name#"_"#vti.LMul.MX#"_MASK")
1420                  (vti.Vector (IMPLICIT_DEF)), fwti.RegClass:$rs1,
1421                  (fwti.Mask VMV0:$vm), timm:$frm, GPR:$vl, vti.Log2SEW, TA_MA)>;
1422  }
1423}
1424
1425multiclass VPatNConvertI2FPVL_W_RM<SDPatternOperator vop,
1426                                string instruction_name> {
1427  foreach fvtiToFWti = AllWidenableFloatVectors in {
1428    defvar fvti = fvtiToFWti.Vti;
1429    defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti;
1430    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1431                                 GetVTypePredicates<iwti>.Predicates) in
1432    def : Pat<(fvti.Vector (vop (iwti.Vector iwti.RegClass:$rs1),
1433                                (iwti.Mask VMV0:$vm),
1434                                VLOpFrag)),
1435              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
1436                  (fvti.Vector (IMPLICIT_DEF)), iwti.RegClass:$rs1,
1437                  (iwti.Mask VMV0:$vm),
1438                  // Value to indicate no rounding mode change in
1439                  // RISCVInsertReadWriteCSR
1440                  FRM_DYN,
1441                  GPR:$vl, fvti.Log2SEW, TA_MA)>;
1442  }
1443}
1444
1445multiclass VPatNConvertI2FP_RM_VL_W<SDNode vop, string instruction_name> {
1446  foreach fvtiToFWti = AllWidenableFloatVectors in {
1447    defvar fvti = fvtiToFWti.Vti;
1448    defvar iwti = GetIntVTypeInfo<fvtiToFWti.Wti>.Vti;
1449    let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
1450                                 GetVTypePredicates<iwti>.Predicates) in
1451    def : Pat<(fvti.Vector (vop (iwti.Vector iwti.RegClass:$rs1),
1452                                (iwti.Mask VMV0:$vm),  (XLenVT timm:$frm),
1453                                VLOpFrag)),
1454              (!cast<Instruction>(instruction_name#"_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
1455                  (fvti.Vector (IMPLICIT_DEF)), iwti.RegClass:$rs1,
1456                  (iwti.Mask VMV0:$vm), timm:$frm, GPR:$vl, fvti.Log2SEW, TA_MA)>;
1457  }
1458}
1459
1460multiclass VPatReductionVL<SDNode vop, string instruction_name, bit is_float> {
1461  foreach vti = !if(is_float, AllFloatVectors, AllIntegerVectors) in {
1462    defvar vti_m1 = !cast<VTypeInfo>(!if(is_float, "VF", "VI") # vti.SEW # "M1");
1463    let Predicates = GetVTypePredicates<vti>.Predicates in {
1464      def: Pat<(vti_m1.Vector (vop (vti_m1.Vector VR:$passthru),
1465                                   (vti.Vector vti.RegClass:$rs1), VR:$rs2,
1466                                   (vti.Mask VMV0:$vm), VLOpFrag,
1467                                   (XLenVT timm:$policy))),
1468          (!cast<Instruction>(instruction_name#"_VS_"#vti.LMul.MX#"_E"#vti.SEW#"_MASK")
1469              (vti_m1.Vector VR:$passthru),
1470              (vti.Vector vti.RegClass:$rs1),
1471              (vti_m1.Vector VR:$rs2),
1472              (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, (XLenVT timm:$policy))>;
1473    }
1474  }
1475}
1476
1477multiclass VPatReductionVL_RM<SDNode vop, string instruction_name, bit is_float> {
1478  foreach vti = !if(is_float, AllFloatVectors, AllIntegerVectors) in {
1479    defvar vti_m1 = !cast<VTypeInfo>(!if(is_float, "VF", "VI") # vti.SEW # "M1");
1480    let Predicates = GetVTypePredicates<vti>.Predicates in {
1481      def: Pat<(vti_m1.Vector (vop (vti_m1.Vector VR:$passthru),
1482                                   (vti.Vector vti.RegClass:$rs1), VR:$rs2,
1483                                   (vti.Mask VMV0:$vm), VLOpFrag,
1484                                   (XLenVT timm:$policy))),
1485          (!cast<Instruction>(instruction_name#"_VS_"#vti.LMul.MX#"_E"#vti.SEW#"_MASK")
1486              (vti_m1.Vector VR:$passthru),
1487              (vti.Vector vti.RegClass:$rs1),
1488              (vti_m1.Vector VR:$rs2),
1489              (vti.Mask VMV0:$vm),
1490              // Value to indicate no rounding mode change in
1491              // RISCVInsertReadWriteCSR
1492              FRM_DYN,
1493              GPR:$vl, vti.Log2SEW, (XLenVT timm:$policy))>;
1494    }
1495  }
1496}
1497
1498multiclass VPatBinaryVL_WV_WX_WI<SDNode op, string instruction_name> {
1499  foreach vtiToWti = AllWidenableIntVectors in {
1500    defvar vti = vtiToWti.Vti;
1501    defvar wti = vtiToWti.Wti;
1502    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1503                                 GetVTypePredicates<wti>.Predicates) in {
1504      def : Pat<
1505        (vti.Vector
1506          (riscv_trunc_vector_vl
1507            (op (wti.Vector wti.RegClass:$rs2),
1508                (wti.Vector (ext_oneuse (vti.Vector vti.RegClass:$rs1)))),
1509            (vti.Mask true_mask),
1510            VLOpFrag)),
1511        (!cast<Instruction>(instruction_name#"_WV_"#vti.LMul.MX)
1512          (vti.Vector (IMPLICIT_DEF)),
1513          wti.RegClass:$rs2, vti.RegClass:$rs1, GPR:$vl, vti.Log2SEW, TA_MA)>;
1514
1515      def : Pat<
1516        (vti.Vector
1517          (riscv_trunc_vector_vl
1518            (op (wti.Vector wti.RegClass:$rs2),
1519                (wti.Vector (Low8BitsSplatPat (XLenVT GPR:$rs1)))),
1520            (vti.Mask true_mask),
1521            VLOpFrag)),
1522        (!cast<Instruction>(instruction_name#"_WX_"#vti.LMul.MX)
1523          (vti.Vector (IMPLICIT_DEF)),
1524          wti.RegClass:$rs2, GPR:$rs1, GPR:$vl, vti.Log2SEW, TA_MA)>;
1525
1526      def : Pat<
1527        (vti.Vector
1528          (riscv_trunc_vector_vl
1529            (op (wti.Vector wti.RegClass:$rs2),
1530                (wti.Vector (SplatPat_uimm5 uimm5:$rs1))), (vti.Mask true_mask),
1531            VLOpFrag)),
1532        (!cast<Instruction>(instruction_name#"_WI_"#vti.LMul.MX)
1533          (vti.Vector (IMPLICIT_DEF)),
1534          wti.RegClass:$rs2, uimm5:$rs1, GPR:$vl, vti.Log2SEW, TA_MA)>;
1535    }
1536  }
1537}
1538
1539multiclass VPatWidenReductionVL<SDNode vop, PatFrags extop, string instruction_name, bit is_float> {
1540  foreach vtiToWti = !if(is_float, AllWidenableFloatVectors, AllWidenableIntVectors) in {
1541    defvar vti = vtiToWti.Vti;
1542    defvar wti = vtiToWti.Wti;
1543    defvar wti_m1 = !cast<VTypeInfo>(!if(is_float, "VF", "VI") # wti.SEW # "M1");
1544    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1545                                 GetVTypePredicates<wti>.Predicates) in {
1546      def: Pat<(wti_m1.Vector (vop (wti_m1.Vector VR:$passthru),
1547                                   (wti.Vector (extop (vti.Vector vti.RegClass:$rs1))),
1548                                   VR:$rs2, (vti.Mask VMV0:$vm), VLOpFrag,
1549                                   (XLenVT timm:$policy))),
1550               (!cast<Instruction>(instruction_name#"_VS_"#vti.LMul.MX#"_E"#vti.SEW#"_MASK")
1551                  (wti_m1.Vector VR:$passthru), (vti.Vector vti.RegClass:$rs1),
1552                  (wti_m1.Vector VR:$rs2), (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
1553                  (XLenVT timm:$policy))>;
1554    }
1555  }
1556}
1557
1558multiclass VPatWidenReductionVL_Ext_VL<SDNode vop, PatFrags extop, string instruction_name, bit is_float> {
1559  foreach vtiToWti = !if(is_float, AllWidenableFloatVectors, AllWidenableIntVectors) in {
1560    defvar vti = vtiToWti.Vti;
1561    defvar wti = vtiToWti.Wti;
1562    defvar wti_m1 = !cast<VTypeInfo>(!if(is_float, "VF", "VI") # wti.SEW # "M1");
1563    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1564                                 GetVTypePredicates<wti>.Predicates) in {
1565      def: Pat<(wti_m1.Vector (vop (wti_m1.Vector VR:$passthru),
1566                                   (wti.Vector (extop (vti.Vector vti.RegClass:$rs1), (vti.Mask true_mask), (XLenVT srcvalue))),
1567                                   VR:$rs2, (vti.Mask VMV0:$vm), VLOpFrag,
1568                                   (XLenVT timm:$policy))),
1569               (!cast<Instruction>(instruction_name#"_VS_"#vti.LMul.MX#"_E"#vti.SEW#"_MASK")
1570                  (wti_m1.Vector VR:$passthru), (vti.Vector vti.RegClass:$rs1),
1571                  (wti_m1.Vector VR:$rs2), (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
1572                  (XLenVT timm:$policy))>;
1573    }
1574  }
1575}
1576
1577multiclass VPatWidenReductionVL_Ext_VL_RM<SDNode vop, PatFrags extop, string instruction_name, bit is_float> {
1578  foreach vtiToWti = !if(is_float, AllWidenableFloatVectors, AllWidenableIntVectors) in {
1579    defvar vti = vtiToWti.Vti;
1580    defvar wti = vtiToWti.Wti;
1581    defvar wti_m1 = !cast<VTypeInfo>(!if(is_float, "VF", "VI") # wti.SEW # "M1");
1582    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1583                                 GetVTypePredicates<wti>.Predicates) in {
1584      def: Pat<(wti_m1.Vector (vop (wti_m1.Vector VR:$passthru),
1585                                   (wti.Vector (extop (vti.Vector vti.RegClass:$rs1), (vti.Mask true_mask), (XLenVT srcvalue))),
1586                                   VR:$rs2, (vti.Mask VMV0:$vm), VLOpFrag,
1587                                   (XLenVT timm:$policy))),
1588               (!cast<Instruction>(instruction_name#"_VS_"#vti.LMul.MX#"_E"#vti.SEW#"_MASK")
1589                  (wti_m1.Vector VR:$passthru), (vti.Vector vti.RegClass:$rs1),
1590                  (wti_m1.Vector VR:$rs2), (vti.Mask VMV0:$vm),
1591                  // Value to indicate no rounding mode change in
1592                  // RISCVInsertReadWriteCSR
1593                  FRM_DYN,
1594                  GPR:$vl, vti.Log2SEW,
1595                  (XLenVT timm:$policy))>;
1596    }
1597  }
1598}
1599
1600multiclass VPatBinaryFPWVL_VV_VF<SDNode vop, string instruction_name> {
1601  foreach fvtiToFWti = AllWidenableFloatVectors in {
1602    defvar vti = fvtiToFWti.Vti;
1603    defvar wti = fvtiToFWti.Wti;
1604    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1605                                 GetVTypePredicates<wti>.Predicates) in {
1606      def : VPatBinaryVL_V<vop, instruction_name, "VV",
1607                           wti.Vector, vti.Vector, vti.Vector, vti.Mask,
1608                           vti.Log2SEW, vti.LMul, wti.RegClass, vti.RegClass,
1609                           vti.RegClass>;
1610      def : VPatBinaryVL_VF<vop, instruction_name#"_V"#vti.ScalarSuffix,
1611                            wti.Vector, vti.Vector, vti.Vector, vti.Mask,
1612                            vti.Log2SEW, vti.LMul, wti.RegClass, vti.RegClass,
1613                            vti.ScalarRegClass>;
1614    }
1615  }
1616}
1617
1618multiclass VPatBinaryFPWVL_VV_VF_RM<SDNode vop, string instruction_name,
1619                                    bit isSEWAware = 0> {
1620  foreach fvtiToFWti = AllWidenableFloatVectors in {
1621    defvar vti = fvtiToFWti.Vti;
1622    defvar wti = fvtiToFWti.Wti;
1623    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1624                                 GetVTypePredicates<wti>.Predicates) in {
1625      def : VPatBinaryVL_V_RM<vop, instruction_name, "VV",
1626                                       wti.Vector, vti.Vector, vti.Vector, vti.Mask,
1627                                       vti.Log2SEW, vti.LMul, wti.RegClass, vti.RegClass,
1628                                       vti.RegClass, isSEWAware>;
1629      def : VPatBinaryVL_VF_RM<vop, instruction_name#"_V"#vti.ScalarSuffix,
1630                                        wti.Vector, vti.Vector, vti.Vector, vti.Mask,
1631                                        vti.Log2SEW, vti.LMul, wti.RegClass, vti.RegClass,
1632                                        vti.ScalarRegClass, isSEWAware>;
1633    }
1634  }
1635}
1636
1637multiclass VPatBinaryFPWVL_VV_VF_WV_WF<SDNode vop, SDNode vop_w, string instruction_name>
1638    : VPatBinaryFPWVL_VV_VF<vop, instruction_name> {
1639  foreach fvtiToFWti = AllWidenableFloatVectors in {
1640    defvar vti = fvtiToFWti.Vti;
1641    defvar wti = fvtiToFWti.Wti;
1642    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1643                                 GetVTypePredicates<wti>.Predicates) in {
1644      defm : VPatTiedBinaryNoMaskVL_V<vop_w, instruction_name, "WV",
1645                                      wti.Vector, vti.Vector, vti.Log2SEW,
1646                                      vti.LMul, wti.RegClass, vti.RegClass>;
1647      def : VPatBinaryVL_V<vop_w, instruction_name, "WV",
1648                           wti.Vector, wti.Vector, vti.Vector, vti.Mask,
1649                           vti.Log2SEW, vti.LMul, wti.RegClass, wti.RegClass,
1650                           vti.RegClass>;
1651      def : VPatBinaryVL_VF<vop_w, instruction_name#"_W"#vti.ScalarSuffix,
1652                            wti.Vector, wti.Vector, vti.Vector, vti.Mask,
1653                            vti.Log2SEW, vti.LMul, wti.RegClass, wti.RegClass,
1654                            vti.ScalarRegClass>;
1655    }
1656  }
1657}
1658
1659multiclass VPatBinaryFPWVL_VV_VF_WV_WF_RM<
1660    SDNode vop, SDNode vop_w, string instruction_name, bit isSEWAware = 0>
1661    : VPatBinaryFPWVL_VV_VF_RM<vop, instruction_name, isSEWAware> {
1662  foreach fvtiToFWti = AllWidenableFloatVectors in {
1663    defvar vti = fvtiToFWti.Vti;
1664    defvar wti = fvtiToFWti.Wti;
1665    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1666                                 GetVTypePredicates<wti>.Predicates) in {
1667      defm : VPatTiedBinaryNoMaskVL_V_RM<vop_w, instruction_name, "WV",
1668                                         wti.Vector, vti.Vector, vti.Log2SEW,
1669                                         vti.LMul, wti.RegClass, vti.RegClass,
1670                                         isSEWAware>;
1671      def : VPatBinaryVL_V_RM<vop_w, instruction_name, "WV",
1672                                       wti.Vector, wti.Vector, vti.Vector, vti.Mask,
1673                                       vti.Log2SEW, vti.LMul, wti.RegClass, wti.RegClass,
1674                                       vti.RegClass, isSEWAware>;
1675      def : VPatBinaryVL_VF_RM<vop_w, instruction_name#"_W"#vti.ScalarSuffix,
1676                                        wti.Vector, wti.Vector, vti.Vector, vti.Mask,
1677                                        vti.Log2SEW, vti.LMul, wti.RegClass, wti.RegClass,
1678                                        vti.ScalarRegClass, isSEWAware>;
1679    }
1680  }
1681}
1682
1683multiclass VPatNarrowShiftSplatExt_WX<SDNode op, PatFrags extop, string instruction_name> {
1684  foreach vtiToWti = AllWidenableIntVectors in {
1685    defvar vti = vtiToWti.Vti;
1686    defvar wti = vtiToWti.Wti;
1687    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1688                                 GetVTypePredicates<wti>.Predicates) in
1689    def : Pat<
1690      (vti.Vector
1691        (riscv_trunc_vector_vl
1692          (op (wti.Vector wti.RegClass:$rs2),
1693              (wti.Vector (extop (vti.Vector (SplatPat (XLenVT GPR:$rs1))),
1694                                 (vti.Mask true_mask), VLOpFrag)),
1695          srcvalue, (wti.Mask true_mask), VLOpFrag),
1696        (vti.Mask true_mask), VLOpFrag)),
1697      (!cast<Instruction>(instruction_name#"_WX_"#vti.LMul.MX)
1698        (vti.Vector (IMPLICIT_DEF)),
1699        wti.RegClass:$rs2, GPR:$rs1, GPR:$vl, vti.Log2SEW, TA_MA)>;
1700  }
1701}
1702
1703multiclass VPatNarrowShiftExtVL_WV<SDNode op, PatFrags extop, string instruction_name> {
1704  foreach vtiToWti = AllWidenableIntVectors in {
1705    defvar vti = vtiToWti.Vti;
1706    defvar wti = vtiToWti.Wti;
1707    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1708                                 GetVTypePredicates<wti>.Predicates) in
1709    def : Pat<
1710      (vti.Vector
1711        (riscv_trunc_vector_vl
1712          (op (wti.Vector wti.RegClass:$rs2),
1713              (wti.Vector (extop (vti.Vector vti.RegClass:$rs1),
1714                                 (vti.Mask true_mask), VLOpFrag)),
1715          srcvalue, (vti.Mask true_mask), VLOpFrag),
1716        (vti.Mask VMV0:$vm), VLOpFrag)),
1717      (!cast<Instruction>(instruction_name#"_WV_"#vti.LMul.MX#"_MASK")
1718        (vti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs2, vti.RegClass:$rs1,
1719        (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
1720  }
1721}
1722
1723multiclass VPatNarrowShiftVL_WV<SDNode op, string instruction_name> {
1724  defm : VPatNarrowShiftExtVL_WV<op, riscv_sext_vl_oneuse, instruction_name>;
1725  defm : VPatNarrowShiftExtVL_WV<op, riscv_zext_vl_oneuse, instruction_name>;
1726}
1727
1728multiclass VPatMultiplyAddVL_VV_VX<SDNode op, string instruction_name> {
1729  foreach vti = AllIntegerVectors in {
1730    defvar suffix = vti.LMul.MX;
1731    let Predicates = GetVTypePredicates<vti>.Predicates in {
1732      // NOTE: We choose VMADD because it has the most commuting freedom. So it
1733      // works best with how TwoAddressInstructionPass tries commuting.
1734      def : Pat<(vti.Vector
1735               (op vti.RegClass:$rs2,
1736                   (riscv_mul_vl_oneuse vti.RegClass:$rs1,
1737                                        vti.RegClass:$rd,
1738                                        srcvalue, (vti.Mask true_mask), VLOpFrag),
1739                             srcvalue, (vti.Mask true_mask), VLOpFrag)),
1740              (!cast<Instruction>(instruction_name#"_VV_"# suffix)
1741                   vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1742                   GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
1743      // The choice of VMADD here is arbitrary, vmadd.vx and vmacc.vx are equally
1744      // commutable.
1745      def : Pat<(vti.Vector
1746               (op vti.RegClass:$rs2,
1747                   (riscv_mul_vl_oneuse (SplatPat XLenVT:$rs1),
1748                                         vti.RegClass:$rd,
1749                                         srcvalue, (vti.Mask true_mask), VLOpFrag),
1750                             srcvalue, (vti.Mask true_mask), VLOpFrag)),
1751              (!cast<Instruction>(instruction_name#"_VX_" # suffix)
1752                   vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1753                   GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
1754    }
1755  }
1756}
1757
1758multiclass VPatMultiplyAccVL_VV_VX<PatFrag op, string instruction_name> {
1759  foreach vti = AllIntegerVectors in {
1760  defvar suffix = vti.LMul.MX;
1761  let Predicates = GetVTypePredicates<vti>.Predicates in {
1762    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1763                (vti.Vector (op vti.RegClass:$rd,
1764                                (riscv_mul_vl_oneuse vti.RegClass:$rs1, vti.RegClass:$rs2,
1765                                    srcvalue, (vti.Mask true_mask), VLOpFrag),
1766                                srcvalue, (vti.Mask true_mask), VLOpFrag)),
1767                            vti.RegClass:$rd, vti.RegClass:$rd, VLOpFrag),
1768              (!cast<Instruction>(instruction_name#"_VV_"# suffix #"_MASK")
1769                   vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1770                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TU_MU)>;
1771    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1772                (vti.Vector (op vti.RegClass:$rd,
1773                                (riscv_mul_vl_oneuse (SplatPat XLenVT:$rs1), vti.RegClass:$rs2,
1774                                    srcvalue, (vti.Mask true_mask), VLOpFrag),
1775                                srcvalue, (vti.Mask true_mask), VLOpFrag)),
1776                            vti.RegClass:$rd, vti.RegClass:$rd, VLOpFrag),
1777              (!cast<Instruction>(instruction_name#"_VX_"# suffix #"_MASK")
1778                   vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1779                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TU_MU)>;
1780    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1781                (vti.Vector (op vti.RegClass:$rd,
1782                                (riscv_mul_vl_oneuse vti.RegClass:$rs1, vti.RegClass:$rs2,
1783                                    srcvalue, (vti.Mask true_mask), VLOpFrag),
1784                                srcvalue, (vti.Mask true_mask), VLOpFrag)),
1785                            vti.RegClass:$rd, undef, VLOpFrag),
1786              (!cast<Instruction>(instruction_name#"_VV_"# suffix #"_MASK")
1787                   vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1788                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
1789    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1790                (vti.Vector (op vti.RegClass:$rd,
1791                                (riscv_mul_vl_oneuse (SplatPat XLenVT:$rs1), vti.RegClass:$rs2,
1792                                    srcvalue, (vti.Mask true_mask), VLOpFrag),
1793                                srcvalue, (vti.Mask true_mask), VLOpFrag)),
1794                            vti.RegClass:$rd, undef, VLOpFrag),
1795              (!cast<Instruction>(instruction_name#"_VX_"# suffix #"_MASK")
1796                   vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1797                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
1798    }
1799  }
1800}
1801
1802multiclass VPatWidenMultiplyAddVL_VV_VX<SDNode vwmacc_op, string instr_name> {
1803  foreach vtiTowti = AllWidenableIntVectors in {
1804    defvar vti = vtiTowti.Vti;
1805    defvar wti = vtiTowti.Wti;
1806    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1807                                 GetVTypePredicates<wti>.Predicates) in {
1808      def : Pat<(vwmacc_op (vti.Vector vti.RegClass:$rs1),
1809                           (vti.Vector vti.RegClass:$rs2),
1810                           (wti.Vector wti.RegClass:$rd),
1811                           (vti.Mask VMV0:$vm), VLOpFrag),
1812                (!cast<Instruction>(instr_name#"_VV_"#vti.LMul.MX#"_MASK")
1813                    wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1814                    (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
1815      def : Pat<(vwmacc_op (SplatPat XLenVT:$rs1),
1816                           (vti.Vector vti.RegClass:$rs2),
1817                           (wti.Vector wti.RegClass:$rd),
1818                           (vti.Mask VMV0:$vm), VLOpFrag),
1819                (!cast<Instruction>(instr_name#"_VX_"#vti.LMul.MX#"_MASK")
1820                    wti.RegClass:$rd, vti.ScalarRegClass:$rs1,
1821                    vti.RegClass:$rs2, (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
1822                    TAIL_AGNOSTIC)>;
1823    }
1824  }
1825}
1826
1827multiclass VPatNarrowShiftSplat_WX_WI<SDNode op, string instruction_name> {
1828  foreach vtiTowti = AllWidenableIntVectors in {
1829    defvar vti = vtiTowti.Vti;
1830    defvar wti = vtiTowti.Wti;
1831    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1832                                 GetVTypePredicates<wti>.Predicates) in {
1833      def : Pat<(vti.Vector (riscv_trunc_vector_vl
1834                (wti.Vector (op wti.RegClass:$rs1, (SplatPat XLenVT:$rs2),
1835                                srcvalue, true_mask, VLOpFrag)), true_mask, VLOpFrag)),
1836                (!cast<Instruction>(instruction_name#"_WX_"#vti.LMul.MX)
1837                    (vti.Vector (IMPLICIT_DEF)),
1838                     wti.RegClass:$rs1, GPR:$rs2, GPR:$vl, vti.Log2SEW, TA_MA)>;
1839      def : Pat<(vti.Vector (riscv_trunc_vector_vl
1840                (wti.Vector (op wti.RegClass:$rs1, (SplatPat_uimm5 uimm5:$rs2),
1841                                srcvalue, true_mask, VLOpFrag)), true_mask, VLOpFrag)),
1842                (!cast<Instruction>(instruction_name#"_WI_"#vti.LMul.MX)
1843                (vti.Vector (IMPLICIT_DEF)),
1844                wti.RegClass:$rs1, uimm5:$rs2, GPR:$vl, vti.Log2SEW, TA_MA)>;
1845    }
1846  }
1847}
1848
1849multiclass VPatFPMulAddVL_VV_VF<SDPatternOperator vop, string instruction_name> {
1850  foreach vti = AllFloatVectors in {
1851  defvar suffix = vti.LMul.MX;
1852  let Predicates = GetVTypePredicates<vti>.Predicates in {
1853    def : Pat<(vti.Vector (vop vti.RegClass:$rs1, vti.RegClass:$rd,
1854                               vti.RegClass:$rs2, (vti.Mask VMV0:$vm),
1855                               VLOpFrag)),
1856              (!cast<Instruction>(instruction_name#"_VV_"# suffix #"_MASK")
1857                   vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1858                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
1859
1860    def : Pat<(vti.Vector (vop (SplatFPOp vti.ScalarRegClass:$rs1),
1861                               vti.RegClass:$rd, vti.RegClass:$rs2,
1862                               (vti.Mask VMV0:$vm),
1863                               VLOpFrag)),
1864              (!cast<Instruction>(instruction_name#"_V" # vti.ScalarSuffix # "_" # suffix # "_MASK")
1865                   vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1866                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
1867    }
1868  }
1869}
1870
1871multiclass VPatFPMulAddVL_VV_VF_RM<SDPatternOperator vop, string instruction_name> {
1872  foreach vti = AllFloatVectors in {
1873  defvar suffix = vti.LMul.MX # "_E" # vti.SEW;
1874  let Predicates = GetVTypePredicates<vti>.Predicates in {
1875    def : Pat<(vti.Vector (vop vti.RegClass:$rs1, vti.RegClass:$rd,
1876                               vti.RegClass:$rs2, (vti.Mask VMV0:$vm),
1877                               VLOpFrag)),
1878              (!cast<Instruction>(instruction_name#"_VV_"# suffix #"_MASK")
1879                   vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1880                   (vti.Mask VMV0:$vm),
1881                   // Value to indicate no rounding mode change in
1882                   // RISCVInsertReadWriteCSR
1883                   FRM_DYN,
1884                   GPR:$vl, vti.Log2SEW, TA_MA)>;
1885
1886    def : Pat<(vti.Vector (vop (SplatFPOp vti.ScalarRegClass:$rs1),
1887                               vti.RegClass:$rd, vti.RegClass:$rs2,
1888                               (vti.Mask VMV0:$vm),
1889                               VLOpFrag)),
1890              (!cast<Instruction>(instruction_name#"_V" # vti.ScalarSuffix # "_" # suffix # "_MASK")
1891                   vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1892                   (vti.Mask VMV0:$vm),
1893                   // Value to indicate no rounding mode change in
1894                   // RISCVInsertReadWriteCSR
1895                   FRM_DYN,
1896                   GPR:$vl, vti.Log2SEW, TA_MA)>;
1897    }
1898  }
1899}
1900
1901multiclass VPatFPMulAccVL_VV_VF_RM<PatFrag vop, string instruction_name> {
1902  foreach vti = AllFloatVectors in {
1903  defvar suffix = vti.LMul.MX # "_E" # vti.SEW;
1904  let Predicates = GetVTypePredicates<vti>.Predicates in {
1905    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1906                           (vti.Vector (vop vti.RegClass:$rs1, vti.RegClass:$rs2,
1907                            vti.RegClass:$rd, (vti.Mask true_mask), VLOpFrag)),
1908                            vti.RegClass:$rd, vti.RegClass:$rd, VLOpFrag),
1909              (!cast<Instruction>(instruction_name#"_VV_"# suffix #"_MASK")
1910                   vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1911                   (vti.Mask VMV0:$vm),
1912                   // Value to indicate no rounding mode change in
1913                   // RISCVInsertReadWriteCSR
1914                   FRM_DYN,
1915                   GPR:$vl, vti.Log2SEW, TU_MU)>;
1916    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1917                           (vti.Vector (vop (SplatFPOp vti.ScalarRegClass:$rs1), vti.RegClass:$rs2,
1918                            vti.RegClass:$rd, (vti.Mask true_mask), VLOpFrag)),
1919                            vti.RegClass:$rd, vti.RegClass:$rd, VLOpFrag),
1920              (!cast<Instruction>(instruction_name#"_V" # vti.ScalarSuffix # "_" # suffix # "_MASK")
1921                   vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1922                   (vti.Mask VMV0:$vm),
1923                   // Value to indicate no rounding mode change in
1924                   // RISCVInsertReadWriteCSR
1925                   FRM_DYN,
1926                   GPR:$vl, vti.Log2SEW, TU_MU)>;
1927    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1928                           (vti.Vector (vop vti.RegClass:$rs1, vti.RegClass:$rs2,
1929                            vti.RegClass:$rd, (vti.Mask true_mask), VLOpFrag)),
1930                            vti.RegClass:$rd, undef, VLOpFrag),
1931              (!cast<Instruction>(instruction_name#"_VV_"# suffix #"_MASK")
1932                   vti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1933                   (vti.Mask VMV0:$vm),
1934                   // Value to indicate no rounding mode change in
1935                   // RISCVInsertReadWriteCSR
1936                   FRM_DYN,
1937                   GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
1938    def : Pat<(riscv_vmerge_vl (vti.Mask VMV0:$vm),
1939                           (vti.Vector (vop (SplatFPOp vti.ScalarRegClass:$rs1), vti.RegClass:$rs2,
1940                            vti.RegClass:$rd, (vti.Mask true_mask), VLOpFrag)),
1941                            vti.RegClass:$rd, undef, VLOpFrag),
1942              (!cast<Instruction>(instruction_name#"_V" # vti.ScalarSuffix # "_" # suffix # "_MASK")
1943                   vti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1944                   (vti.Mask VMV0:$vm),
1945                   // Value to indicate no rounding mode change in
1946                   // RISCVInsertReadWriteCSR
1947                   FRM_DYN,
1948                   GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
1949    }
1950  }
1951}
1952
1953multiclass VPatWidenFPMulAccVL_VV_VF<SDNode vop, string instruction_name> {
1954  foreach vtiToWti = AllWidenableFloatVectors in {
1955    defvar vti = vtiToWti.Vti;
1956    defvar wti = vtiToWti.Wti;
1957    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1958                                 GetVTypePredicates<wti>.Predicates) in {
1959      def : Pat<(vop (vti.Vector vti.RegClass:$rs1),
1960                     (vti.Vector vti.RegClass:$rs2),
1961                     (wti.Vector wti.RegClass:$rd), (vti.Mask VMV0:$vm),
1962                     VLOpFrag),
1963                (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX #"_MASK")
1964                   wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1965                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
1966      def : Pat<(vop (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
1967                     (vti.Vector vti.RegClass:$rs2),
1968                     (wti.Vector wti.RegClass:$rd), (vti.Mask VMV0:$vm),
1969                     VLOpFrag),
1970                (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX #"_MASK")
1971                   wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
1972                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
1973    }
1974  }
1975}
1976
1977multiclass VPatWidenFPMulAccVL_VV_VF_RM<SDNode vop, string instruction_name,
1978                                        list<VTypeInfoToWide> vtiToWtis =
1979                                        AllWidenableFloatVectors> {
1980  foreach vtiToWti = vtiToWtis in {
1981    defvar vti = vtiToWti.Vti;
1982    defvar wti = vtiToWti.Wti;
1983    defvar suffix = vti.LMul.MX # "_E" # vti.SEW;
1984    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
1985                                 GetVTypePredicates<wti>.Predicates,
1986                                 !if(!eq(vti.Scalar, bf16),
1987                                     [HasStdExtZvfbfwma],
1988                                     [])) in {
1989      def : Pat<(vop (vti.Vector vti.RegClass:$rs1),
1990                     (vti.Vector vti.RegClass:$rs2),
1991                     (wti.Vector wti.RegClass:$rd), (vti.Mask VMV0:$vm),
1992                     VLOpFrag),
1993                (!cast<Instruction>(instruction_name#"_VV_"#suffix#"_MASK")
1994                   wti.RegClass:$rd, vti.RegClass:$rs1, vti.RegClass:$rs2,
1995                   (vti.Mask VMV0:$vm),
1996                   // Value to indicate no rounding mode change in
1997                   // RISCVInsertReadWriteCSR
1998                   FRM_DYN,
1999                   GPR:$vl, vti.Log2SEW, TA_MA)>;
2000      def : Pat<(vop (vti.Vector (SplatFPOp vti.ScalarRegClass:$rs1)),
2001                     (vti.Vector vti.RegClass:$rs2),
2002                     (wti.Vector wti.RegClass:$rd), (vti.Mask VMV0:$vm),
2003                     VLOpFrag),
2004                (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#suffix#"_MASK")
2005                   wti.RegClass:$rd, vti.ScalarRegClass:$rs1, vti.RegClass:$rs2,
2006                   (vti.Mask VMV0:$vm),
2007                   // Value to indicate no rounding mode change in
2008                   // RISCVInsertReadWriteCSR
2009                   FRM_DYN,
2010                   GPR:$vl, vti.Log2SEW, TA_MA)>;
2011    }
2012  }
2013}
2014
2015multiclass VPatSlideVL_VX_VI<SDNode vop, string instruction_name> {
2016  foreach vti = AllVectors in {
2017    defvar ivti = GetIntVTypeInfo<vti>.Vti;
2018    let Predicates = GetVTypePredicates<ivti>.Predicates in {
2019      def : Pat<(vti.Vector (vop (vti.Vector vti.RegClass:$rd),
2020                                 (vti.Vector vti.RegClass:$rs1),
2021                                 uimm5:$rs2, (vti.Mask VMV0:$vm),
2022                                 VLOpFrag, (XLenVT timm:$policy))),
2023                (!cast<Instruction>(instruction_name#"_VI_"#vti.LMul.MX#"_MASK")
2024                    vti.RegClass:$rd, vti.RegClass:$rs1, uimm5:$rs2,
2025                    (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
2026                    (XLenVT timm:$policy))>;
2027
2028      def : Pat<(vti.Vector (vop (vti.Vector vti.RegClass:$rd),
2029                                 (vti.Vector vti.RegClass:$rs1),
2030                                 GPR:$rs2, (vti.Mask VMV0:$vm),
2031                                 VLOpFrag, (XLenVT timm:$policy))),
2032                (!cast<Instruction>(instruction_name#"_VX_"#vti.LMul.MX#"_MASK")
2033                    vti.RegClass:$rd, vti.RegClass:$rs1, GPR:$rs2,
2034                    (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
2035                    (XLenVT timm:$policy))>;
2036    }
2037  }
2038}
2039
2040multiclass VPatSlide1VL_VX<SDNode vop, string instruction_name> {
2041  foreach vti = AllIntegerVectors in {
2042    let Predicates = GetVTypePredicates<vti>.Predicates in {
2043      def : Pat<(vti.Vector (vop (vti.Vector vti.RegClass:$rs3),
2044                                 (vti.Vector vti.RegClass:$rs1),
2045                                 GPR:$rs2, (vti.Mask VMV0:$vm), VLOpFrag)),
2046                (!cast<Instruction>(instruction_name#"_VX_"#vti.LMul.MX#"_MASK")
2047                    vti.RegClass:$rs3, vti.RegClass:$rs1, GPR:$rs2,
2048                    (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TU_MU)>;
2049    }
2050  }
2051}
2052
2053multiclass VPatSlide1VL_VF<SDNode vop, string instruction_name> {
2054  foreach vti = AllFloatVectors in {
2055    let Predicates = GetVTypePredicates<vti>.Predicates in {
2056      def : Pat<(vti.Vector (vop (vti.Vector vti.RegClass:$rs3),
2057                                 (vti.Vector vti.RegClass:$rs1),
2058                                 vti.Scalar:$rs2, (vti.Mask VMV0:$vm), VLOpFrag)),
2059                (!cast<Instruction>(instruction_name#"_V"#vti.ScalarSuffix#"_"#vti.LMul.MX#"_MASK")
2060                    vti.RegClass:$rs3, vti.RegClass:$rs1, vti.Scalar:$rs2,
2061                    (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TU_MU)>;
2062    }
2063  }
2064}
2065
2066multiclass VPatAVGADDVL_VV_VX_RM<SDNode vop, int vxrm, string suffix = ""> {
2067  foreach vti = AllIntegerVectors in {
2068    let Predicates = GetVTypePredicates<vti>.Predicates in {
2069      def : Pat<(vop (vti.Vector vti.RegClass:$rs1),
2070                     (vti.Vector vti.RegClass:$rs2),
2071                     vti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2072                (!cast<Instruction>("PseudoVAADD"#suffix#"_VV_"#vti.LMul.MX#"_MASK")
2073                  vti.RegClass:$passthru, vti.RegClass:$rs1, vti.RegClass:$rs2,
2074                  (vti.Mask VMV0:$vm), vxrm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2075      def : Pat<(vop (vti.Vector vti.RegClass:$rs1),
2076                     (vti.Vector (SplatPat (XLenVT GPR:$rs2))),
2077                     vti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2078                (!cast<Instruction>("PseudoVAADD"#suffix#"_VX_"#vti.LMul.MX#"_MASK")
2079                  vti.RegClass:$passthru, vti.RegClass:$rs1, GPR:$rs2,
2080                  (vti.Mask VMV0:$vm), vxrm, GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2081    }
2082  }
2083}
2084
2085//===----------------------------------------------------------------------===//
2086// Patterns.
2087//===----------------------------------------------------------------------===//
2088
2089// 11. Vector Integer Arithmetic Instructions
2090
2091// 11.1. Vector Single-Width Integer Add and Subtract
2092defm : VPatBinaryVL_VV_VX_VI<riscv_add_vl, "PseudoVADD">;
2093defm : VPatBinaryVL_VV_VX<riscv_sub_vl, "PseudoVSUB">;
2094foreach vti = AllIntegerVectors in {
2095  let Predicates = GetVTypePredicates<vti>.Predicates in {
2096    // Handle VRSUB specially since it's the only integer binary op with
2097    // reversed pattern operands
2098    def : Pat<(riscv_sub_vl (vti.Vector (SplatPat (XLenVT GPR:$rs2))),
2099                            (vti.Vector vti.RegClass:$rs1),
2100                            vti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2101              (!cast<Instruction>("PseudoVRSUB_VX_"# vti.LMul.MX#"_MASK")
2102                   vti.RegClass:$passthru, vti.RegClass:$rs1, GPR:$rs2,
2103                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2104    def : Pat<(riscv_sub_vl (vti.Vector (SplatPat_simm5 simm5:$rs2)),
2105                            (vti.Vector vti.RegClass:$rs1),
2106                            vti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2107              (!cast<Instruction>("PseudoVRSUB_VI_"# vti.LMul.MX#"_MASK")
2108                   vti.RegClass:$passthru, vti.RegClass:$rs1, simm5:$rs2,
2109                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2110
2111    // Match VSUB with a small immediate to vadd.vi by negating the immediate.
2112    def : Pat<(riscv_sub_vl (vti.Vector vti.RegClass:$rs1),
2113                            (vti.Vector (SplatPat_simm5_plus1_nodec simm5_plus1:$rs2)),
2114                            vti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2115              (!cast<Instruction>("PseudoVADD_VI_"#vti.LMul.MX#"_MASK")
2116                     vti.RegClass:$passthru, vti.RegClass:$rs1,
2117                     (NegImm simm5_plus1:$rs2), (vti.Mask VMV0:$vm),
2118                     GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2119  }
2120}
2121
2122// (add v, C) -> (sub v, -C) if -C cheaper to materialize
2123foreach vti = I64IntegerVectors in {
2124  let Predicates = [HasVInstructionsI64] in {
2125    def : Pat<(riscv_add_vl (vti.Vector vti.RegClass:$rs1),
2126                            (vti.Vector (SplatPat_imm64_neg i64:$rs2)),
2127                            vti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2128              (!cast<Instruction>("PseudoVSUB_VX_"#vti.LMul.MX#"_MASK")
2129                   vti.RegClass:$passthru, vti.RegClass:$rs1,
2130                   negImm:$rs2, (vti.Mask VMV0:$vm),
2131                   GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2132  }
2133}
2134
2135// 11.2. Vector Widening Integer Add/Subtract
2136defm : VPatBinaryWVL_VV_VX_WV_WX<riscv_vwadd_vl,  riscv_vwadd_w_vl,  "PseudoVWADD">;
2137defm : VPatBinaryWVL_VV_VX_WV_WX<riscv_vwaddu_vl, riscv_vwaddu_w_vl, "PseudoVWADDU">;
2138defm : VPatBinaryWVL_VV_VX_WV_WX<riscv_vwsub_vl,  riscv_vwsub_w_vl,  "PseudoVWSUB">;
2139defm : VPatBinaryWVL_VV_VX_WV_WX<riscv_vwsubu_vl, riscv_vwsubu_w_vl, "PseudoVWSUBU">;
2140
2141// shl_vl (ext_vl v, splat 1) is a special case of widening add.
2142foreach vtiToWti = AllWidenableIntVectors in {
2143  defvar vti = vtiToWti.Vti;
2144  defvar wti = vtiToWti.Wti;
2145  let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
2146                               GetVTypePredicates<wti>.Predicates) in {
2147    def : Pat<(riscv_shl_vl (wti.Vector (riscv_sext_vl_oneuse
2148                              (vti.Vector vti.RegClass:$rs1),
2149                              (vti.Mask VMV0:$vm), VLOpFrag)),
2150                            (wti.Vector (riscv_vmv_v_x_vl
2151                              (wti.Vector undef), 1, VLOpFrag)),
2152                              wti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2153              (!cast<Instruction>("PseudoVWADD_VV_"#vti.LMul.MX#"_MASK")
2154               wti.RegClass:$passthru, vti.RegClass:$rs1, vti.RegClass:$rs1,
2155               (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2156    def : Pat<(riscv_shl_vl (wti.Vector (riscv_zext_vl_oneuse
2157                              (vti.Vector vti.RegClass:$rs1),
2158                              (vti.Mask VMV0:$vm), VLOpFrag)),
2159                            (wti.Vector (riscv_vmv_v_x_vl
2160                              (wti.Vector undef), 1, VLOpFrag)),
2161                              wti.RegClass:$passthru, (vti.Mask VMV0:$vm), VLOpFrag),
2162              (!cast<Instruction>("PseudoVWADDU_VV_"#vti.LMul.MX#"_MASK")
2163               wti.RegClass:$passthru, vti.RegClass:$rs1, vti.RegClass:$rs1,
2164               (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2165  }
2166}
2167
2168// DAGCombiner::hoistLogicOpWithSameOpcodeHands may hoist disjoint ors
2169// to (ext (or disjoint (a, b)))
2170multiclass VPatWidenOrDisjointVL_VV_VX<SDNode extop, string instruction_name> {
2171  foreach vtiToWti = AllWidenableIntVectors in {
2172    defvar vti = vtiToWti.Vti;
2173    defvar wti = vtiToWti.Wti;
2174    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
2175                                 GetVTypePredicates<wti>.Predicates) in {
2176      def : Pat<(wti.Vector
2177                  (extop
2178                    (vti.Vector
2179                      (riscv_or_vl_is_add_oneuse
2180                        vti.RegClass:$rs2, vti.RegClass:$rs1,
2181                        undef, srcvalue, srcvalue)),
2182                    VMV0:$vm, VLOpFrag)),
2183                (!cast<Instruction>(instruction_name#"_VV_"#vti.LMul.MX#"_MASK")
2184                 (wti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2,
2185                 vti.RegClass:$rs1, VMV0:$vm, GPR:$vl, vti.Log2SEW, TA_MA)>;
2186       def : Pat<(wti.Vector
2187                   (extop
2188                     (vti.Vector
2189                       (riscv_or_vl_is_add_oneuse
2190                         vti.RegClass:$rs2, (SplatPat (XLenVT GPR:$rs1)),
2191                         undef, srcvalue, srcvalue)),
2192                     VMV0:$vm, VLOpFrag)),
2193                (!cast<Instruction>(instruction_name#"_VX_"#vti.LMul.MX#"_MASK")
2194                 (wti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2,
2195                 GPR:$rs1, VMV0:$vm, GPR:$vl, vti.Log2SEW, TA_MA)>;
2196    }
2197  }
2198}
2199
2200defm : VPatWidenOrDisjointVL_VV_VX<riscv_sext_vl, "PseudoVWADD">;
2201defm : VPatWidenOrDisjointVL_VV_VX<riscv_zext_vl, "PseudoVWADDU">;
2202
2203// 11.3. Vector Integer Extension
2204defm : VPatExtendVL_V<riscv_zext_vl, "PseudoVZEXT", "VF2",
2205                      AllFractionableVF2IntVectors>;
2206defm : VPatExtendVL_V<riscv_sext_vl, "PseudoVSEXT", "VF2",
2207                      AllFractionableVF2IntVectors>;
2208defm : VPatExtendVL_V<riscv_zext_vl, "PseudoVZEXT", "VF4",
2209                      AllFractionableVF4IntVectors>;
2210defm : VPatExtendVL_V<riscv_sext_vl, "PseudoVSEXT", "VF4",
2211                      AllFractionableVF4IntVectors>;
2212defm : VPatExtendVL_V<riscv_zext_vl, "PseudoVZEXT", "VF8",
2213                      AllFractionableVF8IntVectors>;
2214defm : VPatExtendVL_V<riscv_sext_vl, "PseudoVSEXT", "VF8",
2215                      AllFractionableVF8IntVectors>;
2216
2217// 11.5. Vector Bitwise Logical Instructions
2218defm : VPatBinaryVL_VV_VX_VI<riscv_and_vl, "PseudoVAND">;
2219defm : VPatBinaryVL_VV_VX_VI<riscv_or_vl,  "PseudoVOR">;
2220defm : VPatBinaryVL_VV_VX_VI<riscv_xor_vl, "PseudoVXOR">;
2221
2222// 11.6. Vector Single-Width Bit Shift Instructions
2223defm : VPatBinaryVL_VV_VX_VI<riscv_shl_vl, "PseudoVSLL", uimm5>;
2224defm : VPatBinaryVL_VV_VX_VI<riscv_srl_vl, "PseudoVSRL", uimm5>;
2225defm : VPatBinaryVL_VV_VX_VI<riscv_sra_vl, "PseudoVSRA", uimm5>;
2226
2227foreach vti = AllIntegerVectors in {
2228  // Emit shift by 1 as an add since it might be faster.
2229  let Predicates = GetVTypePredicates<vti>.Predicates in
2230  def : Pat<(riscv_shl_vl (vti.Vector vti.RegClass:$rs1),
2231                          (riscv_vmv_v_x_vl (vti.Vector undef), 1, (XLenVT srcvalue)),
2232                          srcvalue, (vti.Mask true_mask), VLOpFrag),
2233            (!cast<Instruction>("PseudoVADD_VV_"# vti.LMul.MX)
2234                 (vti.Vector (IMPLICIT_DEF)),
2235                 vti.RegClass:$rs1, vti.RegClass:$rs1, GPR:$vl, vti.Log2SEW, TA_MA)>;
2236}
2237
2238// 11.7. Vector Narrowing Integer Right Shift Instructions
2239defm : VPatBinaryVL_WV_WX_WI<srl, "PseudoVNSRL">;
2240defm : VPatBinaryVL_WV_WX_WI<sra, "PseudoVNSRA">;
2241
2242defm : VPatNarrowShiftSplat_WX_WI<riscv_sra_vl, "PseudoVNSRA">;
2243defm : VPatNarrowShiftSplat_WX_WI<riscv_srl_vl, "PseudoVNSRL">;
2244defm : VPatNarrowShiftSplatExt_WX<riscv_sra_vl, riscv_sext_vl_oneuse, "PseudoVNSRA">;
2245defm : VPatNarrowShiftSplatExt_WX<riscv_sra_vl, riscv_zext_vl_oneuse, "PseudoVNSRA">;
2246defm : VPatNarrowShiftSplatExt_WX<riscv_srl_vl, riscv_sext_vl_oneuse, "PseudoVNSRL">;
2247defm : VPatNarrowShiftSplatExt_WX<riscv_srl_vl, riscv_zext_vl_oneuse, "PseudoVNSRL">;
2248
2249defm : VPatNarrowShiftVL_WV<riscv_srl_vl, "PseudoVNSRL">;
2250defm : VPatNarrowShiftVL_WV<riscv_sra_vl, "PseudoVNSRA">;
2251
2252foreach vtiTowti = AllWidenableIntVectors in {
2253  defvar vti = vtiTowti.Vti;
2254  defvar wti = vtiTowti.Wti;
2255  let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
2256                               GetVTypePredicates<wti>.Predicates) in
2257  def : Pat<(vti.Vector (riscv_trunc_vector_vl (wti.Vector wti.RegClass:$rs1),
2258                                               (vti.Mask VMV0:$vm),
2259                                               VLOpFrag)),
2260            (!cast<Instruction>("PseudoVNSRL_WI_"#vti.LMul.MX#"_MASK")
2261                (vti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs1, 0,
2262                (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
2263}
2264
2265// 11.8. Vector Integer Comparison Instructions
2266foreach vti = AllIntegerVectors in {
2267  let Predicates = GetVTypePredicates<vti>.Predicates in {
2268    defm : VPatIntegerSetCCVL_VV<vti, "PseudoVMSEQ", SETEQ>;
2269    defm : VPatIntegerSetCCVL_VV<vti, "PseudoVMSNE", SETNE>;
2270
2271    defm : VPatIntegerSetCCVL_VV_Swappable<vti, "PseudoVMSLT",  SETLT,  SETGT>;
2272    defm : VPatIntegerSetCCVL_VV_Swappable<vti, "PseudoVMSLTU", SETULT, SETUGT>;
2273    defm : VPatIntegerSetCCVL_VV_Swappable<vti, "PseudoVMSLE",  SETLE,  SETGE>;
2274    defm : VPatIntegerSetCCVL_VV_Swappable<vti, "PseudoVMSLEU", SETULE, SETUGE>;
2275
2276    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSEQ",  SETEQ,  SETEQ>;
2277    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSNE",  SETNE,  SETNE>;
2278    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSLT",  SETLT,  SETGT>;
2279    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSLTU", SETULT, SETUGT>;
2280    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSLE",  SETLE,  SETGE>;
2281    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSLEU", SETULE, SETUGE>;
2282    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSGT",  SETGT,  SETLT>;
2283    defm : VPatIntegerSetCCVL_VX_Swappable<vti, "PseudoVMSGTU", SETUGT, SETULT>;
2284    // There is no VMSGE(U)_VX instruction
2285
2286    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSEQ",  SETEQ,  SETEQ>;
2287    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSNE",  SETNE,  SETNE>;
2288    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSLE",  SETLE,  SETGE>;
2289    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSLEU", SETULE, SETUGE>;
2290    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSGT",  SETGT,  SETLT>;
2291    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSGTU", SETUGT, SETULT>;
2292
2293    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSLE",  SETLT, SETGT,
2294                                           SplatPat_simm5_plus1>;
2295    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSLEU", SETULT, SETUGT,
2296                                           SplatPat_simm5_plus1_nonzero>;
2297    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSGT",  SETGE, SETLE,
2298                                           SplatPat_simm5_plus1>;
2299    defm : VPatIntegerSetCCVL_VI_Swappable<vti, "PseudoVMSGTU", SETUGE, SETULE,
2300                                           SplatPat_simm5_plus1_nonzero>;
2301  }
2302} // foreach vti = AllIntegerVectors
2303
2304// 11.9. Vector Integer Min/Max Instructions
2305defm : VPatBinaryVL_VV_VX<riscv_umin_vl, "PseudoVMINU">;
2306defm : VPatBinaryVL_VV_VX<riscv_smin_vl, "PseudoVMIN">;
2307defm : VPatBinaryVL_VV_VX<riscv_umax_vl, "PseudoVMAXU">;
2308defm : VPatBinaryVL_VV_VX<riscv_smax_vl, "PseudoVMAX">;
2309
2310// 11.10. Vector Single-Width Integer Multiply Instructions
2311defm : VPatBinaryVL_VV_VX<riscv_mul_vl, "PseudoVMUL">;
2312defm : VPatBinaryVL_VV_VX<riscv_mulhs_vl, "PseudoVMULH", IntegerVectorsExceptI64>;
2313defm : VPatBinaryVL_VV_VX<riscv_mulhu_vl, "PseudoVMULHU", IntegerVectorsExceptI64>;
2314// vsmul.vv and vsmul.vx are not included in EEW=64 in Zve64*.
2315let Predicates = [HasVInstructionsFullMultiply] in {
2316  defm : VPatBinaryVL_VV_VX<riscv_mulhs_vl, "PseudoVMULH", I64IntegerVectors>;
2317  defm : VPatBinaryVL_VV_VX<riscv_mulhu_vl, "PseudoVMULHU", I64IntegerVectors>;
2318}
2319
2320// 11.11. Vector Integer Divide Instructions
2321defm : VPatBinaryVL_VV_VX<riscv_udiv_vl, "PseudoVDIVU", isSEWAware=1>;
2322defm : VPatBinaryVL_VV_VX<riscv_sdiv_vl, "PseudoVDIV", isSEWAware=1>;
2323defm : VPatBinaryVL_VV_VX<riscv_urem_vl, "PseudoVREMU", isSEWAware=1>;
2324defm : VPatBinaryVL_VV_VX<riscv_srem_vl, "PseudoVREM", isSEWAware=1>;
2325
2326// 11.12. Vector Widening Integer Multiply Instructions
2327defm : VPatBinaryWVL_VV_VX<riscv_vwmul_vl, "PseudoVWMUL">;
2328defm : VPatBinaryWVL_VV_VX<riscv_vwmulu_vl, "PseudoVWMULU">;
2329defm : VPatBinaryWVL_VV_VX<riscv_vwmulsu_vl, "PseudoVWMULSU">;
2330
2331// 11.13 Vector Single-Width Integer Multiply-Add Instructions
2332defm : VPatMultiplyAddVL_VV_VX<riscv_add_vl, "PseudoVMADD">;
2333defm : VPatMultiplyAddVL_VV_VX<riscv_sub_vl, "PseudoVNMSUB">;
2334defm : VPatMultiplyAccVL_VV_VX<riscv_add_vl_oneuse, "PseudoVMACC">;
2335defm : VPatMultiplyAccVL_VV_VX<riscv_sub_vl_oneuse, "PseudoVNMSAC">;
2336
2337// 11.14. Vector Widening Integer Multiply-Add Instructions
2338defm : VPatWidenMultiplyAddVL_VV_VX<riscv_vwmacc_vl, "PseudoVWMACC">;
2339defm : VPatWidenMultiplyAddVL_VV_VX<riscv_vwmaccu_vl, "PseudoVWMACCU">;
2340defm : VPatWidenMultiplyAddVL_VV_VX<riscv_vwmaccsu_vl, "PseudoVWMACCSU">;
2341foreach vtiTowti = AllWidenableIntVectors in {
2342  defvar vti = vtiTowti.Vti;
2343  defvar wti = vtiTowti.Wti;
2344  let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
2345                               GetVTypePredicates<wti>.Predicates) in
2346  def : Pat<(riscv_vwmaccsu_vl (vti.Vector vti.RegClass:$rs1),
2347                               (SplatPat XLenVT:$rs2),
2348                               (wti.Vector wti.RegClass:$rd),
2349                               (vti.Mask VMV0:$vm), VLOpFrag),
2350            (!cast<Instruction>("PseudoVWMACCUS_VX_"#vti.LMul.MX#"_MASK")
2351                wti.RegClass:$rd, vti.ScalarRegClass:$rs2, vti.RegClass:$rs1,
2352                (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2353}
2354
2355// 11.15. Vector Integer Merge Instructions
2356foreach vti = AllIntegerVectors in {
2357  let Predicates = GetVTypePredicates<vti>.Predicates in {
2358    def : Pat<(vti.Vector (riscv_vmerge_vl (vti.Mask VMV0:$vm),
2359                                           vti.RegClass:$rs1,
2360                                           vti.RegClass:$rs2,
2361                                           vti.RegClass:$passthru,
2362                                           VLOpFrag)),
2363              (!cast<Instruction>("PseudoVMERGE_VVM_"#vti.LMul.MX)
2364                  vti.RegClass:$passthru, vti.RegClass:$rs2, vti.RegClass:$rs1,
2365                  (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW)>;
2366
2367    def : Pat<(vti.Vector (riscv_vmerge_vl (vti.Mask VMV0:$vm),
2368                                            (SplatPat XLenVT:$rs1),
2369                                            vti.RegClass:$rs2,
2370                                            vti.RegClass:$passthru,
2371                                            VLOpFrag)),
2372              (!cast<Instruction>("PseudoVMERGE_VXM_"#vti.LMul.MX)
2373                  vti.RegClass:$passthru, vti.RegClass:$rs2, GPR:$rs1,
2374                  (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW)>;
2375
2376    def : Pat<(vti.Vector (riscv_vmerge_vl (vti.Mask VMV0:$vm),
2377                                           (SplatPat_simm5 simm5:$rs1),
2378                                           vti.RegClass:$rs2,
2379                                           vti.RegClass:$passthru,
2380                                           VLOpFrag)),
2381              (!cast<Instruction>("PseudoVMERGE_VIM_"#vti.LMul.MX)
2382                  vti.RegClass:$passthru, vti.RegClass:$rs2, simm5:$rs1,
2383                  (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW)>;
2384  }
2385}
2386
2387// 11.16. Vector Integer Move Instructions
2388foreach vti = AllVectors in {
2389  defvar ivti = GetIntVTypeInfo<vti>.Vti;
2390  let Predicates = GetVTypePredicates<ivti>.Predicates in {
2391    def : Pat<(vti.Vector (riscv_vmv_v_v_vl vti.RegClass:$passthru,
2392                                            vti.RegClass:$rs2, VLOpFrag)),
2393              (!cast<Instruction>("PseudoVMV_V_V_"#vti.LMul.MX)
2394               vti.RegClass:$passthru, vti.RegClass:$rs2, GPR:$vl, vti.Log2SEW, TU_MU)>;
2395}
2396
2397foreach vti = AllIntegerVectors in {
2398  let Predicates = GetVTypePredicates<vti>.Predicates in {
2399      def : Pat<(vti.Vector (riscv_vmv_v_x_vl vti.RegClass:$passthru, GPR:$rs2, VLOpFrag)),
2400                (!cast<Instruction>("PseudoVMV_V_X_"#vti.LMul.MX)
2401                 vti.RegClass:$passthru, GPR:$rs2, GPR:$vl, vti.Log2SEW, TU_MU)>;
2402      defvar ImmPat = !cast<ComplexPattern>("sew"#vti.SEW#"simm5");
2403      def : Pat<(vti.Vector (riscv_vmv_v_x_vl vti.RegClass:$passthru, (ImmPat simm5:$imm5),
2404                                                  VLOpFrag)),
2405                (!cast<Instruction>("PseudoVMV_V_I_"#vti.LMul.MX)
2406                 vti.RegClass:$passthru, simm5:$imm5, GPR:$vl, vti.Log2SEW, TU_MU)>;
2407    }
2408  }
2409}
2410
2411// 12. Vector Fixed-Point Arithmetic Instructions
2412
2413// 12.1. Vector Single-Width Saturating Add and Subtract
2414defm : VPatBinaryVL_VV_VX_VI<riscv_saddsat_vl, "PseudoVSADD">;
2415defm : VPatBinaryVL_VV_VX_VI<riscv_uaddsat_vl, "PseudoVSADDU">;
2416defm : VPatBinaryVL_VV_VX<riscv_ssubsat_vl, "PseudoVSSUB">;
2417defm : VPatBinaryVL_VV_VX<riscv_usubsat_vl, "PseudoVSSUBU">;
2418
2419// 12.2. Vector Single-Width Averaging Add and Subtract
2420defm : VPatAVGADDVL_VV_VX_RM<riscv_avgfloors_vl, 0b10>;
2421defm : VPatAVGADDVL_VV_VX_RM<riscv_avgflooru_vl, 0b10, suffix="U">;
2422defm : VPatAVGADDVL_VV_VX_RM<riscv_avgceils_vl, 0b00>;
2423defm : VPatAVGADDVL_VV_VX_RM<riscv_avgceilu_vl, 0b00, suffix="U">;
2424
2425// 12.5. Vector Narrowing Fixed-Point Clip Instructions
2426foreach vtiTowti = AllWidenableIntVectors in {
2427  defvar vti = vtiTowti.Vti;
2428  defvar wti = vtiTowti.Wti;
2429  let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
2430                               GetVTypePredicates<wti>.Predicates) in {
2431    // Rounding mode here is arbitrary since we aren't shifting out any bits.
2432    def : Pat<(vti.Vector (riscv_trunc_vector_vl_ssat (wti.Vector wti.RegClass:$rs1),
2433                                                      (vti.Mask VMV0:$vm),
2434                                                      VLOpFrag)),
2435              (!cast<Instruction>("PseudoVNCLIP_WI_"#vti.LMul.MX#"_MASK")
2436                  (vti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs1, 0,
2437                  (vti.Mask VMV0:$vm), /*RNU*/0, GPR:$vl, vti.Log2SEW, TA_MA)>;
2438    def : Pat<(vti.Vector (riscv_trunc_vector_vl_usat (wti.Vector wti.RegClass:$rs1),
2439                                                      (vti.Mask VMV0:$vm),
2440                                                      VLOpFrag)),
2441              (!cast<Instruction>("PseudoVNCLIPU_WI_"#vti.LMul.MX#"_MASK")
2442                  (vti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs1, 0,
2443                  (vti.Mask VMV0:$vm), /*RNU*/0, GPR:$vl, vti.Log2SEW, TA_MA)>;
2444  }
2445}
2446
2447// 13. Vector Floating-Point Instructions
2448
2449// 13.2. Vector Single-Width Floating-Point Add/Subtract Instructions
2450defm : VPatBinaryFPVL_VV_VF_RM<any_riscv_fadd_vl, "PseudoVFADD", isSEWAware=1>;
2451defm : VPatBinaryFPVL_VV_VF_RM<any_riscv_fsub_vl, "PseudoVFSUB", isSEWAware=1>;
2452defm : VPatBinaryFPVL_R_VF_RM<any_riscv_fsub_vl, "PseudoVFRSUB", isSEWAware=1>;
2453
2454// 13.3. Vector Widening Floating-Point Add/Subtract Instructions
2455defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM<riscv_vfwadd_vl, riscv_vfwadd_w_vl,
2456                                      "PseudoVFWADD", isSEWAware=1>;
2457defm : VPatBinaryFPWVL_VV_VF_WV_WF_RM<riscv_vfwsub_vl, riscv_vfwsub_w_vl,
2458                                      "PseudoVFWSUB", isSEWAware=1>;
2459
2460// 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions
2461defm : VPatBinaryFPVL_VV_VF_RM<any_riscv_fmul_vl, "PseudoVFMUL", isSEWAware=1>;
2462defm : VPatBinaryFPVL_VV_VF_RM<any_riscv_fdiv_vl, "PseudoVFDIV", isSEWAware=1>;
2463defm : VPatBinaryFPVL_R_VF_RM<any_riscv_fdiv_vl, "PseudoVFRDIV", isSEWAware=1>;
2464
2465// 13.5. Vector Widening Floating-Point Multiply Instructions
2466defm : VPatBinaryFPWVL_VV_VF_RM<riscv_vfwmul_vl, "PseudoVFWMUL", isSEWAware=1>;
2467
2468// 13.6 Vector Single-Width Floating-Point Fused Multiply-Add Instructions.
2469defm : VPatFPMulAddVL_VV_VF_RM<any_riscv_vfmadd_vl,  "PseudoVFMADD">;
2470defm : VPatFPMulAddVL_VV_VF_RM<any_riscv_vfmsub_vl,  "PseudoVFMSUB">;
2471defm : VPatFPMulAddVL_VV_VF_RM<any_riscv_vfnmadd_vl, "PseudoVFNMADD">;
2472defm : VPatFPMulAddVL_VV_VF_RM<any_riscv_vfnmsub_vl, "PseudoVFNMSUB">;
2473defm : VPatFPMulAccVL_VV_VF_RM<riscv_vfmadd_vl_oneuse,  "PseudoVFMACC">;
2474defm : VPatFPMulAccVL_VV_VF_RM<riscv_vfmsub_vl_oneuse,  "PseudoVFMSAC">;
2475defm : VPatFPMulAccVL_VV_VF_RM<riscv_vfnmadd_vl_oneuse, "PseudoVFNMACC">;
2476defm : VPatFPMulAccVL_VV_VF_RM<riscv_vfnmsub_vl_oneuse, "PseudoVFNMSAC">;
2477
2478// 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions
2479defm : VPatWidenFPMulAccVL_VV_VF_RM<riscv_vfwmadd_vl, "PseudoVFWMACC">;
2480defm : VPatWidenFPMulAccVL_VV_VF_RM<riscv_vfwmadd_vl, "PseudoVFWMACCBF16",
2481                                    AllWidenableBFloatToFloatVectors>;
2482defm : VPatWidenFPMulAccVL_VV_VF_RM<riscv_vfwnmadd_vl, "PseudoVFWNMACC">;
2483defm : VPatWidenFPMulAccVL_VV_VF_RM<riscv_vfwmsub_vl, "PseudoVFWMSAC">;
2484defm : VPatWidenFPMulAccVL_VV_VF_RM<riscv_vfwnmsub_vl, "PseudoVFWNMSAC">;
2485
2486// 13.11. Vector Floating-Point MIN/MAX Instructions
2487defm : VPatBinaryFPVL_VV_VF<riscv_vfmin_vl, "PseudoVFMIN", isSEWAware=1>;
2488defm : VPatBinaryFPVL_VV_VF<riscv_vfmax_vl, "PseudoVFMAX", isSEWAware=1>;
2489
2490// 13.13. Vector Floating-Point Compare Instructions
2491defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetcc_vl, SETEQ,
2492                              "PseudoVMFEQ", "PseudoVMFEQ">;
2493defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetcc_vl, SETOEQ,
2494                              "PseudoVMFEQ", "PseudoVMFEQ">;
2495defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetcc_vl, SETNE,
2496                              "PseudoVMFNE", "PseudoVMFNE">;
2497defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetcc_vl, SETUNE,
2498                              "PseudoVMFNE", "PseudoVMFNE">;
2499defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetccs_vl, SETLT,
2500                              "PseudoVMFLT", "PseudoVMFGT">;
2501defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetccs_vl, SETOLT,
2502                              "PseudoVMFLT", "PseudoVMFGT">;
2503defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetccs_vl, SETLE,
2504                              "PseudoVMFLE", "PseudoVMFGE">;
2505defm : VPatFPSetCCVL_VV_VF_FV<any_riscv_fsetccs_vl, SETOLE,
2506                              "PseudoVMFLE", "PseudoVMFGE">;
2507
2508foreach vti = AllFloatVectors in {
2509  let Predicates = GetVTypePredicates<vti>.Predicates in {
2510    // 13.8. Vector Floating-Point Square-Root Instruction
2511    def : Pat<(any_riscv_fsqrt_vl (vti.Vector vti.RegClass:$rs2), (vti.Mask VMV0:$vm),
2512                              VLOpFrag),
2513              (!cast<Instruction>("PseudoVFSQRT_V_"# vti.LMul.MX # "_E" # vti.SEW # "_MASK")
2514                   (vti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2,
2515                   (vti.Mask VMV0:$vm),
2516                   // Value to indicate no rounding mode change in
2517                   // RISCVInsertReadWriteCSR
2518                   FRM_DYN,
2519                   GPR:$vl, vti.Log2SEW, TA_MA)>;
2520
2521    // 13.12. Vector Floating-Point Sign-Injection Instructions
2522    def : Pat<(riscv_fabs_vl (vti.Vector vti.RegClass:$rs), (vti.Mask VMV0:$vm),
2523                             VLOpFrag),
2524              (!cast<Instruction>("PseudoVFSGNJX_VV_"# vti.LMul.MX #"_E"#vti.SEW#"_MASK")
2525                   (vti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs,
2526                   vti.RegClass:$rs, (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
2527                   TA_MA)>;
2528    // Handle fneg with VFSGNJN using the same input for both operands.
2529    def : Pat<(riscv_fneg_vl (vti.Vector vti.RegClass:$rs), (vti.Mask VMV0:$vm),
2530                             VLOpFrag),
2531              (!cast<Instruction>("PseudoVFSGNJN_VV_"# vti.LMul.MX#"_E"#vti.SEW #"_MASK")
2532                   (vti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs,
2533                   vti.RegClass:$rs, (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
2534                   TA_MA)>;
2535
2536    def : Pat<(riscv_fcopysign_vl (vti.Vector vti.RegClass:$rs1),
2537                                  (vti.Vector vti.RegClass:$rs2),
2538                                  vti.RegClass:$passthru,
2539                                  (vti.Mask VMV0:$vm),
2540                                  VLOpFrag),
2541              (!cast<Instruction>("PseudoVFSGNJ_VV_"# vti.LMul.MX#"_E"#vti.SEW#"_MASK")
2542                   vti.RegClass:$passthru, vti.RegClass:$rs1,
2543                   vti.RegClass:$rs2, (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
2544                   TAIL_AGNOSTIC)>;
2545
2546    def : Pat<(riscv_fcopysign_vl (vti.Vector vti.RegClass:$rs1),
2547                                  (riscv_fneg_vl vti.RegClass:$rs2,
2548                                                 (vti.Mask true_mask),
2549                                                 VLOpFrag),
2550                                  srcvalue,
2551                                  (vti.Mask true_mask),
2552                                  VLOpFrag),
2553              (!cast<Instruction>("PseudoVFSGNJN_VV_"# vti.LMul.MX#"_E"#vti.SEW)
2554        (vti.Vector (IMPLICIT_DEF)),
2555                   vti.RegClass:$rs1, vti.RegClass:$rs2, GPR:$vl, vti.Log2SEW, TA_MA)>;
2556
2557    def : Pat<(riscv_fcopysign_vl (vti.Vector vti.RegClass:$rs1),
2558                                  (SplatFPOp vti.ScalarRegClass:$rs2),
2559                                  vti.RegClass:$passthru,
2560                                  (vti.Mask VMV0:$vm),
2561                                  VLOpFrag),
2562              (!cast<Instruction>("PseudoVFSGNJ_V"#vti.ScalarSuffix#"_"# vti.LMul.MX#"_E"#vti.SEW#"_MASK")
2563                   vti.RegClass:$passthru, vti.RegClass:$rs1,
2564                   vti.ScalarRegClass:$rs2, (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
2565                   TAIL_AGNOSTIC)>;
2566
2567    // Rounding without exception to implement nearbyint.
2568    def : Pat<(any_riscv_vfround_noexcept_vl (vti.Vector vti.RegClass:$rs1),
2569                                             (vti.Mask VMV0:$vm), VLOpFrag),
2570              (!cast<Instruction>("PseudoVFROUND_NOEXCEPT_V_" # vti.LMul.MX #"_MASK")
2571                    (vti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs1,
2572                    (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
2573
2574    // 14.14. Vector Floating-Point Classify Instruction
2575    def : Pat<(riscv_fclass_vl (vti.Vector vti.RegClass:$rs2),
2576                               (vti.Mask VMV0:$vm), VLOpFrag),
2577              (!cast<Instruction>("PseudoVFCLASS_V_"# vti.LMul.MX #"_MASK")
2578                 (vti.Vector (IMPLICIT_DEF)), vti.RegClass:$rs2,
2579                 (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TA_MA)>;
2580  }
2581}
2582
2583foreach fvti = AllFloatVectors in {
2584  // Floating-point vselects:
2585  // 11.15. Vector Integer Merge Instructions
2586  // 13.15. Vector Floating-Point Merge Instruction
2587  defvar ivti = GetIntVTypeInfo<fvti>.Vti;
2588  let Predicates = GetVTypePredicates<ivti>.Predicates in {
2589  def : Pat<(fvti.Vector (riscv_vmerge_vl (fvti.Mask VMV0:$vm),
2590                                          fvti.RegClass:$rs1,
2591                                          fvti.RegClass:$rs2,
2592                                          fvti.RegClass:$passthru,
2593                                          VLOpFrag)),
2594            (!cast<Instruction>("PseudoVMERGE_VVM_"#fvti.LMul.MX)
2595                 fvti.RegClass:$passthru, fvti.RegClass:$rs2, fvti.RegClass:$rs1, (fvti.Mask VMV0:$vm),
2596                 GPR:$vl, fvti.Log2SEW)>;
2597
2598  def : Pat<(fvti.Vector (riscv_vmerge_vl (fvti.Mask VMV0:$vm),
2599                                          (SplatFPOp (SelectScalarFPAsInt (XLenVT GPR:$imm))),
2600                                          fvti.RegClass:$rs2,
2601                                          fvti.RegClass:$passthru,
2602                                          VLOpFrag)),
2603            (!cast<Instruction>("PseudoVMERGE_VXM_"#fvti.LMul.MX)
2604                 fvti.RegClass:$passthru, fvti.RegClass:$rs2, GPR:$imm, (fvti.Mask VMV0:$vm),
2605                 GPR:$vl, fvti.Log2SEW)>;
2606
2607
2608  def : Pat<(fvti.Vector (riscv_vmerge_vl (fvti.Mask VMV0:$vm),
2609                                          (SplatFPOp (fvti.Scalar fpimm0)),
2610                                          fvti.RegClass:$rs2,
2611                                          fvti.RegClass:$passthru,
2612                                          VLOpFrag)),
2613            (!cast<Instruction>("PseudoVMERGE_VIM_"#fvti.LMul.MX)
2614                 fvti.RegClass:$passthru, fvti.RegClass:$rs2, 0, (fvti.Mask VMV0:$vm),
2615                 GPR:$vl, fvti.Log2SEW)>;
2616  }
2617}
2618
2619foreach fvti = AllFloatVectors in {
2620  let Predicates = GetVTypePredicates<fvti>.Predicates in {
2621    def : Pat<(fvti.Vector (riscv_vmerge_vl (fvti.Mask VMV0:$vm),
2622                                            (SplatFPOp fvti.ScalarRegClass:$rs1),
2623                                            fvti.RegClass:$rs2,
2624                                            fvti.RegClass:$passthru,
2625                                            VLOpFrag)),
2626              (!cast<Instruction>("PseudoVFMERGE_V"#fvti.ScalarSuffix#"M_"#fvti.LMul.MX)
2627                   fvti.RegClass:$passthru, fvti.RegClass:$rs2,
2628                   (fvti.Scalar fvti.ScalarRegClass:$rs1),
2629                   (fvti.Mask VMV0:$vm), GPR:$vl, fvti.Log2SEW)>;
2630  }
2631}
2632
2633foreach fvti = AllFloatVectors in {
2634  defvar ivti = GetIntVTypeInfo<fvti>.Vti;
2635  let Predicates = GetVTypePredicates<ivti>.Predicates in {
2636    // 13.16. Vector Floating-Point Move Instruction
2637    // If we're splatting fpimm0, use vmv.v.x vd, x0.
2638    def : Pat<(fvti.Vector (riscv_vfmv_v_f_vl
2639                           fvti.Vector:$passthru, (fvti.Scalar (fpimm0)), VLOpFrag)),
2640              (!cast<Instruction>("PseudoVMV_V_I_"#fvti.LMul.MX)
2641               $passthru, 0, GPR:$vl, fvti.Log2SEW, TU_MU)>;
2642    def : Pat<(fvti.Vector (riscv_vfmv_v_f_vl
2643                           fvti.Vector:$passthru, (fvti.Scalar (SelectScalarFPAsInt (XLenVT GPR:$imm))), VLOpFrag)),
2644              (!cast<Instruction>("PseudoVMV_V_X_"#fvti.LMul.MX)
2645               $passthru, GPR:$imm, GPR:$vl, fvti.Log2SEW, TU_MU)>;
2646  }
2647}
2648
2649foreach fvti = AllFloatVectors in {
2650  let Predicates = GetVTypePredicates<fvti>.Predicates in {
2651    def : Pat<(fvti.Vector (riscv_vfmv_v_f_vl
2652                           fvti.Vector:$passthru, (fvti.Scalar fvti.ScalarRegClass:$rs2), VLOpFrag)),
2653              (!cast<Instruction>("PseudoVFMV_V_" # fvti.ScalarSuffix # "_" #
2654                                  fvti.LMul.MX)
2655               $passthru, (fvti.Scalar fvti.ScalarRegClass:$rs2),
2656               GPR:$vl, fvti.Log2SEW, TU_MU)>;
2657  }
2658}
2659
2660// 13.17. Vector Single-Width Floating-Point/Integer Type-Convert Instructions
2661defm : VPatConvertFP2I_RM_VL_V<riscv_vfcvt_rm_xu_f_vl, "PseudoVFCVT_XU_F_V">;
2662defm : VPatConvertFP2I_RM_VL_V<any_riscv_vfcvt_rm_x_f_vl, "PseudoVFCVT_X_F_V">;
2663
2664defm : VPatConvertFP2IVL_V<any_riscv_vfcvt_rtz_xu_f_vl, "PseudoVFCVT_RTZ_XU_F_V">;
2665defm : VPatConvertFP2IVL_V<any_riscv_vfcvt_rtz_x_f_vl, "PseudoVFCVT_RTZ_X_F_V">;
2666
2667defm : VPatConvertI2FPVL_V_RM<any_riscv_uint_to_fp_vl, "PseudoVFCVT_F_XU_V">;
2668defm : VPatConvertI2FPVL_V_RM<any_riscv_sint_to_fp_vl, "PseudoVFCVT_F_X_V">;
2669
2670defm : VPatConvertI2FP_RM_VL_V<riscv_vfcvt_rm_f_xu_vl, "PseudoVFCVT_F_XU_V">;
2671defm : VPatConvertI2FP_RM_VL_V<riscv_vfcvt_rm_f_x_vl, "PseudoVFCVT_F_X_V">;
2672
2673// 13.18. Widening Floating-Point/Integer Type-Convert Instructions
2674defm : VPatWConvertFP2I_RM_VL_V<riscv_vfcvt_rm_xu_f_vl, "PseudoVFWCVT_XU_F_V">;
2675defm : VPatWConvertFP2I_RM_VL_V<riscv_vfcvt_rm_x_f_vl, "PseudoVFWCVT_X_F_V">;
2676
2677defm : VPatWConvertFP2IVL_V<any_riscv_vfcvt_rtz_xu_f_vl, "PseudoVFWCVT_RTZ_XU_F_V">;
2678defm : VPatWConvertFP2IVL_V<any_riscv_vfcvt_rtz_x_f_vl, "PseudoVFWCVT_RTZ_X_F_V">;
2679
2680defm : VPatWConvertI2FPVL_V<any_riscv_uint_to_fp_vl, "PseudoVFWCVT_F_XU_V">;
2681defm : VPatWConvertI2FPVL_V<any_riscv_sint_to_fp_vl, "PseudoVFWCVT_F_X_V">;
2682
2683foreach fvtiToFWti = AllWidenableFloatVectors in {
2684  defvar fvti = fvtiToFWti.Vti;
2685  defvar fwti = fvtiToFWti.Wti;
2686  // Define vfwcvt.f.f.v for f16 when Zvfhmin is enable.
2687  let Predicates = !listconcat(GetVTypeMinimalPredicates<fvti>.Predicates,
2688                               GetVTypeMinimalPredicates<fwti>.Predicates) in
2689  def : Pat<(fwti.Vector (any_riscv_fpextend_vl
2690                             (fvti.Vector fvti.RegClass:$rs1),
2691                             (fvti.Mask VMV0:$vm),
2692                             VLOpFrag)),
2693            (!cast<Instruction>("PseudoVFWCVT_F_F_V_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
2694                (fwti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1,
2695                (fvti.Mask VMV0:$vm),
2696                GPR:$vl, fvti.Log2SEW, TA_MA)>;
2697}
2698
2699foreach fvtiToFWti = AllWidenableBFloatToFloatVectors in {
2700  defvar fvti = fvtiToFWti.Vti;
2701  defvar fwti = fvtiToFWti.Wti;
2702  let Predicates = [HasVInstructionsBF16Minimal] in
2703  def : Pat<(fwti.Vector (any_riscv_fpextend_vl
2704                             (fvti.Vector fvti.RegClass:$rs1),
2705                             (fvti.Mask VMV0:$vm),
2706                             VLOpFrag)),
2707            (!cast<Instruction>("PseudoVFWCVTBF16_F_F_V_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
2708                (fwti.Vector (IMPLICIT_DEF)), fvti.RegClass:$rs1,
2709                (fvti.Mask VMV0:$vm),
2710                GPR:$vl, fvti.Log2SEW, TA_MA)>;
2711}
2712
2713// 13.19 Narrowing Floating-Point/Integer Type-Convert Instructions
2714defm : VPatNConvertFP2I_RM_VL_W<riscv_vfcvt_rm_xu_f_vl, "PseudoVFNCVT_XU_F_W">;
2715defm : VPatNConvertFP2I_RM_VL_W<riscv_vfcvt_rm_x_f_vl, "PseudoVFNCVT_X_F_W">;
2716
2717defm : VPatNConvertFP2IVL_W<any_riscv_vfcvt_rtz_xu_f_vl, "PseudoVFNCVT_RTZ_XU_F_W">;
2718defm : VPatNConvertFP2IVL_W<any_riscv_vfcvt_rtz_x_f_vl, "PseudoVFNCVT_RTZ_X_F_W">;
2719
2720defm : VPatNConvertI2FPVL_W_RM<any_riscv_uint_to_fp_vl, "PseudoVFNCVT_F_XU_W">;
2721defm : VPatNConvertI2FPVL_W_RM<any_riscv_sint_to_fp_vl, "PseudoVFNCVT_F_X_W">;
2722
2723defm : VPatNConvertI2FP_RM_VL_W<riscv_vfcvt_rm_f_xu_vl, "PseudoVFNCVT_F_XU_W">;
2724defm : VPatNConvertI2FP_RM_VL_W<riscv_vfcvt_rm_f_x_vl, "PseudoVFNCVT_F_X_W">;
2725
2726foreach fvtiToFWti = AllWidenableFloatVectors in {
2727  defvar fvti = fvtiToFWti.Vti;
2728  defvar fwti = fvtiToFWti.Wti;
2729  // Define vfncvt.f.f.w for f16 when Zvfhmin is enable.
2730  let Predicates = !listconcat(GetVTypeMinimalPredicates<fvti>.Predicates,
2731                               GetVTypeMinimalPredicates<fwti>.Predicates) in {
2732    def : Pat<(fvti.Vector (any_riscv_fpround_vl
2733                               (fwti.Vector fwti.RegClass:$rs1),
2734                               (fwti.Mask VMV0:$vm), VLOpFrag)),
2735              (!cast<Instruction>("PseudoVFNCVT_F_F_W_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
2736                  (fvti.Vector (IMPLICIT_DEF)), fwti.RegClass:$rs1,
2737                  (fwti.Mask VMV0:$vm),
2738                  // Value to indicate no rounding mode change in
2739                  // RISCVInsertReadWriteCSR
2740                  FRM_DYN,
2741                  GPR:$vl, fvti.Log2SEW, TA_MA)>;
2742
2743  let Predicates = !listconcat(GetVTypePredicates<fvti>.Predicates,
2744                               GetVTypePredicates<fwti>.Predicates) in
2745    def : Pat<(fvti.Vector (any_riscv_fncvt_rod_vl
2746                               (fwti.Vector fwti.RegClass:$rs1),
2747                               (fwti.Mask VMV0:$vm), VLOpFrag)),
2748              (!cast<Instruction>("PseudoVFNCVT_ROD_F_F_W_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
2749                  (fvti.Vector (IMPLICIT_DEF)), fwti.RegClass:$rs1,
2750                  (fwti.Mask VMV0:$vm), GPR:$vl, fvti.Log2SEW, TA_MA)>;
2751  }
2752}
2753
2754foreach fvtiToFWti = AllWidenableBFloatToFloatVectors in {
2755  defvar fvti = fvtiToFWti.Vti;
2756  defvar fwti = fvtiToFWti.Wti;
2757  let Predicates = [HasVInstructionsBF16Minimal] in
2758    def : Pat<(fvti.Vector (any_riscv_fpround_vl
2759                               (fwti.Vector fwti.RegClass:$rs1),
2760                               (fwti.Mask VMV0:$vm), VLOpFrag)),
2761              (!cast<Instruction>("PseudoVFNCVTBF16_F_F_W_"#fvti.LMul.MX#"_E"#fvti.SEW#"_MASK")
2762                  (fvti.Vector (IMPLICIT_DEF)), fwti.RegClass:$rs1,
2763                  (fwti.Mask VMV0:$vm),
2764                  // Value to indicate no rounding mode change in
2765                  // RISCVInsertReadWriteCSR
2766                  FRM_DYN,
2767                  GPR:$vl, fvti.Log2SEW, TA_MA)>;
2768}
2769
2770// 14. Vector Reduction Operations
2771
2772// 14.1. Vector Single-Width Integer Reduction Instructions
2773defm : VPatReductionVL<rvv_vecreduce_ADD_vl,  "PseudoVREDSUM", is_float=0>;
2774defm : VPatReductionVL<rvv_vecreduce_UMAX_vl, "PseudoVREDMAXU", is_float=0>;
2775defm : VPatReductionVL<rvv_vecreduce_SMAX_vl, "PseudoVREDMAX", is_float=0>;
2776defm : VPatReductionVL<rvv_vecreduce_UMIN_vl, "PseudoVREDMINU", is_float=0>;
2777defm : VPatReductionVL<rvv_vecreduce_SMIN_vl, "PseudoVREDMIN", is_float=0>;
2778defm : VPatReductionVL<rvv_vecreduce_AND_vl,  "PseudoVREDAND", is_float=0>;
2779defm : VPatReductionVL<rvv_vecreduce_OR_vl,   "PseudoVREDOR", is_float=0>;
2780defm : VPatReductionVL<rvv_vecreduce_XOR_vl,  "PseudoVREDXOR", is_float=0>;
2781
2782// 14.2. Vector Widening Integer Reduction Instructions
2783defm : VPatWidenReductionVL<rvv_vecreduce_ADD_vl, anyext_oneuse, "PseudoVWREDSUMU", is_float=0>;
2784defm : VPatWidenReductionVL<rvv_vecreduce_ADD_vl, zext_oneuse, "PseudoVWREDSUMU", is_float=0>;
2785defm : VPatWidenReductionVL_Ext_VL<rvv_vecreduce_ADD_vl, riscv_zext_vl_oneuse, "PseudoVWREDSUMU", is_float=0>;
2786defm : VPatWidenReductionVL<rvv_vecreduce_ADD_vl, sext_oneuse, "PseudoVWREDSUM", is_float=0>;
2787defm : VPatWidenReductionVL_Ext_VL<rvv_vecreduce_ADD_vl, riscv_sext_vl_oneuse, "PseudoVWREDSUM", is_float=0>;
2788
2789// 14.3. Vector Single-Width Floating-Point Reduction Instructions
2790defm : VPatReductionVL_RM<rvv_vecreduce_SEQ_FADD_vl, "PseudoVFREDOSUM", is_float=1>;
2791defm : VPatReductionVL_RM<rvv_vecreduce_FADD_vl,     "PseudoVFREDUSUM", is_float=1>;
2792defm : VPatReductionVL<rvv_vecreduce_FMIN_vl,     "PseudoVFREDMIN", is_float=1>;
2793defm : VPatReductionVL<rvv_vecreduce_FMAX_vl,     "PseudoVFREDMAX", is_float=1>;
2794
2795// 14.4. Vector Widening Floating-Point Reduction Instructions
2796defm : VPatWidenReductionVL_Ext_VL_RM<rvv_vecreduce_SEQ_FADD_vl,
2797                                      riscv_fpextend_vl_oneuse,
2798                                      "PseudoVFWREDOSUM", is_float=1>;
2799defm : VPatWidenReductionVL_Ext_VL_RM<rvv_vecreduce_FADD_vl,
2800                                      riscv_fpextend_vl_oneuse,
2801                                      "PseudoVFWREDUSUM", is_float=1>;
2802
2803// 15. Vector Mask Instructions
2804
2805foreach mti = AllMasks in {
2806  let Predicates = [HasVInstructions] in {
2807    // 15.1 Vector Mask-Register Logical Instructions
2808    def : Pat<(mti.Mask (riscv_vmset_vl VLOpFrag)),
2809              (!cast<Instruction>("PseudoVMSET_M_" # mti.BX) GPR:$vl, mti.Log2SEW)>;
2810    def : Pat<(mti.Mask (riscv_vmclr_vl VLOpFrag)),
2811              (!cast<Instruction>("PseudoVMCLR_M_" # mti.BX) GPR:$vl, mti.Log2SEW)>;
2812
2813    def : Pat<(mti.Mask (riscv_vmand_vl VR:$rs1, VR:$rs2, VLOpFrag)),
2814              (!cast<Instruction>("PseudoVMAND_MM_" # mti.BX)
2815                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2816    def : Pat<(mti.Mask (riscv_vmor_vl VR:$rs1, VR:$rs2, VLOpFrag)),
2817              (!cast<Instruction>("PseudoVMOR_MM_" # mti.BX)
2818                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2819    def : Pat<(mti.Mask (riscv_vmxor_vl VR:$rs1, VR:$rs2, VLOpFrag)),
2820              (!cast<Instruction>("PseudoVMXOR_MM_" # mti.BX)
2821                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2822
2823    def : Pat<(mti.Mask (riscv_vmand_vl VR:$rs1,
2824                                        (riscv_vmnot_vl VR:$rs2, VLOpFrag),
2825                                        VLOpFrag)),
2826              (!cast<Instruction>("PseudoVMANDN_MM_" # mti.BX)
2827                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2828    def : Pat<(mti.Mask (riscv_vmor_vl VR:$rs1,
2829                                       (riscv_vmnot_vl VR:$rs2, VLOpFrag),
2830                                       VLOpFrag)),
2831              (!cast<Instruction>("PseudoVMORN_MM_" # mti.BX)
2832                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2833    // XOR is associative so we need 2 patterns for VMXNOR.
2834    def : Pat<(mti.Mask (riscv_vmxor_vl (riscv_vmnot_vl VR:$rs1,
2835                                                        VLOpFrag),
2836                                       VR:$rs2, VLOpFrag)),
2837              (!cast<Instruction>("PseudoVMXNOR_MM_" # mti.BX)
2838                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2839
2840    def : Pat<(mti.Mask (riscv_vmnot_vl (riscv_vmand_vl VR:$rs1, VR:$rs2,
2841                                                        VLOpFrag),
2842                                        VLOpFrag)),
2843              (!cast<Instruction>("PseudoVMNAND_MM_" # mti.BX)
2844                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2845    def : Pat<(mti.Mask (riscv_vmnot_vl (riscv_vmor_vl VR:$rs1, VR:$rs2,
2846                                                       VLOpFrag),
2847                                        VLOpFrag)),
2848              (!cast<Instruction>("PseudoVMNOR_MM_" # mti.BX)
2849                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2850    def : Pat<(mti.Mask (riscv_vmnot_vl (riscv_vmxor_vl VR:$rs1, VR:$rs2,
2851                                                        VLOpFrag),
2852                                        VLOpFrag)),
2853              (!cast<Instruction>("PseudoVMXNOR_MM_" # mti.BX)
2854                   VR:$rs1, VR:$rs2, GPR:$vl, mti.Log2SEW)>;
2855
2856    // Match the not idiom to the vmnot.m pseudo.
2857    def : Pat<(mti.Mask (riscv_vmnot_vl VR:$rs, VLOpFrag)),
2858              (!cast<Instruction>("PseudoVMNAND_MM_" # mti.BX)
2859                   VR:$rs, VR:$rs, GPR:$vl, mti.Log2SEW)>;
2860
2861    // 15.2 Vector count population in mask vcpop.m
2862    def : Pat<(XLenVT (riscv_vcpop_vl (mti.Mask VR:$rs2), (mti.Mask VMV0:$vm),
2863                                      VLOpFrag)),
2864              (!cast<Instruction>("PseudoVCPOP_M_" # mti.BX # "_MASK")
2865                   VR:$rs2, (mti.Mask VMV0:$vm), GPR:$vl, mti.Log2SEW)>;
2866
2867    // 15.3 vfirst find-first-set mask bit
2868    def : Pat<(XLenVT (riscv_vfirst_vl (mti.Mask VR:$rs2), (mti.Mask VMV0:$vm),
2869                                      VLOpFrag)),
2870              (!cast<Instruction>("PseudoVFIRST_M_" # mti.BX # "_MASK")
2871                   VR:$rs2, (mti.Mask VMV0:$vm), GPR:$vl, mti.Log2SEW)>;
2872  }
2873}
2874
2875// 16. Vector Permutation Instructions
2876
2877// 16.1. Integer Scalar Move Instructions
2878foreach vti = NoGroupIntegerVectors in {
2879  let Predicates = GetVTypePredicates<vti>.Predicates in {
2880    def : Pat<(vti.Vector (riscv_vmv_s_x_vl (vti.Vector vti.RegClass:$passthru),
2881                                            vti.ScalarRegClass:$rs1,
2882                                            VLOpFrag)),
2883              (PseudoVMV_S_X $passthru, vti.ScalarRegClass:$rs1, GPR:$vl,
2884                             vti.Log2SEW)>;
2885  }
2886}
2887
2888// 16.4. Vector Register Gather Instruction
2889foreach vti = AllIntegerVectors in {
2890  let Predicates = GetVTypePredicates<vti>.Predicates in {
2891    def : Pat<(vti.Vector (riscv_vrgather_vv_vl vti.RegClass:$rs2,
2892                                                vti.RegClass:$rs1,
2893                                                vti.RegClass:$passthru,
2894                                                (vti.Mask VMV0:$vm),
2895                                                VLOpFrag)),
2896              (!cast<Instruction>("PseudoVRGATHER_VV_"# vti.LMul.MX#"_E"# vti.SEW#"_MASK")
2897                   vti.RegClass:$passthru, vti.RegClass:$rs2, vti.RegClass:$rs1,
2898                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2899    def : Pat<(vti.Vector (riscv_vrgather_vx_vl vti.RegClass:$rs2, GPR:$rs1,
2900                                                vti.RegClass:$passthru,
2901                                                (vti.Mask VMV0:$vm),
2902                                                VLOpFrag)),
2903              (!cast<Instruction>("PseudoVRGATHER_VX_"# vti.LMul.MX#"_MASK")
2904                   vti.RegClass:$passthru, vti.RegClass:$rs2, GPR:$rs1,
2905                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2906    def : Pat<(vti.Vector (riscv_vrgather_vx_vl vti.RegClass:$rs2,
2907                                                uimm5:$imm,
2908                                                vti.RegClass:$passthru,
2909                                                (vti.Mask VMV0:$vm),
2910                                                VLOpFrag)),
2911              (!cast<Instruction>("PseudoVRGATHER_VI_"# vti.LMul.MX#"_MASK")
2912                   vti.RegClass:$passthru, vti.RegClass:$rs2, uimm5:$imm,
2913                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2914  }
2915
2916  // emul = lmul * 16 / sew
2917  defvar vlmul = vti.LMul;
2918  defvar octuple_lmul = vlmul.octuple;
2919  defvar octuple_emul = !srl(!mul(octuple_lmul, 16), vti.Log2SEW);
2920  if !and(!ge(octuple_emul, 1), !le(octuple_emul, 64)) then {
2921    defvar emul_str = octuple_to_str<octuple_emul>.ret;
2922    defvar ivti = !cast<VTypeInfo>("VI16" # emul_str);
2923    defvar inst = "PseudoVRGATHEREI16_VV_" # vti.LMul.MX # "_E" # vti.SEW # "_" # emul_str;
2924    let Predicates = GetVTypePredicates<vti>.Predicates in
2925    def : Pat<(vti.Vector
2926               (riscv_vrgatherei16_vv_vl vti.RegClass:$rs2,
2927                                         (ivti.Vector ivti.RegClass:$rs1),
2928                                         vti.RegClass:$passthru,
2929                                         (vti.Mask VMV0:$vm),
2930                                         VLOpFrag)),
2931              (!cast<Instruction>(inst#"_MASK")
2932                   vti.RegClass:$passthru, vti.RegClass:$rs2, ivti.RegClass:$rs1,
2933                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2934  }
2935}
2936
2937// 16.2. Floating-Point Scalar Move Instructions
2938foreach vti = NoGroupFloatVectors in {
2939  let Predicates = GetVTypePredicates<vti>.Predicates in {
2940    def : Pat<(vti.Vector (riscv_vfmv_s_f_vl (vti.Vector vti.RegClass:$passthru),
2941                                             (vti.Scalar (fpimm0)),
2942                                             VLOpFrag)),
2943              (PseudoVMV_S_X $passthru, (XLenVT X0), GPR:$vl, vti.Log2SEW)>;
2944    def : Pat<(vti.Vector (riscv_vfmv_s_f_vl (vti.Vector vti.RegClass:$passthru),
2945                                             (vti.Scalar (SelectScalarFPAsInt (XLenVT GPR:$imm))),
2946                                             VLOpFrag)),
2947              (PseudoVMV_S_X $passthru, GPR:$imm, GPR:$vl, vti.Log2SEW)>;
2948    def : Pat<(vti.Vector (riscv_vfmv_s_f_vl (vti.Vector vti.RegClass:$passthru),
2949                                             vti.ScalarRegClass:$rs1,
2950                                             VLOpFrag)),
2951              (!cast<Instruction>("PseudoVFMV_S_"#vti.ScalarSuffix)
2952                  vti.RegClass:$passthru,
2953                  (vti.Scalar vti.ScalarRegClass:$rs1), GPR:$vl, vti.Log2SEW)>;
2954  }
2955}
2956
2957foreach vti = AllFloatVectors in {
2958  defvar ivti = GetIntVTypeInfo<vti>.Vti;
2959  let Predicates = GetVTypePredicates<ivti>.Predicates in {
2960    def : Pat<(vti.Vector
2961               (riscv_vrgather_vv_vl vti.RegClass:$rs2,
2962                                     (ivti.Vector vti.RegClass:$rs1),
2963                                     vti.RegClass:$passthru,
2964                                     (vti.Mask VMV0:$vm),
2965                                     VLOpFrag)),
2966              (!cast<Instruction>("PseudoVRGATHER_VV_"# vti.LMul.MX#"_E"# vti.SEW#"_MASK")
2967                   vti.RegClass:$passthru, vti.RegClass:$rs2, vti.RegClass:$rs1,
2968                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2969    def : Pat<(vti.Vector (riscv_vrgather_vx_vl vti.RegClass:$rs2, GPR:$rs1,
2970                                                vti.RegClass:$passthru,
2971                                                (vti.Mask VMV0:$vm),
2972                                                VLOpFrag)),
2973              (!cast<Instruction>("PseudoVRGATHER_VX_"# vti.LMul.MX#"_MASK")
2974                   vti.RegClass:$passthru, vti.RegClass:$rs2, GPR:$rs1,
2975                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2976    def : Pat<(vti.Vector
2977               (riscv_vrgather_vx_vl vti.RegClass:$rs2,
2978                                     uimm5:$imm,
2979                                     vti.RegClass:$passthru,
2980                                     (vti.Mask VMV0:$vm),
2981                                     VLOpFrag)),
2982              (!cast<Instruction>("PseudoVRGATHER_VI_"# vti.LMul.MX#"_MASK")
2983                   vti.RegClass:$passthru, vti.RegClass:$rs2, uimm5:$imm,
2984                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
2985  }
2986
2987  defvar vlmul = vti.LMul;
2988  defvar octuple_lmul = vlmul.octuple;
2989  defvar octuple_emul = !srl(!mul(octuple_lmul, 16), vti.Log2SEW);
2990  if !and(!ge(octuple_emul, 1), !le(octuple_emul, 64)) then {
2991    defvar emul_str = octuple_to_str<octuple_emul>.ret;
2992    defvar ivti = !cast<VTypeInfo>("VI16" # emul_str);
2993    defvar inst = "PseudoVRGATHEREI16_VV_" # vti.LMul.MX # "_E" # vti.SEW # "_" # emul_str;
2994    let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
2995                                 GetVTypePredicates<ivti>.Predicates) in
2996    def : Pat<(vti.Vector
2997               (riscv_vrgatherei16_vv_vl vti.RegClass:$rs2,
2998                                         (ivti.Vector ivti.RegClass:$rs1),
2999                                         vti.RegClass:$passthru,
3000                                         (vti.Mask VMV0:$vm),
3001                                         VLOpFrag)),
3002              (!cast<Instruction>(inst#"_MASK")
3003                   vti.RegClass:$passthru, vti.RegClass:$rs2, ivti.RegClass:$rs1,
3004                   (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW, TAIL_AGNOSTIC)>;
3005  }
3006}
3007
3008//===----------------------------------------------------------------------===//
3009// Miscellaneous RISCVISD SDNodes
3010//===----------------------------------------------------------------------===//
3011
3012// Matches the semantics of the vid.v instruction, with a mask and VL
3013// operand.
3014let HasMaskOp = true in
3015def riscv_vid_vl : RVSDNode<"VID_VL", SDTypeProfile<1, 2, [SDTCisVec<0>,
3016                                                           SDTCVecEltisVT<1, i1>,
3017                                                           SDTCisSameNumEltsAs<0, 1>,
3018                                                           SDTCisVT<2, XLenVT>]>>;
3019
3020def SDTRVVSlide : SDTypeProfile<1, 6, [
3021  SDTCisVec<0>, SDTCisSameAs<1, 0>, SDTCisSameAs<2, 0>, SDTCisVT<3, XLenVT>,
3022  SDTCVecEltisVT<4, i1>, SDTCisSameNumEltsAs<0, 4>, SDTCisVT<5, XLenVT>,
3023  SDTCisVT<6, XLenVT>
3024]>;
3025def SDTRVVSlide1 : SDTypeProfile<1, 5, [
3026  SDTCisVec<0>, SDTCisSameAs<1, 0>, SDTCisSameAs<2, 0>, SDTCisInt<0>,
3027  SDTCisVT<3, XLenVT>, SDTCVecEltisVT<4, i1>, SDTCisSameNumEltsAs<0, 4>,
3028  SDTCisVT<5, XLenVT>
3029]>;
3030def SDTRVVFSlide1 : SDTypeProfile<1, 5, [
3031  SDTCisVec<0>, SDTCisSameAs<1, 0>, SDTCisSameAs<2, 0>, SDTCisFP<0>,
3032  SDTCisEltOfVec<3, 0>, SDTCVecEltisVT<4, i1>, SDTCisSameNumEltsAs<0, 4>,
3033  SDTCisVT<5, XLenVT>
3034]>;
3035
3036let HasMaskOp = true in {
3037  // Matches the semantics of vslideup/vslidedown. The first operand is the
3038  // pass-thru operand, the second is the source vector, the third is the XLenVT
3039  // index (either constant or non-constant), the fourth is the mask, the fifth
3040  // is the VL and the sixth is the policy.
3041  def riscv_slideup_vl   : RVSDNode<"VSLIDEUP_VL", SDTRVVSlide, []>;
3042  def riscv_slidedown_vl : RVSDNode<"VSLIDEDOWN_VL", SDTRVVSlide, []>;
3043
3044  // Matches the semantics of vslide1up/slide1down. The first operand is
3045  // passthru operand, the second is source vector, third is the XLenVT scalar
3046  // value. The fourth and fifth operands are the mask and VL operands.
3047  def riscv_slide1up_vl  : RVSDNode<"VSLIDE1UP_VL", SDTRVVSlide1, []>;
3048  def riscv_slide1down_vl  : RVSDNode<"VSLIDE1DOWN_VL", SDTRVVSlide1, []>;
3049
3050  // Matches the semantics of vfslide1up/vfslide1down. The first operand is
3051  // passthru operand, the second is source vector, third is a scalar value
3052  // whose type matches the element type of the vectors.  The fourth and fifth
3053  // operands are the mask and VL operands.
3054  def riscv_fslide1up_vl  : RVSDNode<"VFSLIDE1UP_VL", SDTRVVFSlide1, []>;
3055  def riscv_fslide1down_vl  : RVSDNode<"VFSLIDE1DOWN_VL", SDTRVVFSlide1, []>;
3056} // let HasMaskOp = true
3057
3058foreach vti = AllIntegerVectors in {
3059  let Predicates = GetVTypePredicates<vti>.Predicates in {
3060    def : Pat<(vti.Vector (riscv_vid_vl (vti.Mask VMV0:$vm),
3061                                        VLOpFrag)),
3062              (!cast<Instruction>("PseudoVID_V_"#vti.LMul.MX#"_MASK")
3063                  (vti.Vector (IMPLICIT_DEF)), (vti.Mask VMV0:$vm), GPR:$vl, vti.Log2SEW,
3064                  TAIL_AGNOSTIC)>;
3065  }
3066}
3067
3068defm : VPatSlideVL_VX_VI<riscv_slideup_vl, "PseudoVSLIDEUP">;
3069defm : VPatSlideVL_VX_VI<riscv_slidedown_vl, "PseudoVSLIDEDOWN">;
3070defm : VPatSlide1VL_VX<riscv_slide1up_vl, "PseudoVSLIDE1UP">;
3071defm : VPatSlide1VL_VF<riscv_fslide1up_vl, "PseudoVFSLIDE1UP">;
3072defm : VPatSlide1VL_VX<riscv_slide1down_vl, "PseudoVSLIDE1DOWN">;
3073defm : VPatSlide1VL_VF<riscv_fslide1down_vl, "PseudoVFSLIDE1DOWN">;
3074