1//==--- riscv_vector.td - RISC-V V-ext Builtin function list --------------===//
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 defines the builtins for RISC-V V-extension. See:
10//
11//     https://github.com/riscv/rvv-intrinsic-doc
12//
13//===----------------------------------------------------------------------===//
14
15//===----------------------------------------------------------------------===//
16// Instruction definitions
17//===----------------------------------------------------------------------===//
18// Each record of the class RVVBuiltin defines a collection of builtins (i.e.
19// "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1",
20// "vadd_vv_i32m2", etc).
21//
22// The elements of this collection are defined by an instantiation process the
23// range of which is specified by the cross product of the LMUL attribute and
24// every element in the attribute TypeRange. By default builtins have LMUL = [1,
25// 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we
26// use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL.
27//
28// LMUL represents the fact that the types of values used by that builtin are
29// values generated by instructions that are executed under that LMUL. However,
30// this does not mean the builtin is necessarily lowered into an instruction
31// that executes under the specified LMUL. An example where this happens are
32// loads and stores of masks. A mask like `vbool8_t` can be generated, for
33// instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two
34// `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will
35// be performed under LMUL=1 because mask registers are not grouped.
36//
37// TypeRange is a non-empty sequence of basic types:
38//
39//   c: int8_t (i8)
40//   s: int16_t (i16)
41//   i: int32_t (i32)
42//   l: int64_t (i64)
43//   x: float16_t (half)
44//   f: float32_t (float)
45//   d: float64_t (double)
46//
47// This way, given an LMUL, a record with a TypeRange "sil" will cause the
48// definition of 3 builtins. Each type "t" in the TypeRange (in this example
49// they are int16_t, int32_t, int64_t) is used as a parameter that drives the
50// definition of that particular builtin (for the given LMUL).
51//
52// During the instantiation, types can be transformed or modified using type
53// transformers. Given a type "t" the following primitive type transformers can
54// be applied to it to yield another type.
55//
56//   e: type of "t" as is (identity)
57//   v: computes a vector type whose element type is "t" for the current LMUL
58//   w: computes a vector type identical to what 'v' computes except for the
59//      element type which is twice as wide as the element type of 'v'
60//   q: computes a vector type identical to what 'v' computes except for the
61//      element type which is four times as wide as the element type of 'v'
62//   o: computes a vector type identical to what 'v' computes except for the
63//      element type which is eight times as wide as the element type of 'v'
64//   m: computes a vector type identical to what 'v' computes except for the
65//      element type which is bool
66//   0: void type, ignores "t"
67//   z: size_t, ignores "t"
68//   t: ptrdiff_t, ignores "t"
69//   u: unsigned long, ignores "t"
70//   l: long, ignores "t"
71//
72// So for instance if t is "i", i.e. int, then "e" will yield int again. "v"
73// will yield an RVV vector type (assume LMUL=1), so __rvv_int32m1_t.
74// Accordingly "w" would yield __rvv_int64m2_t.
75//
76// A type transformer can be prefixed by other non-primitive type transformers.
77//
78//   P: constructs a pointer to the current type
79//   C: adds const to the type
80//   K: requires the integer type to be a constant expression
81//   U: given an integer type or vector type, computes its unsigned variant
82//   I: given a vector type, compute the vector type with integer type
83//      elements of the same width
84//   F: given a vector type, compute the vector type with floating-point type
85//      elements of the same width
86//   S: given a vector type, computes its equivalent one for LMUL=1. This is a
87//      no-op if the vector was already LMUL=1
88//   (Log2EEW:Value): Log2EEW value could be 3/4/5/6 (8/16/32/64), given a
89//      vector type (SEW and LMUL) and EEW (8/16/32/64), computes its
90//      equivalent integer vector type with EEW and corresponding ELMUL (elmul =
91//      (eew/sew) * lmul). For example, vector type is __rvv_float16m4
92//      (SEW=16, LMUL=4) and Log2EEW is 3 (EEW=8), and then equivalent vector
93//      type is __rvv_uint8m2_t (elmul=(8/16)*4 = 2). Ignore to define a new
94//      builtins if its equivalent type has illegal lmul.
95//   (FixedSEW:Value): Given a vector type (SEW and LMUL), and computes another
96//      vector type which only changed SEW as given value. Ignore to define a new
97//      builtin if its equivalent type has illegal lmul or the SEW does not changed.
98//   (SFixedLog2LMUL:Value): Smaller Fixed Log2LMUL. Given a vector type (SEW
99//      and LMUL), and computes another vector type which only changed LMUL as
100//      given value. The new LMUL should be smaller than the old one. Ignore to
101//      define a new builtin if its equivalent type has illegal lmul.
102//   (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW
103//      and LMUL), and computes another vector type which only changed LMUL as
104//      given value. The new LMUL should be larger than the old one. Ignore to
105//      define a new builtin if its equivalent type has illegal lmul.
106//
107// Following with the example above, if t is "i", then "Ue" will yield unsigned
108// int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would
109// yield __rvv_float64m2_t, etc.
110//
111// Each builtin is then defined by applying each type in TypeRange against the
112// sequence of type transformers described in Suffix and Prototype.
113//
114// The name of the builtin is defined by the Name attribute (which defaults to
115// the name of the class) appended (separated with an underscore) the Suffix
116// attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il",
117// the builtin generated will be __builtin_rvv_foo_i32m1 and
118// __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one
119// type transformer (say "vv") each of the types is separated with an
120// underscore as in "__builtin_rvv_foo_i32m1_i32m1".
121//
122// The C/C++ prototype of the builtin is defined by the Prototype attribute.
123// Prototype is a non-empty sequence of type transformers, the first of which
124// is the return type of the builtin and the rest are the parameters of the
125// builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si"
126// a first builtin will have type
127// __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin
128// will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again
129// under LMUL=1).
130//
131// There are a number of attributes that are used to constraint the number and
132// shape of the builtins generated. Refer to the comments below for them.
133class RVVBuiltin<string suffix, string prototype, string type_range,
134                 string mangled_suffix = ""> {
135  // Base name that will be prepended in __builtin_rvv_ and appended the
136  // computed Suffix.
137  string Name = NAME;
138
139  // If not empty, each instantiated builtin will have this appended after an
140  // underscore (_). It is instantiated like Prototype.
141  string Suffix = suffix;
142
143  // If empty, default MangledName is sub string of `Name` which end of first
144  // '_'. For example, the default mangled name  is `vadd` for Name `vadd_vv`.
145  // It's used for describe some special naming cases.
146  string MangledName = "";
147
148  // If not empty, each MangledName will have this appended after an
149  // underscore (_). It is instantiated like Prototype.
150  string MangledSuffix = mangled_suffix;
151
152  // The different variants of the builtin, parameterised with a type.
153  string TypeRange = type_range;
154
155  // We use each type described in TypeRange and LMUL with prototype to
156  // instantiate a specific element of the set of builtins being defined.
157  // Prototype attribute defines the C/C++ prototype of the builtin. It is a
158  // non-empty sequence of type transformers, the first of which is the return
159  // type of the builtin and the rest are the parameters of the builtin, in
160  // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a
161  // first builtin will have type
162  // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin
163  // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t).
164  string Prototype = prototype;
165
166  // This builtin has a masked form.
167  bit HasMask = true;
168
169  // If HasMask, this flag states that this builtin has a maskedoff operand. It
170  // is always the first operand in builtin and IR intrinsic.
171  bit HasMaskedOffOperand = true;
172
173  // This builtin has a granted vector length parameter in the last position.
174  bit HasVL = true;
175
176  // This builtin supports non-masked function overloading api.
177  // All masked operations support overloading api.
178  bit HasNoMaskedOverloaded = true;
179
180  // Reads or writes "memory" or has other side-effects.
181  bit HasSideEffects = false;
182
183  // This builtin is valid for the given Log2LMULs.
184  list<int> Log2LMUL = [0, 1, 2, 3, -1, -2, -3];
185
186  // Manual code in clang codegen riscv_vector_builtin_cg.inc
187  code ManualCodegen = [{}];
188  code ManualCodegenMask = [{}];
189
190  // When emit the automatic clang codegen, it describes what types we have to use
191  // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise,
192  // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd
193  // parameter of the unmasked version. k can't be the mask operand's position.
194  list<int> IntrinsicTypes = [];
195
196  // If these names are not empty, this is the ID of the LLVM intrinsic
197  // we want to lower to.
198  string IRName = NAME;
199
200  // If HasMask, this is the ID of the LLVM intrinsic we want to lower to.
201  string IRNameMask = NAME #"_mask";
202
203  // If non empty, this is the code emitted in the header, otherwise
204  // an automatic definition in header is emitted.
205  string HeaderCode = "";
206
207  // Sub extension of vector spec. Currently only support Zvamo or Zvlsseg.
208  string RequiredExtension = "";
209
210  // Number of fields for Zvlsseg.
211  int NF = 1;
212}
213
214//===----------------------------------------------------------------------===//
215// Basic classes with automatic codegen.
216//===----------------------------------------------------------------------===//
217
218class RVVOutBuiltin<string suffix, string prototype, string type_range>
219    : RVVBuiltin<suffix, prototype, type_range> {
220  let IntrinsicTypes = [-1];
221}
222
223class RVVOp0Builtin<string suffix, string prototype, string type_range>
224    : RVVBuiltin<suffix, prototype, type_range> {
225  let IntrinsicTypes = [0];
226}
227
228class RVVOutOp1Builtin<string suffix, string prototype, string type_range>
229    : RVVBuiltin<suffix, prototype, type_range> {
230  let IntrinsicTypes = [-1, 1];
231}
232
233class RVVOutOp0Op1Builtin<string suffix, string prototype, string type_range>
234    : RVVBuiltin<suffix, prototype, type_range> {
235  let IntrinsicTypes = [-1, 0, 1];
236}
237
238multiclass RVVBuiltinSet<string intrinsic_name, string type_range,
239                         list<list<string>> suffixes_prototypes,
240                         list<int> intrinsic_types> {
241  let IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask",
242      IntrinsicTypes = intrinsic_types in {
243    foreach s_p = suffixes_prototypes in {
244      let Name = NAME # "_" # s_p[0] in {
245        defvar suffix = s_p[1];
246        defvar prototype = s_p[2];
247        def : RVVBuiltin<suffix, prototype, type_range>;
248      }
249    }
250  }
251}
252
253// IntrinsicTypes is output, op0, op1 [-1, 0, 1]
254multiclass RVVOutOp0Op1BuiltinSet<string intrinsic_name, string type_range,
255                                  list<list<string>> suffixes_prototypes>
256    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes,
257                            [-1, 0, 1]>;
258
259multiclass RVVOutBuiltinSet<string intrinsic_name, string type_range,
260                            list<list<string>> suffixes_prototypes>
261    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1]>;
262
263multiclass RVVOp0BuiltinSet<string intrinsic_name, string type_range,
264                            list<list<string>> suffixes_prototypes>
265    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0]>;
266
267// IntrinsicTypes is output, op1 [-1, 1]
268multiclass RVVOutOp1BuiltinSet<string intrinsic_name, string type_range,
269                               list<list<string>> suffixes_prototypes>
270    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1]>;
271
272multiclass RVVOp0Op1BuiltinSet<string intrinsic_name, string type_range,
273                               list<list<string>> suffixes_prototypes>
274    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0, 1]>;
275
276multiclass RVVOutOp1Op2BuiltinSet<string intrinsic_name, string type_range,
277                                  list<list<string>> suffixes_prototypes>
278    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1, 2]>;
279
280multiclass RVVSignedBinBuiltinSet
281    : RVVOutOp1BuiltinSet<NAME, "csil",
282                          [["vv", "v", "vvv"],
283                           ["vx", "v", "vve"]]>;
284
285multiclass RVVUnsignedBinBuiltinSet
286    : RVVOutOp1BuiltinSet<NAME, "csil",
287                          [["vv", "Uv", "UvUvUv"],
288                           ["vx", "Uv", "UvUvUe"]]>;
289
290multiclass RVVIntBinBuiltinSet
291    : RVVSignedBinBuiltinSet,
292      RVVUnsignedBinBuiltinSet;
293
294multiclass RVVSlideOneBuiltinSet
295    : RVVOutOp1BuiltinSet<NAME, "csil",
296                          [["vx", "v", "vve"],
297                           ["vx", "Uv", "UvUve"]]>;
298
299multiclass RVVSignedShiftBuiltinSet
300    : RVVOutOp1BuiltinSet<NAME, "csil",
301                          [["vv", "v", "vvUv"],
302                           ["vx", "v", "vvz"]]>;
303
304multiclass RVVUnsignedShiftBuiltinSet
305    : RVVOutOp1BuiltinSet<NAME, "csil",
306                          [["vv", "Uv", "UvUvUv"],
307                           ["vx", "Uv", "UvUvz"]]>;
308
309multiclass RVVShiftBuiltinSet
310    : RVVSignedShiftBuiltinSet,
311      RVVUnsignedShiftBuiltinSet;
312
313let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
314  multiclass RVVSignedNShiftBuiltinSet
315      : RVVOutOp0Op1BuiltinSet<NAME, "csil",
316                                     [["wv", "v", "vwUv"],
317                                      ["wx", "v", "vwz"]]>;
318  multiclass RVVUnsignedNShiftBuiltinSet
319      : RVVOutOp0Op1BuiltinSet<NAME, "csil",
320                                     [["wv", "Uv", "UvUwUv"],
321                                      ["wx", "Uv", "UvUwz"]]>;
322}
323
324multiclass RVVCarryinBuiltinSet
325    : RVVOutOp1BuiltinSet<NAME, "csil",
326                          [["vvm", "v", "vvvm"],
327                           ["vxm", "v", "vvem"],
328                           ["vvm", "Uv", "UvUvUvm"],
329                           ["vxm", "Uv", "UvUvUem"]]>;
330
331multiclass RVVCarryOutInBuiltinSet<string intrinsic_name>
332    : RVVOp0Op1BuiltinSet<intrinsic_name, "csil",
333                          [["vvm", "vm", "mvvm"],
334                           ["vxm", "vm", "mvem"],
335                           ["vvm", "Uvm", "mUvUvm"],
336                           ["vxm", "Uvm", "mUvUem"]]>;
337
338multiclass RVVSignedMaskOutBuiltinSet
339    : RVVOp0Op1BuiltinSet<NAME, "csil",
340                          [["vv", "vm", "mvv"],
341                           ["vx", "vm", "mve"]]>;
342
343multiclass RVVUnsignedMaskOutBuiltinSet
344    : RVVOp0Op1BuiltinSet<NAME, "csil",
345                          [["vv", "Uvm", "mUvUv"],
346                           ["vx", "Uvm", "mUvUe"]]>;
347
348multiclass RVVIntMaskOutBuiltinSet
349    : RVVSignedMaskOutBuiltinSet,
350      RVVUnsignedMaskOutBuiltinSet;
351
352class RVVIntExt<string intrinsic_name, string suffix, string prototype,
353                string type_range>
354    : RVVBuiltin<suffix, prototype, type_range> {
355  let IRName = intrinsic_name;
356  let IRNameMask = intrinsic_name # "_mask";
357  let MangledName = NAME;
358  let IntrinsicTypes = [-1, 0];
359}
360
361let HasMaskedOffOperand = false in {
362  multiclass RVVIntTerBuiltinSet {
363    defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
364                                  [["vv", "v", "vvvv"],
365                                   ["vx", "v", "vvev"],
366                                   ["vv", "Uv", "UvUvUvUv"],
367                                   ["vx", "Uv", "UvUvUeUv"]]>;
368  }
369  multiclass RVVFloatingTerBuiltinSet {
370    defm "" : RVVOutOp1BuiltinSet<NAME, "xfd",
371                                  [["vv", "v", "vvvv"],
372                                   ["vf", "v", "vvev"]]>;
373  }
374}
375
376let HasMaskedOffOperand = false, Log2LMUL = [-2, -1, 0, 1, 2] in {
377  multiclass RVVFloatingWidenTerBuiltinSet {
378    defm ""  : RVVOutOp1Op2BuiltinSet<NAME, "xf",
379                                      [["vv", "w", "wwvv"],
380                                       ["vf", "w", "wwev"]]>;
381  }
382}
383
384multiclass RVVFloatingBinBuiltinSet
385    : RVVOutOp1BuiltinSet<NAME, "xfd",
386                          [["vv", "v", "vvv"],
387                           ["vf", "v", "vve"]]>;
388
389multiclass RVVFloatingBinVFBuiltinSet
390    : RVVOutOp1BuiltinSet<NAME, "xfd",
391                          [["vf", "v", "vve"]]>;
392
393multiclass RVVFloatingMaskOutBuiltinSet
394    : RVVOp0Op1BuiltinSet<NAME, "xfd",
395                          [["vv", "vm", "mvv"],
396                           ["vf", "vm", "mve"]]>;
397
398multiclass RVVFloatingMaskOutVFBuiltinSet
399    : RVVOp0Op1BuiltinSet<NAME, "fd",
400                          [["vf", "vm", "mve"]]>;
401
402class RVVMaskBinBuiltin : RVVOutBuiltin<"m", "mmm", "c"> {
403  let Name = NAME # "_mm";
404  let HasMask = false;
405}
406
407class RVVMaskUnaryBuiltin : RVVOutBuiltin<"m", "mm", "c"> {
408  let Name = NAME # "_m";
409}
410
411class RVVMaskNullaryBuiltin : RVVOutBuiltin<"m", "m", "c"> {
412  let Name = NAME # "_m";
413  let HasMask = false;
414  let HasNoMaskedOverloaded = false;
415}
416
417class RVVMaskOp0Builtin<string prototype> : RVVOp0Builtin<"m", prototype, "c"> {
418  let Name = NAME # "_m";
419  let HasMaskedOffOperand = false;
420}
421
422let HasMaskedOffOperand = false in {
423  multiclass RVVSlideBuiltinSet {
424    defm "" : RVVOutBuiltinSet<NAME, "csilxfd",
425                               [["vx","v", "vvvz"]]>;
426    defm "" : RVVOutBuiltinSet<NAME, "csil",
427                               [["vx","Uv", "UvUvUvz"]]>;
428  }
429}
430
431class RVVFloatingUnaryBuiltin<string builtin_suffix, string ir_suffix,
432                              string prototype>
433    : RVVOutBuiltin<ir_suffix, prototype, "xfd"> {
434  let Name = NAME # "_" # builtin_suffix;
435}
436
437class RVVFloatingUnaryVVBuiltin : RVVFloatingUnaryBuiltin<"v", "v", "vv">;
438
439class RVVConvBuiltin<string suffix, string prototype, string type_range,
440                     string mangled_name>
441    : RVVBuiltin<suffix, prototype, type_range> {
442  let IntrinsicTypes = [-1, 0];
443  let MangledName = mangled_name;
444}
445
446class RVVConvToSignedBuiltin<string mangled_name>
447    : RVVConvBuiltin<"Iv", "Ivv", "xfd", mangled_name>;
448
449class RVVConvToUnsignedBuiltin<string mangled_name>
450    : RVVConvBuiltin<"Uv", "Uvv", "xfd", mangled_name>;
451
452class RVVConvToWidenSignedBuiltin<string mangled_name>
453    : RVVConvBuiltin<"Iw", "Iwv", "xf", mangled_name>;
454
455class RVVConvToWidenUnsignedBuiltin<string mangled_name>
456    : RVVConvBuiltin<"Uw", "Uwv", "xf", mangled_name>;
457
458class RVVConvToNarrowingSignedBuiltin<string mangled_name>
459    : RVVConvBuiltin<"Iv", "IvFw", "csi", mangled_name>;
460
461class RVVConvToNarrowingUnsignedBuiltin<string mangled_name>
462    : RVVConvBuiltin<"Uv", "UvFw", "csi", mangled_name>;
463
464let HasMaskedOffOperand = false in {
465  multiclass RVVSignedReductionBuiltin {
466    defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
467                                  [["vs", "vSv", "SvSvvSv"]]>;
468  }
469  multiclass RVVUnsignedReductionBuiltin {
470    defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
471                                  [["vs", "UvUSv", "USvUSvUvUSv"]]>;
472  }
473  multiclass RVVFloatingReductionBuiltin {
474    defm "" : RVVOutOp1BuiltinSet<NAME, "xfd",
475                                  [["vs", "vSv", "SvSvvSv"]]>;
476  }
477  multiclass RVVFloatingWidenReductionBuiltin {
478    defm "" : RVVOutOp1BuiltinSet<NAME, "xf",
479                                  [["vs", "vSw", "SwSwvSw"]]>;
480  }
481}
482
483multiclass RVVIntReductionBuiltinSet
484    : RVVSignedReductionBuiltin,
485      RVVUnsignedReductionBuiltin;
486
487// For widen operation which has different mangling name.
488multiclass RVVWidenBuiltinSet<string intrinsic_name, string type_range,
489                              list<list<string>> suffixes_prototypes> {
490  let Log2LMUL = [-3, -2, -1, 0, 1, 2],
491      IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask" in {
492    foreach s_p = suffixes_prototypes in {
493      let Name = NAME # "_" # s_p[0],
494          MangledName = NAME # "_" # s_p[0] in {
495        defvar suffix = s_p[1];
496        defvar prototype = s_p[2];
497        def : RVVOutOp0Op1Builtin<suffix, prototype, type_range>;
498      }
499    }
500  }
501}
502
503// For widen operation with widen operand which has different mangling name.
504multiclass RVVWidenWOp0BuiltinSet<string intrinsic_name, string type_range,
505                                  list<list<string>> suffixes_prototypes> {
506  let Log2LMUL = [-3, -2, -1, 0, 1, 2],
507      IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask" in {
508    foreach s_p = suffixes_prototypes in {
509      let Name = NAME # "_" # s_p[0],
510          MangledName = NAME # "_" # s_p[0] in {
511        defvar suffix = s_p[1];
512        defvar prototype = s_p[2];
513        def : RVVOutOp1Builtin<suffix, prototype, type_range>;
514      }
515    }
516  }
517}
518
519multiclass RVVSignedWidenBinBuiltinSet
520    : RVVWidenBuiltinSet<NAME, "csi",
521                         [["vv", "w", "wvv"],
522                          ["vx", "w", "wve"]]>;
523
524multiclass RVVSignedWidenOp0BinBuiltinSet
525    : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
526                             [["wv", "w", "wwv"],
527                              ["wx", "w", "wwe"]]>;
528
529multiclass RVVUnsignedWidenBinBuiltinSet
530    : RVVWidenBuiltinSet<NAME, "csi",
531                         [["vv", "Uw", "UwUvUv"],
532                          ["vx", "Uw", "UwUvUe"]]>;
533
534multiclass RVVUnsignedWidenOp0BinBuiltinSet
535    : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
536                             [["wv", "Uw", "UwUwUv"],
537                              ["wx", "Uw", "UwUwUe"]]>;
538
539multiclass RVVFloatingWidenBinBuiltinSet
540    : RVVWidenBuiltinSet<NAME, "xf",
541                         [["vv", "w", "wvv"],
542                          ["vf", "w", "wve"]]>;
543
544multiclass RVVFloatingWidenOp0BinBuiltinSet
545    : RVVWidenWOp0BuiltinSet<NAME # "_w", "xf",
546                             [["wv", "w", "wwv"],
547                              ["wf", "w", "wwe"]]>;
548
549defvar TypeList = ["c","s","i","l","x","f","d"];
550defvar EEWList = [["8", "(Log2EEW:3)"],
551                  ["16", "(Log2EEW:4)"],
552                  ["32", "(Log2EEW:5)"],
553                  ["64", "(Log2EEW:6)"]];
554
555class IsFloat<string type> {
556  bit val = !or(!eq(type, "x"), !eq(type, "f"), !eq(type, "d"));
557}
558
559let HasNoMaskedOverloaded = false,
560    ManualCodegen = [{
561      IntrinsicTypes = {ResultType, Ops[1]->getType()};
562      Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
563    }],
564    ManualCodegenMask= [{
565      // Move mask to right before vl.
566      std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
567      IntrinsicTypes = {ResultType, Ops[3]->getType()};
568      Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
569    }] in {
570  class RVVVLEMaskBuiltin : RVVBuiltin<"m", "mPCUe", "c"> {
571    let Name = "vle1_v";
572    let IRName = "vle1";
573    let HasMask = false;
574  }
575  multiclass RVVVLEBuiltin<list<string> types> {
576    let Name = NAME # "_v",
577        IRName = "vle",
578        IRNameMask ="vle_mask" in {
579      foreach type = types in {
580        def : RVVBuiltin<"v", "vPCe", type>;
581        if !not(IsFloat<type>.val) then {
582          def : RVVBuiltin<"Uv", "UvPCUe", type>;
583        }
584      }
585    }
586  }
587}
588
589multiclass RVVVLEFFBuiltin<list<string> types> {
590  let Name = NAME # "_v",
591      IRName = "vleff",
592      IRNameMask = "vleff_mask",
593      HasNoMaskedOverloaded = false,
594      ManualCodegen = [{
595      {
596        IntrinsicTypes = {ResultType, Ops[2]->getType()};
597        Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
598        Value *NewVL = Ops[1];
599        Ops.erase(Ops.begin() + 1);
600        llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
601        llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
602        llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
603        // Store new_vl.
604        clang::CharUnits Align =
605            CGM.getNaturalTypeAlignment(getContext().getSizeType());
606        Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {1}),
607                            Address(NewVL, Align));
608        return V;
609      }
610      }],
611      ManualCodegenMask = [{
612      {
613        // Move mask to right before vl.
614        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
615        IntrinsicTypes = {ResultType, Ops[4]->getType()};
616        Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
617        Value *NewVL = Ops[2];
618        Ops.erase(Ops.begin() + 2);
619        llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
620        llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
621        llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
622        // Store new_vl.
623        clang::CharUnits Align =
624            CGM.getNaturalTypeAlignment(getContext().getSizeType());
625        Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {1}),
626                            Address(NewVL, Align));
627        return V;
628      }
629      }] in {
630    foreach type = types in {
631      def : RVVBuiltin<"v", "vPCePz", type>;
632      // Skip floating types for unsigned versions.
633      if !not(IsFloat<type>.val) then {
634        def : RVVBuiltin<"Uv", "UvPCUePz", type>;
635      }
636    }
637  }
638}
639
640multiclass RVVVLSEBuiltin<list<string> types> {
641  let Name = NAME # "_v",
642      IRName = "vlse",
643      IRNameMask ="vlse_mask",
644      HasNoMaskedOverloaded = false,
645      ManualCodegen = [{
646        IntrinsicTypes = {ResultType, Ops[2]->getType()};
647        Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
648      }],
649      ManualCodegenMask= [{
650        // Move mask to right before vl.
651        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
652        IntrinsicTypes = {ResultType, Ops[4]->getType()};
653        Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
654      }] in {
655    foreach type = types in {
656      def : RVVBuiltin<"v", "vPCet", type>;
657      if !not(IsFloat<type>.val) then {
658        def : RVVBuiltin<"Uv", "UvPCUet", type>;
659      }
660    }
661  }
662}
663
664multiclass RVVIndexedLoad<string op> {
665  let ManualCodegen = [{
666        IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType()};
667        Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
668      }],
669      ManualCodegenMask = [{
670        // Move mask to right before vl.
671        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
672        IntrinsicTypes = {ResultType, Ops[2]->getType(), Ops[4]->getType()};
673        Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
674      }] in {
675      foreach type = TypeList in {
676        foreach eew_list = EEWList in {
677          defvar eew = eew_list[0];
678          defvar eew_type = eew_list[1];
679          let Name = op # eew # "_v", IRName = op, IRNameMask = op # "_mask" in {
680            def: RVVBuiltin<"v", "vPCe" # eew_type # "Uv", type>;
681              if !not(IsFloat<type>.val) then {
682                def: RVVBuiltin<"Uv", "UvPCUe" # eew_type # "Uv", type>;
683              }
684          }
685        }
686      }
687  }
688}
689
690let HasMaskedOffOperand = false,
691    ManualCodegen = [{
692      // Builtin: (ptr, value, vl). Intrinsic: (value, ptr, vl)
693      std::swap(Ops[0], Ops[1]);
694      Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
695      IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType()};
696    }],
697    ManualCodegenMask= [{
698      // Builtin: (mask, ptr, value, vl). Intrinsic: (value, ptr, mask, vl)
699      std::swap(Ops[0], Ops[2]);
700      Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
701      IntrinsicTypes = {Ops[0]->getType(), Ops[3]->getType()};
702    }] in {
703  class RVVVSEMaskBuiltin : RVVBuiltin<"m", "0PUem", "c"> {
704    let Name = "vse1_v";
705    let IRName = "vse1";
706    let HasMask = false;
707  }
708  multiclass RVVVSEBuiltin<list<string> types> {
709    let Name = NAME # "_v",
710        IRName = "vse",
711        IRNameMask = "vse_mask" in {
712      foreach type = types in {
713        def : RVVBuiltin<"v", "0Pev", type>;
714        if !not(IsFloat<type>.val) then {
715          def : RVVBuiltin<"Uv", "0PUeUv", type>;
716        }
717      }
718    }
719  }
720}
721
722multiclass RVVVSSEBuiltin<list<string> types> {
723  let Name = NAME # "_v",
724      IRName = "vsse",
725      IRNameMask = "vsse_mask",
726      HasMaskedOffOperand = false,
727      ManualCodegen = [{
728        // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl)
729        std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
730        Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
731        IntrinsicTypes = {Ops[0]->getType(), Ops[3]->getType()};
732      }],
733      ManualCodegenMask= [{
734        // Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride, mask, vl)
735        std::swap(Ops[0], Ops[3]);
736        Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
737        IntrinsicTypes = {Ops[0]->getType(), Ops[4]->getType()};
738      }] in {
739    foreach type = types in {
740      def : RVVBuiltin<"v", "0Petv", type>;
741      if !not(IsFloat<type>.val) then {
742        def : RVVBuiltin<"Uv", "0PUetUv", type>;
743      }
744    }
745  }
746}
747
748multiclass RVVIndexedStore<string op> {
749  let HasMaskedOffOperand = false,
750      ManualCodegen = [{
751        // Builtin: (ptr, index, value, vl). Intrinsic: (value, ptr, index, vl)
752        std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
753        Ops[1] = Builder.CreateBitCast(Ops[1],Ops[0]->getType()->getPointerTo());
754        IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType(), Ops[3]->getType()};
755      }],
756      ManualCodegenMask= [{
757        // Builtin: (mask, ptr, index, value, vl). Intrinsic: (value, ptr, index, mask, vl)
758        std::swap(Ops[0], Ops[3]);
759        Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
760        IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType(), Ops[4]->getType()};
761      }] in {
762      foreach type = TypeList in {
763        foreach eew_list = EEWList in {
764          defvar eew = eew_list[0];
765          defvar eew_type = eew_list[1];
766          let Name = op # eew  # "_v", IRName = op, IRNameMask = op # "_mask" in  {
767            def : RVVBuiltin<"v", "0Pe" # eew_type # "Uvv", type>;
768            if !not(IsFloat<type>.val) then {
769              def : RVVBuiltin<"Uv", "0PUe" # eew_type # "UvUv", type>;
770            }
771          }
772        }
773      }
774  }
775}
776
777defvar NFList = [2, 3, 4, 5, 6, 7, 8];
778
779class PVString<int nf, bit signed> {
780  string S =
781    !cond(!eq(nf, 2): !if(signed, "PvPv", "PUvPUv"),
782          !eq(nf, 3): !if(signed, "PvPvPv", "PUvPUvPUv"),
783          !eq(nf, 4): !if(signed, "PvPvPvPv", "PUvPUvPUvPUv"),
784          !eq(nf, 5): !if(signed, "PvPvPvPvPv", "PUvPUvPUvPUvPUv"),
785          !eq(nf, 6): !if(signed, "PvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUv"),
786          !eq(nf, 7): !if(signed, "PvPvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUvPUv"),
787          !eq(nf, 8): !if(signed, "PvPvPvPvPvPvPvPv", "PUvPUvPUvPUvPUvPUvPUvPUv"));
788}
789
790multiclass RVVUnitStridedSegLoad<string op> {
791  foreach type = TypeList in {
792    defvar eew = !cond(!eq(type, "c") : "8",
793                       !eq(type, "s") : "16",
794                       !eq(type, "i") : "32",
795                       !eq(type, "l") : "64",
796                       !eq(type, "x") : "16",
797                       !eq(type, "f") : "32",
798                       !eq(type, "d") : "64");
799      foreach nf = NFList in {
800        let Name = op # nf # "e" # eew # "_v",
801            IRName = op # nf,
802            IRNameMask = op # nf # "_mask",
803            NF = nf,
804            HasNoMaskedOverloaded = false,
805            ManualCodegen = [{
806    {
807      // builtin: (val0 address, val1 address, ..., ptr, vl)
808      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
809                        Ops[NF + 1]->getType()};
810      // intrinsic: (ptr, vl)
811      llvm::Value *Operands[] = {Ops[NF], Ops[NF + 1]};
812      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
813      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
814      clang::CharUnits Align = CharUnits::fromQuantity(
815                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
816      llvm::Value *V;
817      for (unsigned I = 0; I < NF; ++I) {
818        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
819                                Address(Ops[I], Align));
820      }
821      return V;
822    }
823            }],
824            ManualCodegenMask = [{
825    {
826      // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, vl)
827      // intrinsic: (maskedoff0, ..., ptr, mask, vl)
828      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
829                        Ops[2 * NF + 2]->getType()};
830      SmallVector<llvm::Value*, 12> Operands;
831      for (unsigned I = 0; I < NF; ++I)
832        Operands.push_back(Ops[NF + I + 1]);
833      Operands.push_back(Ops[2 * NF + 1]);
834      Operands.push_back(Ops[NF]);
835      Operands.push_back(Ops[2 * NF + 2]);
836      assert(Operands.size() == NF + 3);
837      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
838      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
839      clang::CharUnits Align = CharUnits::fromQuantity(
840                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
841      llvm::Value *V;
842      for (unsigned I = 0; I < NF; ++I) {
843        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
844                                Address(Ops[I], Align));
845      }
846      return V;
847    }
848            }] in {
849          defvar PV = PVString<nf, /*signed=*/true>.S;
850          defvar PUV = PVString<nf, /*signed=*/false>.S;
851          def : RVVBuiltin<"v", "0" # PV # "PCe", type>;
852          if !not(IsFloat<type>.val) then {
853            def : RVVBuiltin<"Uv", "0" # PUV # "PCUe", type>;
854        }
855      }
856    }
857  }
858}
859
860multiclass RVVUnitStridedSegLoadFF<string op> {
861  foreach type = TypeList in {
862    defvar eew = !cond(!eq(type, "c") : "8",
863                       !eq(type, "s") : "16",
864                       !eq(type, "i") : "32",
865                       !eq(type, "l") : "64",
866                       !eq(type, "x") : "16",
867                       !eq(type, "f") : "32",
868                       !eq(type, "d") : "64");
869      foreach nf = NFList in {
870        let Name = op # nf # "e" # eew # "ff_v",
871            IRName = op # nf # "ff",
872            IRNameMask = op # nf # "ff_mask",
873            NF = nf,
874            HasNoMaskedOverloaded = false,
875            ManualCodegen = [{
876    {
877      // builtin: (val0 address, val1 address, ..., ptr, new_vl, vl)
878      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
879                        Ops[NF + 2]->getType()};
880      // intrinsic: (ptr, vl)
881      llvm::Value *Operands[] = {Ops[NF], Ops[NF + 2]};
882      Value *NewVL = Ops[NF + 1];
883      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
884      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
885      clang::CharUnits Align = CharUnits::fromQuantity(
886                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
887      for (unsigned I = 0; I < NF; ++I) {
888        Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
889                            Address(Ops[I], Align));
890      }
891      // Store new_vl.
892      return Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {NF}),
893                                 Address(NewVL, Align));
894    }
895            }],
896            ManualCodegenMask = [{
897    {
898      // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, new_vl, vl)
899      // intrinsic: (maskedoff0, ..., ptr, mask, vl)
900      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
901                        Ops[2 * NF + 3]->getType()};
902      SmallVector<llvm::Value*, 12> Operands;
903      for (unsigned I = 0; I < NF; ++I)
904        Operands.push_back(Ops[NF + I + 1]);
905      Operands.push_back(Ops[2 * NF + 1]);
906      Operands.push_back(Ops[NF]);
907      Operands.push_back(Ops[2 * NF + 3]);
908      Value *NewVL = Ops[2 * NF + 2];
909      assert(Operands.size() == NF + 3);
910      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
911      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
912      clang::CharUnits Align = CharUnits::fromQuantity(
913                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
914      for (unsigned I = 0; I < NF; ++I) {
915        Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
916                            Address(Ops[I], Align));
917      }
918      // Store new_vl.
919      return Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {NF}),
920                                 Address(NewVL, Align));
921    }
922            }] in {
923          defvar PV = PVString<nf, /*signed=*/true>.S;
924          defvar PUV = PVString<nf, /*signed=*/false>.S;
925          def : RVVBuiltin<"v", "0" # PV # "PCe" # "Pz", type>;
926          if !not(IsFloat<type>.val) then {
927            def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # "Pz", type>;
928        }
929      }
930    }
931  }
932}
933
934multiclass RVVStridedSegLoad<string op> {
935  foreach type = TypeList in {
936    defvar eew = !cond(!eq(type, "c") : "8",
937                       !eq(type, "s") : "16",
938                       !eq(type, "i") : "32",
939                       !eq(type, "l") : "64",
940                       !eq(type, "x") : "16",
941                       !eq(type, "f") : "32",
942                       !eq(type, "d") : "64");
943      foreach nf = NFList in {
944        let Name = op # nf # "e" # eew # "_v",
945            IRName = op # nf,
946            IRNameMask = op # nf # "_mask",
947            NF = nf,
948            HasNoMaskedOverloaded = false,
949            ManualCodegen = [{
950    {
951      // builtin: (val0 address, val1 address, ..., ptr, stride, vl)
952      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
953                        Ops[NF + 2]->getType()};
954      // intrinsic: (ptr, stride, vl)
955      llvm::Value *Operands[] = {Ops[NF], Ops[NF + 1], Ops[NF + 2]};
956      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
957      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
958      clang::CharUnits Align = CharUnits::fromQuantity(
959                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
960      llvm::Value *V;
961      for (unsigned I = 0; I < NF; ++I) {
962        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
963                                Address(Ops[I], Align));
964      }
965      return V;
966    }
967            }],
968            ManualCodegenMask = [{
969    {
970      // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, stride, vl)
971      // intrinsic: (maskedoff0, ..., ptr, stride, mask, vl)
972      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
973                        Ops[2 * NF + 3]->getType()};
974      SmallVector<llvm::Value*, 12> Operands;
975      for (unsigned I = 0; I < NF; ++I)
976        Operands.push_back(Ops[NF + I + 1]);
977      Operands.push_back(Ops[2 * NF + 1]);
978      Operands.push_back(Ops[2 * NF + 2]);
979      Operands.push_back(Ops[NF]);
980      Operands.push_back(Ops[2 * NF + 3]);
981      assert(Operands.size() == NF + 4);
982      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
983      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
984      clang::CharUnits Align = CharUnits::fromQuantity(
985                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
986      llvm::Value *V;
987      for (unsigned I = 0; I < NF; ++I) {
988        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
989                                Address(Ops[I], Align));
990      }
991      return V;
992    }
993            }] in {
994          defvar PV = PVString<nf, /*signed=*/true>.S;
995          defvar PUV = PVString<nf, /*signed=*/false>.S;
996          def : RVVBuiltin<"v", "0" # PV # "PCe" # "t", type>;
997          if !not(IsFloat<type>.val) then {
998            def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # "t", type>;
999        }
1000      }
1001    }
1002  }
1003}
1004
1005multiclass RVVIndexedSegLoad<string op> {
1006  foreach type = TypeList in {
1007    foreach eew_info = EEWList in {
1008      defvar eew = eew_info[0];
1009      defvar eew_type = eew_info[1];
1010      foreach nf = NFList in {
1011        let Name = op # nf # "ei" # eew # "_v",
1012            IRName = op # nf,
1013            IRNameMask = op # nf # "_mask",
1014            NF = nf,
1015            ManualCodegen = [{
1016    {
1017      // builtin: (val0 address, val1 address, ..., ptr, index, vl)
1018      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
1019                        Ops[NF + 1]->getType(), Ops[NF + 2]->getType()};
1020      // intrinsic: (ptr, index, vl)
1021      llvm::Value *Operands[] = {Ops[NF], Ops[NF + 1], Ops[NF + 2]};
1022      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
1023      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
1024      clang::CharUnits Align = CharUnits::fromQuantity(
1025                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
1026      llvm::Value *V;
1027      for (unsigned I = 0; I < NF; ++I) {
1028        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
1029                                Address(Ops[I], Align));
1030      }
1031      return V;
1032    }
1033            }],
1034            ManualCodegenMask = [{
1035    {
1036      // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, index, vl)
1037      IntrinsicTypes = {Ops[0]->getType()->getPointerElementType(),
1038                        Ops[2 * NF + 2]->getType(), Ops[2 * NF + 3]->getType()};
1039      // intrinsic: (maskedoff0, ..., ptr, index, mask, vl)
1040      SmallVector<llvm::Value*, 12> Operands;
1041      for (unsigned I = 0; I < NF; ++I)
1042        Operands.push_back(Ops[NF + I + 1]);
1043      Operands.push_back(Ops[2 * NF + 1]);
1044      Operands.push_back(Ops[2 * NF + 2]);
1045      Operands.push_back(Ops[NF]);
1046      Operands.push_back(Ops[2 * NF + 3]);
1047      assert(Operands.size() == NF + 4);
1048      llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
1049      llvm::Value *LoadValue = Builder.CreateCall(F, Operands, "");
1050      clang::CharUnits Align = CharUnits::fromQuantity(
1051                                 IntrinsicTypes[0]->getScalarSizeInBits() / 8);
1052      llvm::Value *V;
1053      for (unsigned I = 0; I < NF; ++I) {
1054        V = Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {I}),
1055                                Address(Ops[I], Align));
1056      }
1057      return V;
1058    }
1059            }] in {
1060          defvar PV = PVString<nf, /*signed=*/true>.S;
1061          defvar PUV = PVString<nf, /*signed=*/false>.S;
1062          def : RVVBuiltin<"v", "0" # PV # "PCe" # eew_type # "Uv", type>;
1063          if !not(IsFloat<type>.val) then {
1064            def : RVVBuiltin<"Uv", "0" # PUV # "PCUe" # eew_type # "Uv", type>;
1065          }
1066        }
1067      }
1068    }
1069  }
1070}
1071
1072class VString<int nf, bit signed> {
1073  string S = !cond(!eq(nf, 2): !if(signed, "vv", "UvUv"),
1074                   !eq(nf, 3): !if(signed, "vvv", "UvUvUv"),
1075                   !eq(nf, 4): !if(signed, "vvvv", "UvUvUvUv"),
1076                   !eq(nf, 5): !if(signed, "vvvvv", "UvUvUvUvUv"),
1077                   !eq(nf, 6): !if(signed, "vvvvvv", "UvUvUvUvUvUv"),
1078                   !eq(nf, 7): !if(signed, "vvvvvvv", "UvUvUvUvUvUvUv"),
1079                   !eq(nf, 8): !if(signed, "vvvvvvvv", "UvUvUvUvUvUvUvUv"));
1080}
1081
1082multiclass RVVUnitStridedSegStore<string op> {
1083  foreach type = TypeList in {
1084    defvar eew = !cond(!eq(type, "c") : "8",
1085                       !eq(type, "s") : "16",
1086                       !eq(type, "i") : "32",
1087                       !eq(type, "l") : "64",
1088                       !eq(type, "x") : "16",
1089                       !eq(type, "f") : "32",
1090                       !eq(type, "d") : "64");
1091      foreach nf = NFList in {
1092        let Name = op # nf # "e" # eew # "_v",
1093            IRName = op # nf,
1094            IRNameMask = op # nf # "_mask",
1095            NF = nf,
1096            HasMaskedOffOperand = false,
1097            ManualCodegen = [{
1098    {
1099      // Builtin: (ptr, val0, val1, ..., vl)
1100      // Intrinsic: (val0, val1, ..., ptr, vl)
1101      std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
1102      IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()};
1103      assert(Ops.size() == NF + 2);
1104    }
1105            }],
1106            ManualCodegenMask = [{
1107    {
1108      // Builtin: (mask, ptr, val0, val1, ..., vl)
1109      // Intrinsic: (val0, val1, ..., ptr, mask, vl)
1110      std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1);
1111      std::swap(Ops[NF], Ops[NF + 1]);
1112      IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 2]->getType()};
1113      assert(Ops.size() == NF + 3);
1114    }
1115            }] in {
1116          defvar V = VString<nf, /*signed=*/true>.S;
1117          defvar UV = VString<nf, /*signed=*/false>.S;
1118          def : RVVBuiltin<"v", "0Pe" # V, type>;
1119          if !not(IsFloat<type>.val) then {
1120            def : RVVBuiltin<"Uv", "0PUe" # UV, type>;
1121        }
1122      }
1123    }
1124  }
1125}
1126
1127multiclass RVVStridedSegStore<string op> {
1128  foreach type = TypeList in {
1129    defvar eew = !cond(!eq(type, "c") : "8",
1130                       !eq(type, "s") : "16",
1131                       !eq(type, "i") : "32",
1132                       !eq(type, "l") : "64",
1133                       !eq(type, "x") : "16",
1134                       !eq(type, "f") : "32",
1135                       !eq(type, "d") : "64");
1136      foreach nf = NFList in {
1137        let Name = op # nf # "e" # eew # "_v",
1138            IRName = op # nf,
1139            IRNameMask = op # nf # "_mask",
1140            NF = nf,
1141            HasMaskedOffOperand = false,
1142            ManualCodegen = [{
1143    {
1144      // Builtin: (ptr, stride, val0, val1, ..., vl).
1145      // Intrinsic: (val0, val1, ..., ptr, stride, vl)
1146      std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1);
1147      IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()};
1148      assert(Ops.size() == NF + 3);
1149    }
1150            }],
1151            ManualCodegenMask = [{
1152    {
1153      // Builtin: (mask, ptr, stride, val0, val1, ..., vl).
1154      // Intrinsic: (val0, val1, ..., ptr, stride, mask, vl)
1155      std::rotate(Ops.begin(), Ops.begin() + 3, Ops.end() - 1);
1156      std::rotate(Ops.begin() + NF, Ops.begin() + NF + 1, Ops.begin() + NF + 3);
1157      IntrinsicTypes = {Ops[0]->getType(), Ops[NF + 1]->getType()};
1158      assert(Ops.size() == NF + 4);
1159    }
1160            }] in {
1161          defvar V = VString<nf, /*signed=*/true>.S;
1162          defvar UV = VString<nf, /*signed=*/false>.S;
1163          def : RVVBuiltin<"v", "0Pet" # V, type>;
1164          if !not(IsFloat<type>.val) then {
1165            def : RVVBuiltin<"Uv", "0PUet" # UV, type>;
1166        }
1167      }
1168    }
1169  }
1170}
1171
1172multiclass RVVIndexedSegStore<string op> {
1173  foreach type = TypeList in {
1174    foreach eew_info = EEWList in {
1175      defvar eew = eew_info[0];
1176      defvar eew_type = eew_info[1];
1177      foreach nf = NFList in {
1178        let Name = op # nf # "ei" # eew # "_v",
1179            IRName = op # nf,
1180            IRNameMask = op # nf # "_mask",
1181            NF = nf,
1182            HasMaskedOffOperand = false,
1183            ManualCodegen = [{
1184    {
1185      // Builtin: (ptr, index, val0, val1, ..., vl)
1186      // Intrinsic: (val0, val1, ..., ptr, index, vl)
1187      std::rotate(Ops.begin(), Ops.begin() + 2, Ops.end() - 1);
1188      IntrinsicTypes = {Ops[0]->getType(),
1189                        Ops[NF + 1]->getType(), Ops[NF + 2]->getType()};
1190      assert(Ops.size() == NF + 3);
1191    }
1192            }],
1193            ManualCodegenMask = [{
1194    {
1195      // Builtin: (mask, ptr, index, val0, val1, ..., vl)
1196      // Intrinsic: (val0, val1, ..., ptr, index, mask, vl)
1197      std::rotate(Ops.begin(), Ops.begin() + 3, Ops.end() - 1);
1198      std::rotate(Ops.begin() + NF, Ops.begin() + NF + 1, Ops.begin() + NF + 3);
1199      IntrinsicTypes = {Ops[0]->getType(),
1200                        Ops[NF + 1]->getType(), Ops[NF + 3]->getType()};
1201      assert(Ops.size() == NF + 4);
1202    }
1203            }] in {
1204          defvar V = VString<nf, /*signed=*/true>.S;
1205          defvar UV = VString<nf, /*signed=*/false>.S;
1206          def : RVVBuiltin<"v", "0Pe" # eew_type # "Uv" # V, type>;
1207          if !not(IsFloat<type>.val) then {
1208            def : RVVBuiltin<"Uv", "0PUe" # eew_type # "Uv" # UV, type>;
1209          }
1210        }
1211      }
1212    }
1213  }
1214}
1215
1216multiclass RVVAMOBuiltinSet<bit has_signed = false, bit has_unsigned = false,
1217                            bit has_fp = false> {
1218  defvar type_list = !if(has_fp, ["i","l","f","d"], ["i","l"]);
1219  foreach type = type_list in
1220    foreach eew_list = EEWList in {
1221      defvar eew = eew_list[0];
1222      defvar eew_index = eew_list[1];
1223      let Name = NAME # "ei" # eew # "_" # "v",
1224          IRName = NAME,
1225          IRNameMask = NAME # "_mask",
1226          HasMaskedOffOperand = false,
1227          ManualCodegen = [{
1228            // base, bindex, value, vl
1229            IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
1230            Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
1231          }],
1232          ManualCodegenMask = [{
1233            std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
1234            IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[4]->getType()};
1235            Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
1236          }] in {
1237        if has_signed then
1238          def : RVVBuiltin<"v", "vPe" # eew_index # "Uvv", type>;
1239        if !and(!not(IsFloat<type>.val), has_unsigned) then
1240          def : RVVBuiltin<"Uv", "UvPUe" # eew_index # "UvUv", type>;
1241      }
1242    }
1243}
1244
1245multiclass RVVPseudoUnaryBuiltin<string IR, string type_range> {
1246  let Name = NAME,
1247      IRName = IR,
1248      IRNameMask = IR # "_mask",
1249      ManualCodegen = [{
1250      {
1251        // op1, vl
1252        IntrinsicTypes = {ResultType,
1253                          cast<llvm::VectorType>(ResultType)->getElementType(),
1254                          Ops[1]->getType()};
1255        Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[1]));
1256        break;
1257      }
1258      }],
1259      ManualCodegenMask = [{
1260      {
1261        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
1262        // maskedoff, op1, mask, vl
1263        IntrinsicTypes = {ResultType,
1264                          cast<llvm::VectorType>(ResultType)->getElementType(),
1265                          Ops[3]->getType()};
1266        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[1]));
1267        break;
1268      }
1269      }] in {
1270        def : RVVBuiltin<"v", "vv", type_range>;
1271  }
1272}
1273
1274multiclass RVVPseudoVNotBuiltin<string IR, string type_range> {
1275  let Name = NAME,
1276      IRName = IR,
1277      IRNameMask = IR # "_mask",
1278      ManualCodegen = [{
1279      {
1280        // op1, vl
1281        IntrinsicTypes = {ResultType,
1282                          cast<llvm::VectorType>(ResultType)->getElementType(),
1283                          Ops[1]->getType()};
1284        Ops.insert(Ops.begin() + 1,
1285                   llvm::Constant::getAllOnesValue(IntrinsicTypes[1]));
1286        break;
1287      }
1288      }],
1289      ManualCodegenMask = [{
1290      {
1291        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
1292        // maskedoff, op1, mask, vl
1293        IntrinsicTypes = {ResultType,
1294                          cast<llvm::VectorType>(ResultType)->getElementType(),
1295                          Ops[3]->getType()};
1296        Ops.insert(Ops.begin() + 2,
1297                   llvm::Constant::getAllOnesValue(IntrinsicTypes[1]));
1298        break;
1299      }
1300      }] in {
1301        def : RVVBuiltin<"v", "vv", type_range>;
1302        def : RVVBuiltin<"Uv", "UvUv", type_range>;
1303  }
1304}
1305
1306multiclass RVVPseudoMaskBuiltin<string IR, string type_range> {
1307  let Name = NAME,
1308      IRName = IR,
1309      HasMask = false,
1310      ManualCodegen = [{
1311      {
1312        // op1, vl
1313        IntrinsicTypes = {ResultType,
1314                          Ops[1]->getType()};
1315        Ops.insert(Ops.begin() + 1, Ops[0]);
1316        break;
1317      }
1318      }] in {
1319        def : RVVBuiltin<"m", "mm", type_range>;
1320  }
1321}
1322
1323multiclass RVVPseudoVFUnaryBuiltin<string IR, string type_range> {
1324  let Name = NAME,
1325      IRName = IR,
1326      IRNameMask = IR # "_mask",
1327      ManualCodegen = [{
1328      {
1329        // op1, vl
1330        IntrinsicTypes = {ResultType,
1331                          Ops[0]->getType(), Ops[1]->getType()};
1332        Ops.insert(Ops.begin() + 1, Ops[0]);
1333        break;
1334      }
1335      }],
1336      ManualCodegenMask = [{
1337      {
1338        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
1339        // maskedoff, op1, mask, vl
1340        IntrinsicTypes = {ResultType,
1341                          Ops[1]->getType(),
1342                          Ops[3]->getType()};
1343        Ops.insert(Ops.begin() + 2, Ops[1]);
1344        break;
1345      }
1346      }] in {
1347        def : RVVBuiltin<"v", "vv", type_range>;
1348  }
1349}
1350
1351multiclass RVVPseudoVWCVTBuiltin<string IR, string MName, string type_range,
1352                                 list<list<string>> suffixes_prototypes> {
1353  let Name = NAME,
1354      MangledName = MName,
1355      IRName = IR,
1356      IRNameMask = IR # "_mask",
1357      ManualCodegen = [{
1358      {
1359        // op1, vl
1360        IntrinsicTypes = {ResultType,
1361                          Ops[0]->getType(),
1362                          cast<llvm::VectorType>(Ops[0]->getType())->getElementType(),
1363                          Ops[1]->getType()};
1364        Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[2]));
1365        break;
1366      }
1367      }],
1368      ManualCodegenMask = [{
1369      {
1370        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
1371        // maskedoff, op1, mask, vl
1372        IntrinsicTypes = {ResultType,
1373                          Ops[1]->getType(),
1374                          cast<llvm::VectorType>(Ops[1]->getType())->getElementType(),
1375                          Ops[3]->getType()};
1376        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[2]));
1377        break;
1378      }
1379      }] in {
1380        foreach s_p = suffixes_prototypes in {
1381          def : RVVBuiltin<s_p[0], s_p[1], type_range>;
1382        }
1383  }
1384}
1385
1386multiclass RVVPseudoVNCVTBuiltin<string IR, string MName, string type_range,
1387                                 list<list<string>> suffixes_prototypes> {
1388  let Name = NAME,
1389      MangledName = MName,
1390      IRName = IR,
1391      IRNameMask = IR # "_mask",
1392      ManualCodegen = [{
1393      {
1394        // op1, vl
1395        IntrinsicTypes = {ResultType,
1396                          Ops[0]->getType(),
1397                          Ops[1]->getType(),
1398                          Ops[1]->getType()};
1399        Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[2]));
1400        break;
1401      }
1402      }],
1403      ManualCodegenMask = [{
1404      {
1405        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
1406        // maskedoff, op1, mask, vl
1407        IntrinsicTypes = {ResultType,
1408                          Ops[1]->getType(),
1409                          Ops[3]->getType(),
1410                          Ops[3]->getType()};
1411        Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[2]));
1412        break;
1413      }
1414      }] in {
1415        foreach s_p = suffixes_prototypes in {
1416          def : RVVBuiltin<s_p[0], s_p[1], type_range>;
1417        }
1418  }
1419}
1420
1421// 6. Configuration-Setting Instructions
1422// 6.1. vsetvli/vsetvl instructions
1423let HasVL = false,
1424    HasMask = false,
1425    HasSideEffects = true,
1426    Log2LMUL = [0],
1427    ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type
1428{
1429  // vsetvl is a macro because for it require constant integers in SEW and LMUL.
1430  let HeaderCode =
1431[{
1432#define vsetvl_e8mf8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 5)
1433#define vsetvl_e8mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 6)
1434#define vsetvl_e8mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 7)
1435#define vsetvl_e8m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 0)
1436#define vsetvl_e8m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 1)
1437#define vsetvl_e8m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 2)
1438#define vsetvl_e8m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 3)
1439
1440#define vsetvl_e16mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 6)
1441#define vsetvl_e16mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 7)
1442#define vsetvl_e16m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 0)
1443#define vsetvl_e16m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 1)
1444#define vsetvl_e16m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 2)
1445#define vsetvl_e16m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 3)
1446
1447#define vsetvl_e32mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 7)
1448#define vsetvl_e32m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 0)
1449#define vsetvl_e32m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 1)
1450#define vsetvl_e32m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 2)
1451#define vsetvl_e32m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 3)
1452
1453#define vsetvl_e64m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 0)
1454#define vsetvl_e64m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 1)
1455#define vsetvl_e64m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 2)
1456#define vsetvl_e64m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 3)
1457
1458}] in
1459  def vsetvli : RVVBuiltin<"", "zzKzKz", "i">;
1460
1461  let HeaderCode =
1462[{
1463#define vsetvlmax_e8mf8() __builtin_rvv_vsetvlimax(0, 5)
1464#define vsetvlmax_e8mf4() __builtin_rvv_vsetvlimax(0, 6)
1465#define vsetvlmax_e8mf2() __builtin_rvv_vsetvlimax(0, 7)
1466#define vsetvlmax_e8m1() __builtin_rvv_vsetvlimax(0, 0)
1467#define vsetvlmax_e8m2() __builtin_rvv_vsetvlimax(0, 1)
1468#define vsetvlmax_e8m4() __builtin_rvv_vsetvlimax(0, 2)
1469#define vsetvlmax_e8m8() __builtin_rvv_vsetvlimax(0, 3)
1470
1471#define vsetvlmax_e16mf4() __builtin_rvv_vsetvlimax(1, 6)
1472#define vsetvlmax_e16mf2() __builtin_rvv_vsetvlimax(1, 7)
1473#define vsetvlmax_e16m1() __builtin_rvv_vsetvlimax(1, 0)
1474#define vsetvlmax_e16m2() __builtin_rvv_vsetvlimax(1, 1)
1475#define vsetvlmax_e16m4() __builtin_rvv_vsetvlimax(1, 2)
1476#define vsetvlmax_e16m8() __builtin_rvv_vsetvlimax(1, 3)
1477
1478#define vsetvlmax_e32mf2() __builtin_rvv_vsetvlimax(2, 7)
1479#define vsetvlmax_e32m1() __builtin_rvv_vsetvlimax(2, 0)
1480#define vsetvlmax_e32m2() __builtin_rvv_vsetvlimax(2, 1)
1481#define vsetvlmax_e32m4() __builtin_rvv_vsetvlimax(2, 2)
1482#define vsetvlmax_e32m8() __builtin_rvv_vsetvlimax(2, 3)
1483
1484#define vsetvlmax_e64m1() __builtin_rvv_vsetvlimax(3, 0)
1485#define vsetvlmax_e64m2() __builtin_rvv_vsetvlimax(3, 1)
1486#define vsetvlmax_e64m4() __builtin_rvv_vsetvlimax(3, 2)
1487#define vsetvlmax_e64m8() __builtin_rvv_vsetvlimax(3, 3)
1488
1489}] in
1490  def vsetvlimax : RVVBuiltin<"", "zKzKz", "i">;
1491}
1492
1493// 7. Vector Loads and Stores
1494// 7.4. Vector Unit-Stride Instructions
1495def vle1: RVVVLEMaskBuiltin;
1496defm vle8: RVVVLEBuiltin<["c"]>;
1497defm vle16: RVVVLEBuiltin<["s","x"]>;
1498defm vle32: RVVVLEBuiltin<["i","f"]>;
1499defm vle64: RVVVLEBuiltin<["l","d"]>;
1500
1501def vse1 : RVVVSEMaskBuiltin;
1502defm vse8 : RVVVSEBuiltin<["c"]>;
1503defm vse16: RVVVSEBuiltin<["s","x"]>;
1504defm vse32: RVVVSEBuiltin<["i","f"]>;
1505defm vse64: RVVVSEBuiltin<["l","d"]>;
1506
1507// 7.5. Vector Strided Instructions
1508defm vlse8: RVVVLSEBuiltin<["c"]>;
1509defm vlse16: RVVVLSEBuiltin<["s","x"]>;
1510defm vlse32: RVVVLSEBuiltin<["i","f"]>;
1511defm vlse64: RVVVLSEBuiltin<["l","d"]>;
1512
1513defm vsse8 : RVVVSSEBuiltin<["c"]>;
1514defm vsse16: RVVVSSEBuiltin<["s","x"]>;
1515defm vsse32: RVVVSSEBuiltin<["i","f"]>;
1516defm vsse64: RVVVSSEBuiltin<["l","d"]>;
1517
1518// 7.6. Vector Indexed Instructions
1519defm : RVVIndexedLoad<"vluxei">;
1520defm : RVVIndexedLoad<"vloxei">;
1521
1522defm : RVVIndexedStore<"vsuxei">;
1523defm : RVVIndexedStore<"vsoxei">;
1524
1525// 7.7. Unit-stride Fault-Only-First Loads
1526defm vle8ff: RVVVLEFFBuiltin<["c"]>;
1527defm vle16ff: RVVVLEFFBuiltin<["s","x"]>;
1528defm vle32ff: RVVVLEFFBuiltin<["i", "f"]>;
1529defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>;
1530
1531// 7.8 Vector Load/Store Segment Instructions
1532let RequiredExtension = "Zvlsseg" in {
1533defm : RVVUnitStridedSegLoad<"vlseg">;
1534defm : RVVUnitStridedSegLoadFF<"vlseg">;
1535defm : RVVStridedSegLoad<"vlsseg">;
1536defm : RVVIndexedSegLoad<"vluxseg">;
1537defm : RVVIndexedSegLoad<"vloxseg">;
1538defm : RVVUnitStridedSegStore<"vsseg">;
1539defm : RVVStridedSegStore<"vssseg">;
1540defm : RVVIndexedSegStore<"vsuxseg">;
1541defm : RVVIndexedSegStore<"vsoxseg">;
1542}
1543
1544// 8. Vector AMO Operations
1545let RequiredExtension = "Zvamo" in {
1546defm vamoswap : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true, /* hasFP */ true>;
1547defm vamoadd : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1548defm vamoxor : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1549defm vamoand : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1550defm vamoor : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1551defm vamomin : RVVAMOBuiltinSet< /* hasSigned */ true>;
1552defm vamomax : RVVAMOBuiltinSet< /* hasSigned */ true>;
1553defm vamominu : RVVAMOBuiltinSet< /* hasSigned */ false, /* hasUnsigned */ true>;
1554defm vamomaxu : RVVAMOBuiltinSet< /* hasSigned */ false, /* hasUnsigned */ true>;
1555}
1556
1557// 12. Vector Integer Arithmetic Instructions
1558// 12.1. Vector Single-Width Integer Add and Subtract
1559defm vadd : RVVIntBinBuiltinSet;
1560defm vsub : RVVIntBinBuiltinSet;
1561defm vrsub : RVVOutOp1BuiltinSet<"vrsub", "csil",
1562                                 [["vx", "v", "vve"],
1563                                  ["vx", "Uv", "UvUvUe"]]>;
1564defm vneg_v : RVVPseudoUnaryBuiltin<"vrsub", "csil">;
1565
1566// 12.2. Vector Widening Integer Add/Subtract
1567// Widening unsigned integer add/subtract, 2*SEW = SEW +/- SEW
1568defm vwaddu : RVVUnsignedWidenBinBuiltinSet;
1569defm vwsubu : RVVUnsignedWidenBinBuiltinSet;
1570// Widening signed integer add/subtract, 2*SEW = SEW +/- SEW
1571defm vwadd : RVVSignedWidenBinBuiltinSet;
1572defm vwsub : RVVSignedWidenBinBuiltinSet;
1573// Widening unsigned integer add/subtract, 2*SEW = 2*SEW +/- SEW
1574defm vwaddu : RVVUnsignedWidenOp0BinBuiltinSet;
1575defm vwsubu : RVVUnsignedWidenOp0BinBuiltinSet;
1576// Widening signed integer add/subtract, 2*SEW = 2*SEW +/- SEW
1577defm vwadd : RVVSignedWidenOp0BinBuiltinSet;
1578defm vwsub : RVVSignedWidenOp0BinBuiltinSet;
1579defm vwcvtu_x_x_v : RVVPseudoVWCVTBuiltin<"vwaddu", "vwcvtu_x", "csi",
1580                                          [["Uw", "UwUv"]]>;
1581defm vwcvt_x_x_v : RVVPseudoVWCVTBuiltin<"vwadd", "vwcvt_x", "csi",
1582                                         [["w", "wv"]]>;
1583
1584// 12.3. Vector Integer Extension
1585let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1586  def vsext_vf2 : RVVIntExt<"vsext", "w", "wv", "csi">;
1587  def vzext_vf2 : RVVIntExt<"vzext", "Uw", "UwUv", "csi">;
1588}
1589let Log2LMUL = [-3, -2, -1, 0, 1] in {
1590  def vsext_vf4 : RVVIntExt<"vsext", "q", "qv", "cs">;
1591  def vzext_vf4 : RVVIntExt<"vzext", "Uq", "UqUv", "cs">;
1592}
1593let Log2LMUL = [-3, -2, -1, 0] in {
1594  def vsext_vf8 : RVVIntExt<"vsext", "o", "ov", "c">;
1595  def vzext_vf8 : RVVIntExt<"vzext", "Uo", "UoUv", "c">;
1596}
1597
1598// 12.4. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
1599let HasMask = false in {
1600  defm vadc : RVVCarryinBuiltinSet;
1601  defm vmadc : RVVCarryOutInBuiltinSet<"vmadc_carry_in">;
1602  defm vmadc : RVVIntMaskOutBuiltinSet;
1603  defm vsbc : RVVCarryinBuiltinSet;
1604  defm vmsbc : RVVCarryOutInBuiltinSet<"vmsbc_borrow_in">;
1605  defm vmsbc : RVVIntMaskOutBuiltinSet;
1606}
1607
1608// 12.5. Vector Bitwise Logical Instructions
1609defm vand : RVVIntBinBuiltinSet;
1610defm vxor : RVVIntBinBuiltinSet;
1611defm vor : RVVIntBinBuiltinSet;
1612defm vnot_v : RVVPseudoVNotBuiltin<"vxor", "csil">;
1613
1614// 12.6. Vector Single-Width Bit Shift Instructions
1615defm vsll : RVVShiftBuiltinSet;
1616defm vsrl : RVVUnsignedShiftBuiltinSet;
1617defm vsra : RVVSignedShiftBuiltinSet;
1618
1619// 12.7. Vector Narrowing Integer Right Shift Instructions
1620defm vnsrl : RVVUnsignedNShiftBuiltinSet;
1621defm vnsra : RVVSignedNShiftBuiltinSet;
1622defm vncvt_x_x_w : RVVPseudoVNCVTBuiltin<"vnsrl", "vncvt_x", "csi",
1623                                         [["v", "vw"],
1624                                          ["Uv", "UvUw"]]>;
1625
1626// 12.8. Vector Integer Comparison Instructions
1627defm vmseq : RVVIntMaskOutBuiltinSet;
1628defm vmsne : RVVIntMaskOutBuiltinSet;
1629defm vmsltu : RVVUnsignedMaskOutBuiltinSet;
1630defm vmslt : RVVSignedMaskOutBuiltinSet;
1631defm vmsleu : RVVUnsignedMaskOutBuiltinSet;
1632defm vmsle : RVVSignedMaskOutBuiltinSet;
1633defm vmsgtu : RVVUnsignedMaskOutBuiltinSet;
1634defm vmsgt : RVVSignedMaskOutBuiltinSet;
1635defm vmsgeu : RVVUnsignedMaskOutBuiltinSet;
1636defm vmsge : RVVSignedMaskOutBuiltinSet;
1637
1638// 12.9. Vector Integer Min/Max Instructions
1639defm vminu : RVVUnsignedBinBuiltinSet;
1640defm vmin : RVVSignedBinBuiltinSet;
1641defm vmaxu : RVVUnsignedBinBuiltinSet;
1642defm vmax : RVVSignedBinBuiltinSet;
1643
1644// 12.10. Vector Single-Width Integer Multiply Instructions
1645defm vmul : RVVIntBinBuiltinSet;
1646defm vmulh : RVVSignedBinBuiltinSet;
1647defm vmulhu : RVVUnsignedBinBuiltinSet;
1648defm vmulhsu : RVVOutOp1BuiltinSet<"vmulhsu", "csil",
1649                                   [["vv", "v", "vvUv"],
1650                                    ["vx", "v", "vvUe"]]>;
1651
1652// 12.11. Vector Integer Divide Instructions
1653defm vdivu : RVVUnsignedBinBuiltinSet;
1654defm vdiv : RVVSignedBinBuiltinSet;
1655defm vremu : RVVUnsignedBinBuiltinSet;
1656defm vrem : RVVSignedBinBuiltinSet;
1657
1658// 12.12. Vector Widening Integer Multiply Instructions
1659let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1660defm vwmul : RVVOutOp0Op1BuiltinSet<"vwmul", "csi",
1661                                    [["vv", "w", "wvv"],
1662                                     ["vx", "w", "wve"]]>;
1663defm vwmulu : RVVOutOp0Op1BuiltinSet<"vwmulu", "csi",
1664                                     [["vv", "Uw", "UwUvUv"],
1665                                      ["vx", "Uw", "UwUvUe"]]>;
1666defm vwmulsu : RVVOutOp0Op1BuiltinSet<"vwmulsu", "csi",
1667                                      [["vv", "w", "wvUv"],
1668                                       ["vx", "w", "wvUe"]]>;
1669}
1670
1671// 12.13. Vector Single-Width Integer Multiply-Add Instructions
1672defm vmacc  : RVVIntTerBuiltinSet;
1673defm vnmsac : RVVIntTerBuiltinSet;
1674defm vmadd  : RVVIntTerBuiltinSet;
1675defm vnmsub : RVVIntTerBuiltinSet;
1676
1677// 12.14. Vector Widening Integer Multiply-Add Instructions
1678let HasMaskedOffOperand = false,
1679    Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1680defm vwmaccu : RVVOutOp1Op2BuiltinSet<"vwmaccu", "csi",
1681                                      [["vv", "Uw", "UwUwUvUv"],
1682                                       ["vx", "Uw", "UwUwUeUv"]]>;
1683defm vwmacc : RVVOutOp1Op2BuiltinSet<"vwmacc", "csi",
1684                                     [["vv", "w", "wwvv"],
1685                                      ["vx", "w", "wwev"]]>;
1686defm vwmaccsu : RVVOutOp1Op2BuiltinSet<"vwmaccsu", "csi",
1687                                       [["vv", "w", "wwvUv"],
1688                                        ["vx", "w", "wweUv"]]>;
1689defm vwmaccus : RVVOutOp1Op2BuiltinSet<"vwmaccus", "csi",
1690                                       [["vx", "w", "wwUev"]]>;
1691}
1692
1693// 12.15. Vector Integer Merge Instructions
1694// C/C++ Operand: (mask, op1, op2, vl), Intrinsic: (op1, op2, mask, vl)
1695let HasMask = false,
1696    ManualCodegen = [{
1697      std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
1698      IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
1699    }] in {
1700  defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "csil",
1701                                    [["vvm", "v", "vmvv"],
1702                                     ["vxm", "v", "vmve"],
1703                                     ["vvm", "Uv", "UvmUvUv"],
1704                                     ["vxm", "Uv", "UvmUvUe"]]>;
1705}
1706
1707// 12.16. Vector Integer Move Instructions
1708let HasMask = false in {
1709  let MangledName = "vmv_v" in {
1710    defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csil",
1711                                   [["v", "Uv", "UvUv"]]>;
1712    defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csilxfd",
1713                                   [["v", "v", "vv"]]>;
1714  }
1715  let HasNoMaskedOverloaded = false in
1716    defm vmv_v : RVVOutBuiltinSet<"vmv_v_x", "csil",
1717                                   [["x", "v", "ve"],
1718                                    ["x", "Uv", "UvUe"]]>;
1719}
1720
1721// 13. Vector Fixed-Point Arithmetic Instructions
1722// 13.1. Vector Single-Width Saturating Add and Subtract
1723defm vsaddu : RVVUnsignedBinBuiltinSet;
1724defm vsadd : RVVSignedBinBuiltinSet;
1725defm vssubu : RVVUnsignedBinBuiltinSet;
1726defm vssub : RVVSignedBinBuiltinSet;
1727
1728// 13.2. Vector Single-Width Averaging Add and Subtract
1729defm vaaddu : RVVUnsignedBinBuiltinSet;
1730defm vaadd : RVVSignedBinBuiltinSet;
1731defm vasubu : RVVUnsignedBinBuiltinSet;
1732defm vasub : RVVSignedBinBuiltinSet;
1733
1734// 13.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
1735defm vsmul : RVVSignedBinBuiltinSet;
1736
1737// 13.4. Vector Single-Width Scaling Shift Instructions
1738defm vssrl : RVVUnsignedShiftBuiltinSet;
1739defm vssra : RVVSignedShiftBuiltinSet;
1740
1741// 13.5. Vector Narrowing Fixed-Point Clip Instructions
1742defm vnclipu : RVVUnsignedNShiftBuiltinSet;
1743defm vnclip : RVVSignedNShiftBuiltinSet;
1744
1745// 14. Vector Floating-Point Instructions
1746// 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions
1747defm vfadd  : RVVFloatingBinBuiltinSet;
1748defm vfsub  : RVVFloatingBinBuiltinSet;
1749defm vfrsub : RVVFloatingBinVFBuiltinSet;
1750
1751// 14.3. Vector Widening Floating-Point Add/Subtract Instructions
1752// Widening FP add/subtract, 2*SEW = SEW +/- SEW
1753defm vfwadd : RVVFloatingWidenBinBuiltinSet;
1754defm vfwsub : RVVFloatingWidenBinBuiltinSet;
1755// Widening FP add/subtract, 2*SEW = 2*SEW +/- SEW
1756defm vfwadd : RVVFloatingWidenOp0BinBuiltinSet;
1757defm vfwsub : RVVFloatingWidenOp0BinBuiltinSet;
1758
1759// 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions
1760defm vfmul  : RVVFloatingBinBuiltinSet;
1761defm vfdiv  : RVVFloatingBinBuiltinSet;
1762defm vfrdiv : RVVFloatingBinVFBuiltinSet;
1763
1764// 14.5. Vector Widening Floating-Point Multiply
1765let Log2LMUL = [-2, -1, 0, 1, 2] in {
1766  defm vfwmul : RVVOutOp0Op1BuiltinSet<"vfwmul", "xf",
1767                                       [["vv", "w", "wvv"],
1768                                        ["vf", "w", "wve"]]>;
1769}
1770
1771// 14.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions
1772defm vfmacc  : RVVFloatingTerBuiltinSet;
1773defm vfnmacc : RVVFloatingTerBuiltinSet;
1774defm vfmsac  : RVVFloatingTerBuiltinSet;
1775defm vfnmsac : RVVFloatingTerBuiltinSet;
1776defm vfmadd  : RVVFloatingTerBuiltinSet;
1777defm vfnmadd : RVVFloatingTerBuiltinSet;
1778defm vfmsub  : RVVFloatingTerBuiltinSet;
1779defm vfnmsub : RVVFloatingTerBuiltinSet;
1780
1781// 14.7. Vector Widening Floating-Point Fused Multiply-Add Instructions
1782defm vfwmacc  : RVVFloatingWidenTerBuiltinSet;
1783defm vfwnmacc : RVVFloatingWidenTerBuiltinSet;
1784defm vfwmsac  : RVVFloatingWidenTerBuiltinSet;
1785defm vfwnmsac : RVVFloatingWidenTerBuiltinSet;
1786
1787// 14.8. Vector Floating-Point Square-Root Instruction
1788def vfsqrt : RVVFloatingUnaryVVBuiltin;
1789
1790// 14.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction
1791def vfrsqrt7 : RVVFloatingUnaryVVBuiltin;
1792
1793// 14.10. Vector Floating-Point Reciprocal Estimate Instruction
1794def vfrec7 : RVVFloatingUnaryVVBuiltin;
1795
1796// 14.11. Vector Floating-Point MIN/MAX Instructions
1797defm vfmin : RVVFloatingBinBuiltinSet;
1798defm vfmax : RVVFloatingBinBuiltinSet;
1799
1800// 14.12. Vector Floating-Point Sign-Injection Instructions
1801defm vfsgnj  : RVVFloatingBinBuiltinSet;
1802defm vfsgnjn : RVVFloatingBinBuiltinSet;
1803defm vfsgnjx : RVVFloatingBinBuiltinSet;
1804defm vfneg_v : RVVPseudoVFUnaryBuiltin<"vfsgnjn", "xfd">;
1805defm vfabs_v : RVVPseudoVFUnaryBuiltin<"vfsgnjx", "xfd">;
1806
1807// 14.13. Vector Floating-Point Compare Instructions
1808defm vmfeq : RVVFloatingMaskOutBuiltinSet;
1809defm vmfne : RVVFloatingMaskOutBuiltinSet;
1810defm vmflt : RVVFloatingMaskOutBuiltinSet;
1811defm vmfle : RVVFloatingMaskOutBuiltinSet;
1812defm vmfgt : RVVFloatingMaskOutBuiltinSet;
1813defm vmfge : RVVFloatingMaskOutBuiltinSet;
1814
1815// 14.14. Vector Floating-Point Classify Instruction
1816let Name = "vfclass_v" in
1817  def vfclass : RVVOp0Builtin<"Uv", "Uvv", "xfd">;
1818
1819// 14.15. Vector Floating-Point Merge Instructio
1820// C/C++ Operand: (mask, op1, op2, vl), Builtin: (op1, op2, mask, vl)
1821let HasMask = false,
1822    ManualCodegen = [{
1823      std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
1824      IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
1825    }] in {
1826  defm vmerge : RVVOutOp1BuiltinSet<"vfmerge", "xfd",
1827                                    [["vvm", "v", "vmvv"]]>;
1828  defm vfmerge : RVVOutOp1BuiltinSet<"vfmerge", "xfd",
1829                                    [["vfm", "v", "vmve"]]>;
1830}
1831
1832// 14.16. Vector Floating-Point Move Instruction
1833let HasMask = false, HasNoMaskedOverloaded = false in
1834  defm vfmv_v : RVVOutBuiltinSet<"vfmv_v_f", "xfd",
1835                                  [["f", "v", "ve"]]>;
1836
1837// 14.17. Single-Width Floating-Point/Integer Type-Convert Instructions
1838def vfcvt_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_xu">;
1839def vfcvt_x_f_v : RVVConvToSignedBuiltin<"vfcvt_x">;
1840def vfcvt_rtz_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_rtz_xu">;
1841def vfcvt_rtz_x_f_v : RVVConvToSignedBuiltin<"vfcvt_rtz_x">;
1842def vfcvt_f_xu_v : RVVConvBuiltin<"Fv", "FvUv", "sil", "vfcvt_f">;
1843def vfcvt_f_x_v : RVVConvBuiltin<"Fv", "Fvv", "sil", "vfcvt_f">;
1844
1845// 14.18. Widening Floating-Point/Integer Type-Convert Instructions
1846let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1847  def vfwcvt_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_xu">;
1848  def vfwcvt_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_x">;
1849  def vfwcvt_rtz_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_rtz_xu">;
1850  def vfwcvt_rtz_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_rtz_x">;
1851  def vfwcvt_f_xu_v : RVVConvBuiltin<"Fw", "FwUv", "csi", "vfwcvt_f">;
1852  def vfwcvt_f_x_v : RVVConvBuiltin<"Fw", "Fwv", "csi", "vfwcvt_f">;
1853  def vfwcvt_f_f_v : RVVConvBuiltin<"w", "wv", "xf", "vfwcvt_f">;
1854}
1855
1856// 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions
1857let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1858  def vfncvt_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_xu">;
1859  def vfncvt_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_x">;
1860  def vfncvt_rtz_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_rtz_xu">;
1861  def vfncvt_rtz_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_rtz_x">;
1862  def vfncvt_f_xu_w : RVVConvBuiltin<"Fv", "FvUw", "csi", "vfncvt_f">;
1863  def vfncvt_f_x_w : RVVConvBuiltin<"Fv", "Fvw", "csi", "vfncvt_f">;
1864  def vfncvt_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_f">;
1865  def vfncvt_rod_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_rod_f">;
1866}
1867
1868// 15. Vector Reduction Operations
1869// 15.1. Vector Single-Width Integer Reduction Instructions
1870defm vredsum : RVVIntReductionBuiltinSet;
1871defm vredmaxu : RVVUnsignedReductionBuiltin;
1872defm vredmax : RVVSignedReductionBuiltin;
1873defm vredminu : RVVUnsignedReductionBuiltin;
1874defm vredmin : RVVSignedReductionBuiltin;
1875defm vredand : RVVIntReductionBuiltinSet;
1876defm vredor : RVVIntReductionBuiltinSet;
1877defm vredxor : RVVIntReductionBuiltinSet;
1878
1879// 15.2. Vector Widening Integer Reduction Instructions
1880// Vector Widening Integer Reduction Operations
1881let HasMaskedOffOperand = false in {
1882  defm vwredsum : RVVOutOp1BuiltinSet<"vwredsum", "csi",
1883                                      [["vs", "vSw", "SwSwvSw"]]>;
1884  defm vwredsumu : RVVOutOp1BuiltinSet<"vwredsumu", "csi",
1885                                       [["vs", "UvUSw", "USwUSwUvUSw"]]>;
1886}
1887
1888// 15.3. Vector Single-Width Floating-Point Reduction Instructions
1889defm vfredmax : RVVFloatingReductionBuiltin;
1890defm vfredmin : RVVFloatingReductionBuiltin;
1891defm vfredsum : RVVFloatingReductionBuiltin;
1892defm vfredosum : RVVFloatingReductionBuiltin;
1893
1894// 15.4. Vector Widening Floating-Point Reduction Instructions
1895defm vfwredsum : RVVFloatingWidenReductionBuiltin;
1896defm vfwredosum : RVVFloatingWidenReductionBuiltin;
1897
1898// 16. Vector Mask Instructions
1899// 16.1. Vector Mask-Register Logical Instructions
1900def vmand    : RVVMaskBinBuiltin;
1901def vmnand   : RVVMaskBinBuiltin;
1902def vmandnot : RVVMaskBinBuiltin;
1903def vmxor    : RVVMaskBinBuiltin;
1904def vmor     : RVVMaskBinBuiltin;
1905def vmnor    : RVVMaskBinBuiltin;
1906def vmornot  : RVVMaskBinBuiltin;
1907def vmxnor   : RVVMaskBinBuiltin;
1908// pseudoinstructions
1909def vmclr    : RVVMaskNullaryBuiltin;
1910def vmset    : RVVMaskNullaryBuiltin;
1911defm vmmv_m : RVVPseudoMaskBuiltin<"vmand", "c">;
1912defm vmnot_m : RVVPseudoMaskBuiltin<"vmnand", "c">;
1913
1914// 16.2. Vector mask population count vpopc
1915def vpopc : RVVMaskOp0Builtin<"um">;
1916
1917// 16.3. vfirst find-first-set mask bit
1918def vfirst : RVVMaskOp0Builtin<"lm">;
1919
1920// 16.4. vmsbf.m set-before-first mask bit
1921def vmsbf : RVVMaskUnaryBuiltin;
1922
1923// 16.5. vmsif.m set-including-first mask bit
1924def vmsif : RVVMaskUnaryBuiltin;
1925
1926// 16.6. vmsof.m set-only-first mask bit
1927def vmsof : RVVMaskUnaryBuiltin;
1928
1929let HasNoMaskedOverloaded = false in {
1930  // 16.8. Vector Iota Instruction
1931  defm viota : RVVOutBuiltinSet<"viota", "csil", [["m", "Uv", "Uvm"]]>;
1932
1933  // 16.9. Vector Element Index Instruction
1934  defm vid : RVVOutBuiltinSet<"vid", "csil", [["v", "v", "v"],
1935                                              ["v", "Uv", "Uv"]]>;
1936}
1937
1938// 17. Vector Permutation Instructions
1939// 17.1. Integer Scalar Move Instructions
1940let HasMask = false in {
1941  let HasVL = false, MangledName = "vmv_x" in
1942    defm vmv_x : RVVOp0BuiltinSet<"vmv_x_s", "csil",
1943                                   [["s", "ve", "ev"],
1944                                    ["s", "UvUe", "UeUv"]]>;
1945  let MangledName = "vmv_s" in
1946    defm vmv_s : RVVOutBuiltinSet<"vmv_s_x", "csil",
1947                                   [["x", "v", "vve"],
1948                                    ["x", "Uv", "UvUvUe"]]>;
1949}
1950
1951// 17.2. Floating-Point Scalar Move Instructions
1952let HasMask = false in {
1953  let HasVL = false, MangledName = "vfmv_f" in
1954    defm vfmv_f : RVVOp0BuiltinSet<"vfmv_f_s", "xfd",
1955                                     [["s", "ve", "ev"]]>;
1956  let MangledName = "vfmv_s" in
1957    defm vfmv_s : RVVOutBuiltinSet<"vfmv_s_f", "xfd",
1958                                     [["f", "v", "vve"],
1959                                      ["x", "Uv", "UvUvUe"]]>;
1960}
1961
1962// 17.3. Vector Slide Instructions
1963// 17.3.1. Vector Slideup Instructions
1964defm vslideup   : RVVSlideBuiltinSet;
1965// 17.3.2. Vector Slidedown Instructions
1966defm vslidedown : RVVSlideBuiltinSet;
1967
1968// 17.3.3. Vector Slide1up Instructions
1969defm vslide1up : RVVSlideOneBuiltinSet;
1970defm vfslide1up : RVVFloatingBinVFBuiltinSet;
1971
1972// 17.3.4. Vector Slide1down Instruction
1973defm vslide1down : RVVSlideOneBuiltinSet;
1974defm vfslide1down : RVVFloatingBinVFBuiltinSet;
1975
1976// 17.4. Vector Register Gather Instructions
1977// signed and floating type
1978defm vrgather : RVVOutBuiltinSet<"vrgather_vv", "csilxfd",
1979                                 [["vv", "v", "vvUv"]]>;
1980defm vrgather : RVVOutBuiltinSet<"vrgather_vx", "csilxfd",
1981                                 [["vx", "v", "vvz"]]>;
1982defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csilxfd",
1983                                     [["vv", "v", "vv(Log2EEW:4)Uv"]]>;
1984// unsigned type
1985defm vrgather : RVVOutBuiltinSet<"vrgather_vv", "csil",
1986                                 [["vv", "Uv", "UvUvUv"]]>;
1987defm vrgather : RVVOutBuiltinSet<"vrgather_vx", "csil",
1988                                 [["vx", "Uv", "UvUvz"]]>;
1989defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csil",
1990                                     [["vv", "Uv", "UvUv(Log2EEW:4)Uv"]]>;
1991
1992// 17.5. Vector Compress Instruction
1993let HasMask = false,
1994    ManualCodegen = [{
1995      std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
1996      IntrinsicTypes = {ResultType, Ops[3]->getType()};
1997    }] in {
1998  // signed and floating type
1999  defm vcompress : RVVOutBuiltinSet<"vcompress", "csilxfd",
2000                                    [["vm", "v", "vmvv"]]>;
2001  // unsigned type
2002  defm vcompress : RVVOutBuiltinSet<"vcompress", "csil",
2003                                    [["vm", "Uv", "UvmUvUv"]]>;
2004}
2005
2006// Miscellaneous
2007let HasMask = false, HasVL = false, IRName = "" in {
2008  let Name = "vreinterpret_v",
2009      ManualCodegen = [{
2010        return Builder.CreateBitCast(Ops[0], ResultType);
2011      }] in {
2012    // Reinterpret between different type under the same SEW and LMUL
2013    def vreinterpret_i_u : RVVBuiltin<"Uvv", "vUv", "csil", "v">;
2014    def vreinterpret_i_f : RVVBuiltin<"Fvv", "vFv", "sil", "v">;
2015    def vreinterpret_u_i : RVVBuiltin<"vUv", "Uvv", "csil", "Uv">;
2016    def vreinterpret_u_f : RVVBuiltin<"FvUv", "UvFv", "sil", "Uv">;
2017    def vreinterpret_f_i : RVVBuiltin<"vFv", "Fvv", "sil", "Fv">;
2018    def vreinterpret_f_u : RVVBuiltin<"UvFv", "FvUv", "sil", "Fv">;
2019
2020    // Reinterpret between different SEW under the same LMUL
2021    foreach dst_sew = ["(FixedSEW:8)", "(FixedSEW:16)", "(FixedSEW:32)",
2022                       "(FixedSEW:64)"] in {
2023      def vreinterpret_i_ # dst_sew : RVVBuiltin<"v" # dst_sew # "v",
2024                                                 dst_sew # "vv", "csil", dst_sew # "v">;
2025      def vreinterpret_u_ # dst_sew : RVVBuiltin<"Uv" # dst_sew # "Uv",
2026                                                 dst_sew # "UvUv", "csil", dst_sew # "Uv">;
2027    }
2028  }
2029
2030  let Name = "vundefined", HasNoMaskedOverloaded = false,
2031      ManualCodegen = [{
2032        return llvm::UndefValue::get(ResultType);
2033      }] in {
2034    def vundefined : RVVBuiltin<"v", "v", "csilxfd">;
2035    def vundefined_u : RVVBuiltin<"Uv", "Uv", "csil">;
2036  }
2037
2038  // LMUL truncation
2039  // C/C++ Operand: VecTy, IR Operand: VecTy, Index
2040  let Name = "vlmul_trunc_v", MangledName = "vlmul_trunc",
2041      ManualCodegen = [{ {
2042        ID = Intrinsic::experimental_vector_extract;
2043        IntrinsicTypes = {ResultType, Ops[0]->getType()};
2044        Ops.push_back(ConstantInt::get(Int64Ty, 0));
2045        return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
2046      } }] in {
2047    foreach dst_lmul = ["(SFixedLog2LMUL:-3)", "(SFixedLog2LMUL:-2)", "(SFixedLog2LMUL:-1)",
2048                        "(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in {
2049      def vlmul_trunc # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v",
2050                                              dst_lmul # "vv", "csilxfd", dst_lmul # "v">;
2051      def vlmul_trunc_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv",
2052                                                dst_lmul # "UvUv", "csil", dst_lmul # "Uv">;
2053    }
2054  }
2055
2056  // LMUL extension
2057  // C/C++ Operand: SubVecTy, IR Operand: VecTy, SubVecTy, Index
2058  let Name = "vlmul_ext_v", MangledName = "vlmul_ext",
2059      ManualCodegen = [{
2060        ID = Intrinsic::experimental_vector_insert;
2061        IntrinsicTypes = {ResultType, Ops[0]->getType()};
2062        Ops.push_back(llvm::UndefValue::get(ResultType));
2063        std::swap(Ops[0], Ops[1]);
2064        Ops.push_back(ConstantInt::get(Int64Ty, 0));
2065        return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
2066      }] in {
2067    foreach dst_lmul = ["(LFixedLog2LMUL:-2)", "(LFixedLog2LMUL:-1)", "(LFixedLog2LMUL:-0)",
2068                        "(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in {
2069      def vlmul_ext # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v",
2070                                            dst_lmul # "vv", "csilxfd", dst_lmul # "v">;
2071      def vlmul_ext_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv",
2072                                              dst_lmul # "UvUv", "csil", dst_lmul # "Uv">;
2073    }
2074  }
2075
2076  let Name = "vget_v",
2077      ManualCodegen = [{
2078      {
2079        ID = Intrinsic::experimental_vector_extract;
2080        ScalableVectorType *VecTy = cast<ScalableVectorType>(ResultType);
2081        Ops[1] = Builder.CreateMul(Ops[1],
2082                                   ConstantInt::get(Ops[1]->getType(),
2083                                                    VecTy->getMinNumElements()));
2084        IntrinsicTypes = {ResultType, Ops[0]->getType()};
2085        return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
2086      }
2087      }] in {
2088    foreach dst_lmul = ["(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in {
2089      def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vvKz", "csilfd", dst_lmul # "v">;
2090      def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUvKz", "csil", dst_lmul # "Uv">;
2091    }
2092  }
2093
2094  let Name = "vset_v", Log2LMUL = [0, 1, 2],
2095      ManualCodegen = [{
2096      {
2097        ID = Intrinsic::experimental_vector_insert;
2098        IntrinsicTypes = {ResultType, Ops[2]->getType()};
2099        ScalableVectorType *VecTy = cast<ScalableVectorType>(Ops[2]->getType());
2100        Ops[1] = Builder.CreateMul(Ops[1],
2101                                   ConstantInt::get(Ops[1]->getType(),
2102                                                    VecTy->getMinNumElements()));
2103        std::swap(Ops[1], Ops[2]);
2104        return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
2105      }
2106      }] in {
2107    foreach dst_lmul = ["(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in {
2108      def : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "v" # dst_lmul # "vKzv", "csilfd">;
2109      def : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "Uv" # dst_lmul #"UvKzUv", "csil">;
2110    }
2111  }
2112}
2113