xref: /llvm-project/clang/include/clang/Basic/riscv_vector_common.td (revision e375c0f7d0c8f4c49ff2a430da0c3a7d058e9cf3)
1//==------ riscv_vector_common.td - RISC-V V-ext builtin class ------------===//
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 RVV builtin base class for RISC-V V-extension.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14// Instruction definitions
15//===----------------------------------------------------------------------===//
16// Each record of the class RVVBuiltin defines a collection of builtins (i.e.
17// "def vadd : RVVBuiltin" will be used to define things like "vadd_vv_i32m1",
18// "vadd_vv_i32m2", etc).
19//
20// The elements of this collection are defined by an instantiation process the
21// range of which is specified by the cross product of the LMUL attribute and
22// every element in the attribute TypeRange. By default builtins have LMUL = [1,
23// 2, 4, 8, 1/2, 1/4, 1/8] so the process is repeated 7 times. In tablegen we
24// use the Log2LMUL [0, 1, 2, 3, -1, -2, -3] to represent the LMUL.
25//
26// LMUL represents the fact that the types of values used by that builtin are
27// values generated by instructions that are executed under that LMUL. However,
28// this does not mean the builtin is necessarily lowered into an instruction
29// that executes under the specified LMUL. An example where this happens are
30// loads and stores of masks. A mask like `vbool8_t` can be generated, for
31// instance, by comparing two `__rvv_int8m1_t` (this is LMUL=1) or comparing two
32// `__rvv_int16m2_t` (this is LMUL=2). The actual load or store, however, will
33// be performed under LMUL=1 because mask registers are not grouped.
34//
35// TypeRange is a non-empty sequence of basic types:
36//
37//   c: int8_t (i8)
38//   s: int16_t (i16)
39//   i: int32_t (i32)
40//   l: int64_t (i64)
41//   x: float16_t (half)
42//   f: float32_t (float)
43//   d: float64_t (double)
44//   y: bfloat16_t (bfloat16)
45//
46// This way, given an LMUL, a record with a TypeRange "sil" will cause the
47// definition of 3 builtins. Each type "t" in the TypeRange (in this example
48// they are int16_t, int32_t, int64_t) is used as a parameter that drives the
49// definition of that particular builtin (for the given LMUL).
50//
51// During the instantiation, types can be transformed or modified using type
52// transformers. Given a type "t" the following primitive type transformers can
53// be applied to it to yield another type.
54//
55//   e: type of "t" as is (identity)
56//   v: computes a vector type whose element type is "t" for the current LMUL
57//   w: computes a vector type identical to what 'v' computes except for the
58//      element type which is twice as wide as the element type of 'v'
59//   q: computes a vector type identical to what 'v' computes except for the
60//      element type which is four times as wide as the element type of 'v'
61//   o: computes a vector type identical to what 'v' computes except for the
62//      element type which is eight times as wide as the element type of 'v'
63//   m: computes a vector type identical to what 'v' computes except for the
64//      element type which is bool
65//   0: void type, ignores "t"
66//   z: size_t, ignores "t"
67//   t: ptrdiff_t, ignores "t"
68//   u: unsigned long, ignores "t"
69//   l: long, ignores "t"
70//   f: float32, 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//   (SEFixedLog2LMUL:Value): Smaller or Equal Fixed Log2LMUL. Given a vector
103//      type (SEW and LMUL), and computes another vector type which only
104//      changed LMUL as given value. The new LMUL should be smaller than or
105//      equal to the old one. Ignore to define a new builtin if its equivalent
106//      type has illegal lmul.
107//   (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW
108//      and LMUL), and computes another vector type which only changed LMUL as
109//      given value. The new LMUL should be larger than the old one. Ignore to
110//      define a new builtin if its equivalent type has illegal lmul.
111//
112// Following with the example above, if t is "i", then "Ue" will yield unsigned
113// int and "Fv" will yield __rvv_float32m1_t (again assuming LMUL=1), Fw would
114// yield __rvv_float64m2_t, etc.
115//
116// Each builtin is then defined by applying each type in TypeRange against the
117// sequence of type transformers described in Suffix and Prototype.
118//
119// The name of the builtin is defined by the Name attribute (which defaults to
120// the name of the class) appended (separated with an underscore) the Suffix
121// attribute. For instance with Name="foo", Suffix = "v" and TypeRange = "il",
122// the builtin generated will be __builtin_rvv_foo_i32m1 and
123// __builtin_rvv_foo_i64m1 (under LMUL=1). If Suffix contains more than one
124// type transformer (say "vv") each of the types is separated with an
125// underscore as in "__builtin_rvv_foo_i32m1_i32m1".
126//
127// The C/C++ prototype of the builtin is defined by the Prototype attribute.
128// Prototype is a non-empty sequence of type transformers, the first of which
129// is the return type of the builtin and the rest are the parameters of the
130// builtin, in order. For instance if Prototype is "wvv" and TypeRange is "si"
131// a first builtin will have type
132// __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t) and the second builtin
133// will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t) (again
134// under LMUL=1).
135//
136// There are a number of attributes that are used to constraint the number and
137// shape of the builtins generated. Refer to the comments below for them.
138
139class PolicyScheme<int val>{
140  int Value = val;
141}
142def NonePolicy : PolicyScheme<0>;
143def HasPassthruOperand : PolicyScheme<1>;
144def HasPolicyOperand : PolicyScheme<2>;
145
146class RVVBuiltin<string suffix, string prototype, string type_range,
147                 string overloaded_suffix = ""> {
148  // Base name that will be prepended in __builtin_rvv_ and appended the
149  // computed Suffix.
150  string Name = NAME;
151
152  // If not empty, each instantiated builtin will have this appended after an
153  // underscore (_). It is instantiated like Prototype.
154  string Suffix = suffix;
155
156  // If empty, default OverloadedName is sub string of `Name` which end of first
157  // '_'. For example, the default overloaded name  is `vadd` for Name `vadd_vv`.
158  // It's used for describe some special naming cases.
159  string OverloadedName = "";
160
161  // If not empty, each OverloadedName will have this appended after an
162  // underscore (_). It is instantiated like Prototype.
163  string OverloadedSuffix = overloaded_suffix;
164
165  // The different variants of the builtin, parameterised with a type.
166  string TypeRange = type_range;
167
168  // We use each type described in TypeRange and LMUL with prototype to
169  // instantiate a specific element of the set of builtins being defined.
170  // Prototype attribute defines the C/C++ prototype of the builtin. It is a
171  // non-empty sequence of type transformers, the first of which is the return
172  // type of the builtin and the rest are the parameters of the builtin, in
173  // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a
174  // first builtin will have type
175  // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin
176  // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t).
177  string Prototype = prototype;
178
179  // This builtin has a masked form.
180  bit HasMasked = true;
181
182  // If HasMasked, this flag states that this builtin has a maskedoff operand. It
183  // is always the first operand in builtin and IR intrinsic.
184  bit HasMaskedOffOperand = true;
185
186  // This builtin has a granted vector length parameter.
187  bit HasVL = true;
188
189  // The policy scheme for masked intrinsic IR.
190  // It could be NonePolicy or HasPolicyOperand.
191  // HasPolicyOperand: Has a policy operand. 0 is tail and mask undisturbed, 1 is
192  // tail agnostic, 2 is mask undisturbed, and 3 is tail and mask agnostic. The
193  // policy operand is located at the last position.
194  PolicyScheme MaskedPolicyScheme = HasPolicyOperand;
195
196  // The policy scheme for unmasked intrinsic IR.
197  // It could be NonePolicy, HasPassthruOperand or HasPolicyOperand.
198  // HasPassthruOperand: Has a passthru operand to decide tail policy. If it is
199  // poison, tail policy is tail agnostic, otherwise policy is tail undisturbed.
200  // HasPolicyOperand: Has a policy operand. 1 is tail agnostic and 0 is tail
201  // undisturbed.
202  PolicyScheme UnMaskedPolicyScheme = NonePolicy;
203
204  // This builtin support tail agnostic and undisturbed policy.
205  bit HasTailPolicy = true;
206  // This builtin support mask agnostic and undisturbed policy.
207  bit HasMaskPolicy = true;
208
209  // This builtin prototype with TA or TAMA policy could not support overloading
210  // API. Other policy intrinsic functions would support overloading API with
211  // suffix `_tu`, `tumu`, `tuma`, `tamu` and `tama`.
212  bit SupportOverloading = true;
213
214  // This builtin is valid for the given Log2LMULs.
215  list<int> Log2LMUL = [0, 1, 2, 3, -1, -2, -3];
216
217  // Manual code in clang codegen riscv_vector_builtin_cg.inc
218  code ManualCodegen = [{}];
219
220  // When emit the automatic clang codegen, it describes what types we have to use
221  // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise,
222  // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd
223  // parameter of the unmasked version. k can't be the mask operand's position.
224  list<int> IntrinsicTypes = [];
225
226  // If these names are not empty, this is the ID of the LLVM intrinsic
227  // we want to lower to.
228  string IRName = NAME;
229
230  // If HasMasked, this is the ID of the LLVM intrinsic we want to lower to.
231  string MaskedIRName = NAME #"_mask";
232
233  // Use clang_builtin_alias to save the number of builtins.
234  bit HasBuiltinAlias = true;
235
236  // Features required to enable for this builtin.
237  list<string> RequiredFeatures = [];
238
239  // Number of fields for Load/Store Segment instructions.
240  int NF = 1;
241
242  // Set to true if the builtin is associated with tuple types.
243  bit IsTuple = false;
244
245  // Set to true if the builtin has a parameter that models floating-point
246  // rounding mode control
247  bit HasFRMRoundModeOp = false;
248}
249
250// This is the code emitted in the header.
251class RVVHeader {
252  code HeaderCode;
253}
254
255//===----------------------------------------------------------------------===//
256// Basic classes with automatic codegen.
257//===----------------------------------------------------------------------===//
258
259class RVVOutBuiltin<string suffix, string prototype, string type_range>
260    : RVVBuiltin<suffix, prototype, type_range> {
261  let IntrinsicTypes = [-1];
262}
263
264class RVVOp0Builtin<string suffix, string prototype, string type_range>
265    : RVVBuiltin<suffix, prototype, type_range> {
266  let IntrinsicTypes = [0];
267}
268
269class RVVOutOp1Builtin<string suffix, string prototype, string type_range>
270    : RVVBuiltin<suffix, prototype, type_range> {
271  let IntrinsicTypes = [-1, 1];
272}
273
274class RVVOutOp0Op1Builtin<string suffix, string prototype, string type_range>
275    : RVVBuiltin<suffix, prototype, type_range> {
276  let IntrinsicTypes = [-1, 0, 1];
277}
278
279multiclass RVVBuiltinSet<string intrinsic_name, string type_range,
280                         list<list<string>> suffixes_prototypes,
281                         list<int> intrinsic_types> {
282  let IRName = intrinsic_name, MaskedIRName = intrinsic_name # "_mask",
283      IntrinsicTypes = intrinsic_types in {
284    foreach s_p = suffixes_prototypes in {
285      let Name = NAME # "_" # s_p[0] in {
286        defvar suffix = s_p[1];
287        defvar prototype = s_p[2];
288        def : RVVBuiltin<suffix, prototype, type_range>;
289      }
290    }
291  }
292}
293
294// IntrinsicTypes is output, op0, op1 [-1, 0, 1]
295multiclass RVVOutOp0Op1BuiltinSet<string intrinsic_name, string type_range,
296                                  list<list<string>> suffixes_prototypes>
297    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes,
298                            [-1, 0, 1]>;
299
300multiclass RVVOutBuiltinSet<string intrinsic_name, string type_range,
301                            list<list<string>> suffixes_prototypes>
302    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1]>;
303
304multiclass RVVOp0BuiltinSet<string intrinsic_name, string type_range,
305                            list<list<string>> suffixes_prototypes>
306    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0]>;
307
308// IntrinsicTypes is output, op1 [-1, 0]
309multiclass RVVOutOp0BuiltinSet<string intrinsic_name, string type_range,
310                               list<list<string>> suffixes_prototypes>
311    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 0]>;
312
313// IntrinsicTypes is output, op1 [-1, 1]
314multiclass RVVOutOp1BuiltinSet<string intrinsic_name, string type_range,
315                               list<list<string>> suffixes_prototypes>
316    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1]>;
317
318multiclass RVVOp0Op1BuiltinSet<string intrinsic_name, string type_range,
319                               list<list<string>> suffixes_prototypes>
320    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0, 1]>;
321
322multiclass RVVOutOp1Op2BuiltinSet<string intrinsic_name, string type_range,
323                                  list<list<string>> suffixes_prototypes>
324    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1, 2]>;
325
326// IntrinsicTypes is output, op2 [-1, 2]
327multiclass RVVOutOp2BuiltinSet<string intrinsic_name, string type_range,
328                               list<list<string>> suffixes_prototypes>
329    : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 2]>;
330
331multiclass RVVSignedBinBuiltinSet
332    : RVVOutOp1BuiltinSet<NAME, "csil",
333                          [["vv", "v", "vvv"],
334                           ["vx", "v", "vve"]]>;
335
336multiclass RVVSignedBinBuiltinSetRoundingMode
337    : RVVOutOp1BuiltinSet<NAME, "csil",
338                          [["vv", "v", "vvvu"],
339                           ["vx", "v", "vveu"]]>;
340
341multiclass RVVUnsignedBinBuiltinSet
342    : RVVOutOp1BuiltinSet<NAME, "csil",
343                          [["vv", "Uv", "UvUvUv"],
344                           ["vx", "Uv", "UvUvUe"]]>;
345
346multiclass RVVUnsignedBinBuiltinSetRoundingMode
347    : RVVOutOp1BuiltinSet<NAME, "csil",
348                          [["vv", "Uv", "UvUvUvu"],
349                           ["vx", "Uv", "UvUvUeu"]]>;
350
351multiclass RVVIntBinBuiltinSet
352    : RVVSignedBinBuiltinSet,
353      RVVUnsignedBinBuiltinSet;
354
355multiclass RVVInt64BinBuiltinSet
356    : RVVOutOp1BuiltinSet<NAME, "l",
357                          [["vv", "v", "vvv"],
358                           ["vx", "v", "vve"]]>,
359      RVVOutOp1BuiltinSet<NAME, "l",
360                          [["vv", "Uv", "UvUvUv"],
361                           ["vx", "Uv", "UvUvUe"]]>;
362
363multiclass RVVSlideOneBuiltinSet
364    : RVVOutOp1BuiltinSet<NAME, "csil",
365                          [["vx", "v", "vve"],
366                           ["vx", "Uv", "UvUvUe"]]>;
367
368multiclass RVVSignedShiftBuiltinSet
369    : RVVOutOp1BuiltinSet<NAME, "csil",
370                          [["vv", "v", "vvUv"],
371                           ["vx", "v", "vvz"]]>;
372
373multiclass RVVSignedShiftBuiltinSetRoundingMode
374    : RVVOutOp1BuiltinSet<NAME, "csil",
375                          [["vv", "v", "vvUvu"],
376                           ["vx", "v", "vvzu"]]>;
377
378multiclass RVVUnsignedShiftBuiltinSet
379    : RVVOutOp1BuiltinSet<NAME, "csil",
380                          [["vv", "Uv", "UvUvUv"],
381                           ["vx", "Uv", "UvUvz"]]>;
382
383multiclass RVVUnsignedShiftBuiltinSetRoundingMode
384    : RVVOutOp1BuiltinSet<NAME, "csil",
385                          [["vv", "Uv", "UvUvUvu"],
386                           ["vx", "Uv", "UvUvzu"]]>;
387
388multiclass RVVShiftBuiltinSet
389    : RVVSignedShiftBuiltinSet,
390      RVVUnsignedShiftBuiltinSet;
391
392let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
393  multiclass RVVSignedNShiftBuiltinSet
394      : RVVOutOp0Op1BuiltinSet<NAME, "csil",
395                                     [["wv", "v", "vwUv"],
396                                      ["wx", "v", "vwz"]]>;
397
398  multiclass RVVSignedNShiftBuiltinSetRoundingMode
399      : RVVOutOp0Op1BuiltinSet<NAME, "csil",
400                                     [["wv", "v", "vwUvu"],
401                                      ["wx", "v", "vwzu"]]>;
402
403  multiclass RVVUnsignedNShiftBuiltinSet
404      : RVVOutOp0Op1BuiltinSet<NAME, "csil",
405                                     [["wv", "Uv", "UvUwUv"],
406                                      ["wx", "Uv", "UvUwz"]]>;
407
408  multiclass RVVUnsignedNShiftBuiltinSetRoundingMode
409      : RVVOutOp0Op1BuiltinSet<NAME, "csil",
410                                     [["wv", "Uv", "UvUwUvu"],
411                                      ["wx", "Uv", "UvUwzu"]]>;
412
413}
414
415multiclass RVVCarryinBuiltinSet
416    : RVVOutOp1BuiltinSet<NAME, "csil",
417                          [["vvm", "v", "vvvm"],
418                           ["vxm", "v", "vvem"],
419                           ["vvm", "Uv", "UvUvUvm"],
420                           ["vxm", "Uv", "UvUvUem"]]>;
421
422multiclass RVVCarryOutInBuiltinSet<string intrinsic_name>
423    : RVVOp0Op1BuiltinSet<intrinsic_name, "csil",
424                          [["vvm", "vm", "mvvm"],
425                           ["vxm", "vm", "mvem"],
426                           ["vvm", "Uvm", "mUvUvm"],
427                           ["vxm", "Uvm", "mUvUem"]]>;
428
429multiclass RVVSignedMaskOutBuiltinSet
430    : RVVOp0Op1BuiltinSet<NAME, "csil",
431                          [["vv", "vm", "mvv"],
432                           ["vx", "vm", "mve"]]>;
433
434multiclass RVVUnsignedMaskOutBuiltinSet
435    : RVVOp0Op1BuiltinSet<NAME, "csil",
436                          [["vv", "Uvm", "mUvUv"],
437                           ["vx", "Uvm", "mUvUe"]]>;
438
439multiclass RVVIntMaskOutBuiltinSet
440    : RVVSignedMaskOutBuiltinSet,
441      RVVUnsignedMaskOutBuiltinSet;
442
443class RVVIntExt<string intrinsic_name, string suffix, string prototype,
444                string type_range>
445    : RVVBuiltin<suffix, prototype, type_range> {
446  let IRName = intrinsic_name;
447  let MaskedIRName = intrinsic_name # "_mask";
448  let OverloadedName = NAME;
449  let IntrinsicTypes = [-1, 0];
450}
451
452let HasMaskedOffOperand = false in {
453  multiclass RVVIntTerBuiltinSet {
454    defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
455                                  [["vv", "v", "vvvv"],
456                                   ["vx", "v", "vvev"],
457                                   ["vv", "Uv", "UvUvUvUv"],
458                                   ["vx", "Uv", "UvUvUeUv"]]>;
459  }
460  multiclass RVVFloatingTerBuiltinSet {
461    defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
462                                  [["vv", "v", "vvvv"],
463                                   ["vf", "v", "vvev"]]>;
464    let RequiredFeatures = ["Zvfh"] in
465      defm "" : RVVOutOp1BuiltinSet<NAME, "x",
466                                    [["vv", "v", "vvvv"],
467                                     ["vf", "v", "vvev"]]>;
468  }
469  multiclass RVVFloatingTerBuiltinSetRoundingMode {
470    defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
471                                  [["vv", "v", "vvvvu"],
472                                   ["vf", "v", "vvevu"]]>;
473    let RequiredFeatures = ["Zvfh"] in
474      defm "" : RVVOutOp1BuiltinSet<NAME, "x",
475                                    [["vv", "v", "vvvvu"],
476                                     ["vf", "v", "vvevu"]]>;
477  }
478}
479
480let HasMaskedOffOperand = false, Log2LMUL = [-2, -1, 0, 1, 2] in {
481  multiclass RVVFloatingWidenTerBuiltinSet {
482    defm ""  : RVVOutOp1Op2BuiltinSet<NAME, "f",
483                                      [["vv", "w", "wwvv"],
484                                       ["vf", "w", "wwev"]]>;
485    let RequiredFeatures = ["Zvfh"] in
486      defm ""  : RVVOutOp1Op2BuiltinSet<NAME, "x",
487                                        [["vv", "w", "wwvv"],
488                                         ["vf", "w", "wwev"]]>;
489  }
490  multiclass RVVFloatingWidenTerBuiltinSetRoundingMode {
491    defm ""  : RVVOutOp1Op2BuiltinSet<NAME, "f",
492                                      [["vv", "w", "wwvvu"],
493                                       ["vf", "w", "wwevu"]]>;
494    let RequiredFeatures = ["Zvfh"] in
495      defm ""  : RVVOutOp1Op2BuiltinSet<NAME, "x",
496                                        [["vv", "w", "wwvvu"],
497                                         ["vf", "w", "wwevu"]]>;
498  }
499}
500
501multiclass RVVFloatingBinBuiltinSet {
502  defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
503                                [["vv", "v", "vvv"],
504                                 ["vf", "v", "vve"]]>;
505  let RequiredFeatures = ["Zvfh"] in
506    defm "" : RVVOutOp1BuiltinSet<NAME, "x",
507                                  [["vv", "v", "vvv"],
508                                   ["vf", "v", "vve"]]>;
509}
510
511multiclass RVVFloatingBinBuiltinSetRoundingMode {
512  defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
513                                [["vv", "v", "vvvu"],
514                                 ["vf", "v", "vveu"]]>;
515  let RequiredFeatures = ["Zvfh"] in
516    defm "" : RVVOutOp1BuiltinSet<NAME, "x",
517                                  [["vv", "v", "vvvu"],
518                                   ["vf", "v", "vveu"]]>;
519}
520
521multiclass RVVFloatingBinVFBuiltinSet {
522  defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
523                                [["vf", "v", "vve"]]>;
524  let RequiredFeatures = ["Zvfh"] in
525    defm "" : RVVOutOp1BuiltinSet<NAME, "x",
526                                  [["vf", "v", "vve"]]>;
527}
528
529multiclass RVVFloatingBinVFBuiltinSetRoundingMode {
530  defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
531                                [["vf", "v", "vveu"]]>;
532  let RequiredFeatures = ["Zvfh"] in
533    defm "" : RVVOutOp1BuiltinSet<NAME, "x",
534                                  [["vf", "v", "vveu"]]>;
535}
536
537multiclass RVVFloatingMaskOutBuiltinSet {
538  defm "" : RVVOp0Op1BuiltinSet<NAME, "fd",
539                                [["vv", "vm", "mvv"],
540                                 ["vf", "vm", "mve"]]>;
541  let RequiredFeatures = ["Zvfh"] in
542    defm "" : RVVOp0Op1BuiltinSet<NAME, "x",
543                                  [["vv", "vm", "mvv"],
544                                   ["vf", "vm", "mve"]]>;
545}
546
547multiclass RVVFloatingMaskOutVFBuiltinSet
548    : RVVOp0Op1BuiltinSet<NAME, "fd",
549                          [["vf", "vm", "mve"]]>;
550
551multiclass RVVConvBuiltinSet<string intrinsic_name, string type_range,
552                         list<list<string>> suffixes_prototypes> {
553let Name = intrinsic_name,
554    IRName = intrinsic_name,
555    MaskedIRName = intrinsic_name # "_mask",
556    IntrinsicTypes = [-1, 0] in {
557  foreach s_p = suffixes_prototypes in {
558      defvar suffix = s_p[0];
559      defvar prototype = s_p[1];
560      def : RVVBuiltin<suffix, prototype, type_range>;
561    }
562  }
563}
564
565
566class RVVMaskBinBuiltin : RVVOutBuiltin<"m", "mmm", "c"> {
567  let Name = NAME # "_mm";
568  let HasMasked = false;
569}
570
571class RVVMaskUnaryBuiltin : RVVOutBuiltin<"m", "mm", "c"> {
572  let Name = NAME # "_m";
573}
574
575class RVVMaskNullaryBuiltin : RVVOutBuiltin<"m", "m", "c"> {
576  let Name = NAME # "_m";
577  let HasMasked = false;
578  let SupportOverloading = false;
579}
580
581class RVVMaskOp0Builtin<string prototype> : RVVOp0Builtin<"m", prototype, "c"> {
582  let Name = NAME # "_m";
583  let HasMaskedOffOperand = false;
584}
585
586let UnMaskedPolicyScheme = HasPolicyOperand,
587    HasMaskedOffOperand = false in {
588  multiclass RVVSlideUpBuiltinSet {
589    defm "" : RVVOutBuiltinSet<NAME, "csilfd",
590                               [["vx","v", "vvvz"]]>;
591    let RequiredFeatures = ["Zvfh"] in
592      defm "" : RVVOutBuiltinSet<NAME, "x",
593                                 [["vx","v", "vvvz"]]>;
594    defm "" : RVVOutBuiltinSet<NAME, "csil",
595                               [["vx","Uv", "UvUvUvz"]]>;
596  }
597}
598
599let UnMaskedPolicyScheme = HasPassthruOperand,
600    ManualCodegen = [{
601      if (IsMasked) {
602        std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
603        if ((PolicyAttrs & RVV_VTA) && (PolicyAttrs & RVV_VMA))
604          Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
605      } else {
606        if (PolicyAttrs & RVV_VTA)
607          Ops.insert(Ops.begin(), llvm::PoisonValue::get(ResultType));
608      }
609
610      Ops.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs));
611      IntrinsicTypes = {ResultType, Ops.back()->getType()};
612    }] in {
613  multiclass RVVSlideDownBuiltinSet {
614    defm "" : RVVOutBuiltinSet<NAME, "csilfd",
615                               [["vx","v", "vvz"]]>;
616    let RequiredFeatures = ["Zvfh"] in
617      defm "" : RVVOutBuiltinSet<NAME, "x",
618                                 [["vx","v", "vvz"]]>;
619    defm "" : RVVOutBuiltinSet<NAME, "csil",
620                               [["vx","Uv", "UvUvz"]]>;
621  }
622}
623
624class RVVConvBuiltin<string suffix, string prototype, string type_range,
625                     string overloaded_name>
626    : RVVBuiltin<suffix, prototype, type_range> {
627  let IntrinsicTypes = [-1, 0];
628  let OverloadedName = overloaded_name;
629}
630
631class RVVConvToSignedBuiltin<string overloaded_name>
632    : RVVConvBuiltin<"Iv", "Ivv", "xfd", overloaded_name>;
633
634class RVVConvToUnsignedBuiltin<string overloaded_name>
635    : RVVConvBuiltin<"Uv", "Uvv", "xfd", overloaded_name>;
636
637class RVVConvToWidenSignedBuiltin<string overloaded_name>
638    : RVVConvBuiltin<"Iw", "Iwv", "xf", overloaded_name>;
639
640class RVVConvToWidenUnsignedBuiltin<string overloaded_name>
641    : RVVConvBuiltin<"Uw", "Uwv", "xf", overloaded_name>;
642
643class RVVConvToNarrowingSignedBuiltin<string overloaded_name>
644    : RVVConvBuiltin<"Iv", "IvFw", "si", overloaded_name>;
645
646class RVVConvToNarrowingUnsignedBuiltin<string overloaded_name>
647    : RVVConvBuiltin<"Uv", "UvFw", "si", overloaded_name>;
648
649let HasMaskedOffOperand = true in {
650  multiclass RVVSignedReductionBuiltin {
651    defm "" : RVVOutOp0BuiltinSet<NAME, "csil",
652                                  [["vs", "vSv", "SvvSv"]]>;
653  }
654  multiclass RVVUnsignedReductionBuiltin {
655    defm "" : RVVOutOp0BuiltinSet<NAME, "csil",
656                                  [["vs", "UvUSv", "USvUvUSv"]]>;
657  }
658  multiclass RVVFloatingReductionBuiltin {
659    defm "" : RVVOutOp0BuiltinSet<NAME, "fd",
660                                  [["vs", "vSv", "SvvSv"]]>;
661    let RequiredFeatures = ["Zvfh"] in
662      defm "" : RVVOutOp0BuiltinSet<NAME, "x",
663                                    [["vs", "vSv", "SvvSv"]]>;
664  }
665  multiclass RVVFloatingReductionBuiltinRoundingMode {
666    defm "" : RVVOutOp0BuiltinSet<NAME, "fd",
667                                  [["vs", "vSv", "SvvSvu"]]>;
668    let RequiredFeatures = ["Zvfh"] in
669      defm "" : RVVOutOp0BuiltinSet<NAME, "x",
670                                    [["vs", "vSv", "SvvSvu"]]>;
671  }
672  multiclass RVVFloatingWidenReductionBuiltin {
673    defm "" : RVVOutOp0BuiltinSet<NAME, "f",
674                                  [["vs", "vSw", "SwvSw"]]>;
675    let RequiredFeatures = ["Zvfh"] in
676      defm "" : RVVOutOp0BuiltinSet<NAME, "x",
677                                    [["vs", "vSw", "SwvSw"]]>;
678  }
679  multiclass RVVFloatingWidenReductionBuiltinRoundingMode {
680    defm "" : RVVOutOp0BuiltinSet<NAME, "f",
681                                  [["vs", "vSw", "SwvSwu"]]>;
682    let RequiredFeatures = ["Zvfh"] in
683      defm "" : RVVOutOp0BuiltinSet<NAME, "x",
684                                    [["vs", "vSw", "SwvSwu"]]>;
685  }
686}
687
688multiclass RVVIntReductionBuiltinSet
689    : RVVSignedReductionBuiltin,
690      RVVUnsignedReductionBuiltin;
691
692// For widen operation which has different mangling name.
693multiclass RVVWidenBuiltinSet<string intrinsic_name, string type_range,
694                              list<list<string>> suffixes_prototypes> {
695  let Log2LMUL = [-3, -2, -1, 0, 1, 2],
696      IRName = intrinsic_name, MaskedIRName = intrinsic_name # "_mask" in {
697    foreach s_p = suffixes_prototypes in {
698      let Name = NAME # "_" # s_p[0],
699          OverloadedName = NAME # "_" # s_p[0] in {
700        defvar suffix = s_p[1];
701        defvar prototype = s_p[2];
702        def : RVVOutOp0Op1Builtin<suffix, prototype, type_range>;
703      }
704    }
705  }
706}
707
708// For widen operation with widen operand which has different mangling name.
709multiclass RVVWidenWOp0BuiltinSet<string intrinsic_name, string type_range,
710                                  list<list<string>> suffixes_prototypes> {
711  let Log2LMUL = [-3, -2, -1, 0, 1, 2],
712      IRName = intrinsic_name, MaskedIRName = intrinsic_name # "_mask" in {
713    foreach s_p = suffixes_prototypes in {
714      let Name = NAME # "_" # s_p[0],
715          OverloadedName = NAME # "_" # s_p[0] in {
716        defvar suffix = s_p[1];
717        defvar prototype = s_p[2];
718        def : RVVOutOp1Builtin<suffix, prototype, type_range>;
719      }
720    }
721  }
722}
723
724multiclass RVVSignedWidenBinBuiltinSet
725    : RVVWidenBuiltinSet<NAME, "csi",
726                         [["vv", "w", "wvv"],
727                          ["vx", "w", "wve"]]>;
728
729multiclass RVVSignedWidenOp0BinBuiltinSet
730    : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
731                             [["wv", "w", "wwv"],
732                              ["wx", "w", "wwe"]]>;
733
734multiclass RVVUnsignedWidenBinBuiltinSet
735    : RVVWidenBuiltinSet<NAME, "csi",
736                         [["vv", "Uw", "UwUvUv"],
737                          ["vx", "Uw", "UwUvUe"]]>;
738
739multiclass RVVUnsignedWidenOp0BinBuiltinSet
740    : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
741                             [["wv", "Uw", "UwUwUv"],
742                              ["wx", "Uw", "UwUwUe"]]>;
743
744multiclass RVVFloatingWidenBinBuiltinSet {
745  defm "" : RVVWidenBuiltinSet<NAME, "f",
746                               [["vv", "w", "wvv"],
747                                ["vf", "w", "wve"]]>;
748  let RequiredFeatures = ["Zvfh"] in
749    defm "" : RVVWidenBuiltinSet<NAME, "x",
750                                 [["vv", "w", "wvv"],
751                                  ["vf", "w", "wve"]]>;
752}
753
754multiclass RVVFloatingWidenBinBuiltinSetRoundingMode {
755  defm "" : RVVWidenBuiltinSet<NAME, "f",
756                               [["vv", "w", "wvvu"],
757                                ["vf", "w", "wveu"]]>;
758  let RequiredFeatures = ["Zvfh"] in
759    defm "" : RVVWidenBuiltinSet<NAME, "x",
760                                 [["vv", "w", "wvvu"],
761                                  ["vf", "w", "wveu"]]>;
762}
763
764multiclass RVVFloatingWidenOp0BinBuiltinSet {
765  defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "f",
766                                   [["wv", "w", "wwv"],
767                                    ["wf", "w", "wwe"]]>;
768  let RequiredFeatures = ["Zvfh"] in
769    defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "x",
770                                     [["wv", "w", "wwv"],
771                                      ["wf", "w", "wwe"]]>;
772}
773
774multiclass RVVFloatingWidenOp0BinBuiltinSetRoundingMode {
775  defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "f",
776                                   [["wv", "w", "wwvu"],
777                                    ["wf", "w", "wweu"]]>;
778  let RequiredFeatures = ["Zvfh"] in
779    defm "" : RVVWidenWOp0BuiltinSet<NAME # "_w", "x",
780                                     [["wv", "w", "wwvu"],
781                                      ["wf", "w", "wweu"]]>;
782}
783