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// h: 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 managed_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 // The different variants of the builtin, parameterised with a type.
149 string TypeRange = type_range;
150
151 // We use each type described in TypeRange and LMUL with prototype to
152 // instantiate a specific element of the set of builtins being defined.
153 // Prototype attribute defines the C/C++ prototype of the builtin. It is a
154 // non-empty sequence of type transformers, the first of which is the return
155 // type of the builtin and the rest are the parameters of the builtin, in
156 // order. For instance if Prototype is "wvv", TypeRange is "si" and LMUL=1, a
157 // first builtin will have type
158 // __rvv_int32m2_t (__rvv_int16m1_t, __rvv_int16m1_t), and the second builtin
159 // will have type __rvv_int64m2_t (__rvv_int32m1_t, __rvv_int32m1_t).
160 string Prototype = prototype;
161
162 // This builtin has a masked form.
163 bit HasMask = true;
164
165 // If HasMask, this flag states that this builtin has a maskedoff operand. It
166 // is always the first operand in builtin and IR intrinsic.
167 bit HasMaskedOffOperand = true;
168
169 // This builtin has a granted vector length parameter in the last position.
170 bit HasVL = true;
171
172 // This builtin supports non-masked function overloading api.
173 // All masked operations support overloading api.
174 bit HasNoMaskedOverloaded = true;
175
176 // Reads or writes "memory" or has other side-effects.
177 bit HasSideEffects = false;
178
179 // This builtin is valid for the given Log2LMULs.
180 list<int> Log2LMUL = [0, 1, 2, 3, -1, -2, -3];
181
182 // Manual code in clang codegen riscv_vector_builtin_cg.inc
183 code ManualCodegen = [{}];
184 code ManualCodegenMask = [{}];
185
186 // When emit the automatic clang codegen, it describes what types we have to use
187 // to obtain the specific LLVM intrinsic. -1 means the return type, otherwise,
188 // k >= 0 meaning the k-th operand (counting from zero) of the codegen'd
189 // parameter of the unmasked version. k can't be the mask operand's position.
190 list<int> IntrinsicTypes = [];
191
192 // If these names are not empty, this is the ID of the LLVM intrinsic
193 // we want to lower to.
194 string IRName = NAME;
195
196 // If HasMask, this is the ID of the LLVM intrinsic we want to lower to.
197 string IRNameMask = NAME #"_mask";
198
199 // If non empty, this is the code emitted in the header, otherwise
200 // an automatic definition in header is emitted.
201 string HeaderCode = "";
202
203 // Sub extension of vector spec. Currently only support Zvamo or Zvlsseg.
204 string RequiredExtension = "";
205
206}
207
208//===----------------------------------------------------------------------===//
209// Basic classes with automatic codegen.
210//===----------------------------------------------------------------------===//
211
212class RVVOutBuiltin<string suffix, string prototype, string type_range>
213 : RVVBuiltin<suffix, prototype, type_range> {
214 let IntrinsicTypes = [-1];
215}
216
217class RVVOp0Builtin<string suffix, string prototype, string type_range>
218 : RVVBuiltin<suffix, prototype, type_range> {
219 let IntrinsicTypes = [0];
220}
221
222class RVVOutOp1Builtin<string suffix, string prototype, string type_range>
223 : RVVBuiltin<suffix, prototype, type_range> {
224 let IntrinsicTypes = [-1, 1];
225}
226
227class RVVOutOp0Op1Builtin<string suffix, string prototype, string type_range>
228 : RVVBuiltin<suffix, prototype, type_range> {
229 let IntrinsicTypes = [-1, 0, 1];
230}
231
232multiclass RVVBuiltinSet<string intrinsic_name, string type_range,
233 list<list<string>> suffixes_prototypes,
234 list<int> intrinsic_types> {
235 let IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask",
236 IntrinsicTypes = intrinsic_types in {
237 foreach s_p = suffixes_prototypes in {
238 let Name = NAME # "_" # s_p[0] in {
239 defvar suffix = s_p[1];
240 defvar prototype = s_p[2];
241 def : RVVBuiltin<suffix, prototype, type_range>;
242 }
243 }
244 }
245}
246
247// IntrinsicTypes is output, op0, op1 [-1, 0, 1]
248multiclass RVVOutOp0Op1BuiltinSet<string intrinsic_name, string type_range,
249 list<list<string>> suffixes_prototypes>
250 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes,
251 [-1, 0, 1]>;
252
253multiclass RVVOutBuiltinSet<string intrinsic_name, string type_range,
254 list<list<string>> suffixes_prototypes>
255 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1]>;
256
257multiclass RVVOp0BuiltinSet<string intrinsic_name, string type_range,
258 list<list<string>> suffixes_prototypes>
259 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0]>;
260
261// IntrinsicTypes is output, op1 [-1, 1]
262multiclass RVVOutOp1BuiltinSet<string intrinsic_name, string type_range,
263 list<list<string>> suffixes_prototypes>
264 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1]>;
265
266multiclass RVVOp0Op1BuiltinSet<string intrinsic_name, string type_range,
267 list<list<string>> suffixes_prototypes>
268 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [0, 1]>;
269
270multiclass RVVOutOp1Op2BuiltinSet<string intrinsic_name, string type_range,
271 list<list<string>> suffixes_prototypes>
272 : RVVBuiltinSet<intrinsic_name, type_range, suffixes_prototypes, [-1, 1, 2]>;
273
274multiclass RVVSignedBinBuiltinSet
275 : RVVOutOp1BuiltinSet<NAME, "csil",
276 [["vv", "v", "vvv"],
277 ["vx", "v", "vve"]]>;
278
279multiclass RVVUnsignedBinBuiltinSet
280 : RVVOutOp1BuiltinSet<NAME, "csil",
281 [["vv", "Uv", "UvUvUv"],
282 ["vx", "Uv", "UvUvUe"]]>;
283
284multiclass RVVIntBinBuiltinSet
285 : RVVSignedBinBuiltinSet,
286 RVVUnsignedBinBuiltinSet;
287
288multiclass RVVSlideOneBuiltinSet
289 : RVVOutOp1BuiltinSet<NAME, "csil",
290 [["vx", "v", "vve"],
291 ["vx", "Uv", "UvUve"]]>;
292
293multiclass RVVSignedShiftBuiltinSet
294 : RVVOutOp1BuiltinSet<NAME, "csil",
295 [["vv", "v", "vvUv"],
296 ["vx", "v", "vvz"]]>;
297
298multiclass RVVUnsignedShiftBuiltinSet
299 : RVVOutOp1BuiltinSet<NAME, "csil",
300 [["vv", "Uv", "UvUvUv"],
301 ["vx", "Uv", "UvUvz"]]>;
302
303multiclass RVVShiftBuiltinSet
304 : RVVSignedShiftBuiltinSet,
305 RVVUnsignedShiftBuiltinSet;
306
307let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
308 multiclass RVVSignedNShiftBuiltinSet
309 : RVVOutOp0Op1BuiltinSet<NAME, "csil",
310 [["wv", "v", "vwUv"],
311 ["wx", "v", "vwz"]]>;
312 multiclass RVVUnsignedNShiftBuiltinSet
313 : RVVOutOp0Op1BuiltinSet<NAME, "csil",
314 [["wv", "Uv", "UvUwUv"],
315 ["wx", "Uv", "UvUwz"]]>;
316}
317
318multiclass RVVCarryinBuiltinSet
319 : RVVOutOp1BuiltinSet<NAME, "csil",
320 [["vvm", "v", "vvvm"],
321 ["vxm", "v", "vvem"],
322 ["vvm", "Uv", "UvUvUvm"],
323 ["vxm", "Uv", "UvUvUem"]]>;
324
325multiclass RVVCarryOutInBuiltinSet<string intrinsic_name>
326 : RVVOp0Op1BuiltinSet<intrinsic_name, "csil",
327 [["vvm", "vm", "mvvm"],
328 ["vxm", "vm", "mvem"],
329 ["vvm", "Uvm", "mUvUvm"],
330 ["vxm", "Uvm", "mUvUem"]]>;
331
332multiclass RVVSignedMaskOutBuiltinSet
333 : RVVOp0Op1BuiltinSet<NAME, "csil",
334 [["vv", "vm", "mvv"],
335 ["vx", "vm", "mve"]]>;
336
337multiclass RVVUnsignedMaskOutBuiltinSet
338 : RVVOp0Op1BuiltinSet<NAME, "csil",
339 [["vv", "Uvm", "mUvUv"],
340 ["vx", "Uvm", "mUvUe"]]>;
341
342multiclass RVVIntMaskOutBuiltinSet
343 : RVVSignedMaskOutBuiltinSet,
344 RVVUnsignedMaskOutBuiltinSet;
345
346class RVVIntExt<string intrinsic_name, string suffix, string prototype,
347 string type_range>
348 : RVVBuiltin<suffix, prototype, type_range> {
349 let IRName = intrinsic_name;
350 let IRNameMask = intrinsic_name # "_mask";
351 let MangledName = NAME;
352 let IntrinsicTypes = [-1, 0];
353}
354
355let HasMaskedOffOperand = false in {
356 multiclass RVVIntTerBuiltinSet {
357 defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
358 [["vv", "v", "vvvv"],
359 ["vx", "v", "vvev"],
360 ["vv", "Uv", "UvUvUvUv"],
361 ["vx", "Uv", "UvUvUeUv"]]>;
362 }
363 multiclass RVVFloatingTerBuiltinSet {
364 defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
365 [["vv", "v", "vvvv"],
366 ["vf", "v", "vvev"]]>;
367 }
368}
369
370let HasMaskedOffOperand = false, Log2LMUL = [-1, 0, 1, 2] in {
371 multiclass RVVFloatingWidenTerBuiltinSet {
372 defm "" : RVVOutOp1Op2BuiltinSet<NAME, "f",
373 [["vv", "w", "wwvv"],
374 ["vf", "w", "wwev"]]>;
375 }
376}
377
378multiclass RVVFloatingBinBuiltinSet
379 : RVVOutOp1BuiltinSet<NAME, "fd",
380 [["vv", "v", "vvv"],
381 ["vf", "v", "vve"]]>;
382
383multiclass RVVFloatingBinVFBuiltinSet
384 : RVVOutOp1BuiltinSet<NAME, "fd",
385 [["vf", "v", "vve"]]>;
386
387multiclass RVVFloatingMaskOutBuiltinSet
388 : RVVOp0Op1BuiltinSet<NAME, "fd",
389 [["vv", "vm", "mvv"],
390 ["vf", "vm", "mve"]]>;
391
392multiclass RVVFloatingMaskOutVFBuiltinSet
393 : RVVOp0Op1BuiltinSet<NAME, "fd",
394 [["vf", "vm", "mve"]]>;
395
396class RVVMaskBinBuiltin : RVVOutBuiltin<"m", "mmm", "c"> {
397 let Name = NAME # "_mm";
398 let HasMask = false;
399}
400
401class RVVMaskUnaryBuiltin : RVVOutBuiltin<"m", "mm", "c"> {
402 let Name = NAME # "_m";
403}
404
405class RVVMaskNullaryBuiltin : RVVOutBuiltin<"m", "m", "c"> {
406 let Name = NAME # "_m";
407 let HasMask = false;
408 let HasNoMaskedOverloaded = false;
409}
410
411class RVVMaskOp0Builtin<string prototype> : RVVOp0Builtin<"m", prototype, "c"> {
412 let Name = NAME # "_m";
413 let HasMaskedOffOperand = false;
414}
415
416let HasMaskedOffOperand = false in {
417 multiclass RVVSlideBuiltinSet {
418 defm "" : RVVOutBuiltinSet<NAME, "csilfd",
419 [["vx","v", "vvvz"]]>;
420 defm "" : RVVOutBuiltinSet<NAME, "csil",
421 [["vx","Uv", "UvUvUvz"]]>;
422 }
423}
424
425class RVVFloatingUnaryBuiltin<string builtin_suffix, string ir_suffix,
426 string prototype>
427 : RVVOutBuiltin<ir_suffix, prototype, "fd"> {
428 let Name = NAME # "_" # builtin_suffix;
429}
430
431class RVVFloatingUnaryVVBuiltin : RVVFloatingUnaryBuiltin<"v", "v", "vv">;
432
433class RVVConvBuiltin<string suffix, string prototype, string type_range,
434 string mangled_name>
435 : RVVBuiltin<suffix, prototype, type_range> {
436 let IntrinsicTypes = [-1, 0];
437 let MangledName = mangled_name;
438}
439
440class RVVConvToSignedBuiltin<string mangled_name>
441 : RVVConvBuiltin<"Iv", "Ivv", "fd", mangled_name>;
442
443class RVVConvToUnsignedBuiltin<string mangled_name>
444 : RVVConvBuiltin<"Uv", "Uvv", "fd", mangled_name>;
445
446class RVVConvToWidenSignedBuiltin<string mangled_name>
447 : RVVConvBuiltin<"Iw", "Iwv", "f", mangled_name>;
448
449class RVVConvToWidenUnsignedBuiltin<string mangled_name>
450 : RVVConvBuiltin<"Uw", "Uwv", "f", mangled_name>;
451
452class RVVConvToNarrowingSignedBuiltin<string mangled_name>
453 : RVVConvBuiltin<"Iv", "IvFw", "si", mangled_name>;
454
455class RVVConvToNarrowingUnsignedBuiltin<string mangled_name>
456 : RVVConvBuiltin<"Uv", "UvFw", "si", mangled_name>;
457
458let HasMaskedOffOperand = false in {
459 multiclass RVVSignedReductionBuiltin {
460 defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
461 [["vs", "vSv", "SvSvvSv"]]>;
462 }
463 multiclass RVVUnsignedReductionBuiltin {
464 defm "" : RVVOutOp1BuiltinSet<NAME, "csil",
465 [["vs", "UvUSv", "USvUSvUvUSv"]]>;
466 }
467 multiclass RVVFloatingReductionBuiltin {
468 defm "" : RVVOutOp1BuiltinSet<NAME, "fd",
469 [["vs", "vSv", "SvSvvSv"]]>;
470 }
471 multiclass RVVFloatingWidenReductionBuiltin {
472 defm "" : RVVOutOp1BuiltinSet<NAME, "f",
473 [["vs", "vSw", "SwSwvSw"]]>;
474 }
475}
476
477multiclass RVVIntReductionBuiltinSet
478 : RVVSignedReductionBuiltin,
479 RVVUnsignedReductionBuiltin;
480
481// For widen operation which has different mangling name.
482multiclass RVVWidenBuiltinSet<string intrinsic_name, string type_range,
483 list<list<string>> suffixes_prototypes> {
484 let Log2LMUL = [-3, -2, -1, 0, 1, 2],
485 IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask" in {
486 foreach s_p = suffixes_prototypes in {
487 let Name = NAME # "_" # s_p[0],
488 MangledName = NAME # "_" # s_p[0] in {
489 defvar suffix = s_p[1];
490 defvar prototype = s_p[2];
491 def : RVVOutOp0Op1Builtin<suffix, prototype, type_range>;
492 }
493 }
494 }
495}
496
497// For widen operation with widen operand which has different mangling name.
498multiclass RVVWidenWOp0BuiltinSet<string intrinsic_name, string type_range,
499 list<list<string>> suffixes_prototypes> {
500 let Log2LMUL = [-3, -2, -1, 0, 1, 2],
501 IRName = intrinsic_name, IRNameMask = intrinsic_name # "_mask" in {
502 foreach s_p = suffixes_prototypes in {
503 let Name = NAME # "_" # s_p[0],
504 MangledName = NAME # "_" # s_p[0] in {
505 defvar suffix = s_p[1];
506 defvar prototype = s_p[2];
507 def : RVVOutOp1Builtin<suffix, prototype, type_range>;
508 }
509 }
510 }
511}
512
513multiclass RVVSignedWidenBinBuiltinSet
514 : RVVWidenBuiltinSet<NAME, "csi",
515 [["vv", "w", "wvv"],
516 ["vx", "w", "wve"]]>;
517
518multiclass RVVSignedWidenOp0BinBuiltinSet
519 : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
520 [["wv", "w", "wwv"],
521 ["wx", "w", "wwe"]]>;
522
523multiclass RVVUnsignedWidenBinBuiltinSet
524 : RVVWidenBuiltinSet<NAME, "csi",
525 [["vv", "Uw", "UwUvUv"],
526 ["vx", "Uw", "UwUvUe"]]>;
527
528multiclass RVVUnsignedWidenOp0BinBuiltinSet
529 : RVVWidenWOp0BuiltinSet<NAME # "_w", "csi",
530 [["wv", "Uw", "UwUwUv"],
531 ["wx", "Uw", "UwUwUe"]]>;
532
533multiclass RVVFloatingWidenBinBuiltinSet
534 : RVVWidenBuiltinSet<NAME, "f",
535 [["vv", "w", "wvv"],
536 ["vf", "w", "wve"]]>;
537
538multiclass RVVFloatingWidenOp0BinBuiltinSet
539 : RVVWidenWOp0BuiltinSet<NAME # "_w", "f",
540 [["wv", "w", "wwv"],
541 ["wf", "w", "wwe"]]>;
542
543defvar TypeList = ["c","s","i","l","f","d"];
544defvar EEWList = [["8", "(Log2EEW:3)"],
545 ["16", "(Log2EEW:4)"],
546 ["32", "(Log2EEW:5)"],
547 ["64", "(Log2EEW:6)"]];
548
549class IsFloat<string type> {
550 bit val = !or(!eq(type, "h"), !eq(type, "f"), !eq(type, "d"));
551}
552
553let HasNoMaskedOverloaded = false,
554 ManualCodegen = [{
555 IntrinsicTypes = {ResultType, Ops[1]->getType()};
556 Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
557 }],
558 ManualCodegenMask= [{
559 // Move mask to right before vl.
560 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
561 IntrinsicTypes = {ResultType, Ops[3]->getType()};
562 Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
563 }] in {
564 class RVVVLEMaskBuiltin : RVVBuiltin<"m", "mPCUe", "c"> {
565 let Name = "vle1_v";
566 let IRName = "vle1";
567 let HasMask = false;
568 }
569 multiclass RVVVLEBuiltin<list<string> types> {
570 let Name = NAME # "_v",
571 IRName = "vle",
572 IRNameMask ="vle_mask" in {
573 foreach type = types in {
574 def : RVVBuiltin<"v", "vPCe", type>;
575 if !not(IsFloat<type>.val) then {
576 def : RVVBuiltin<"Uv", "UvPCUe", type>;
577 }
578 }
579 }
580 }
581}
582
583multiclass RVVVLEFFBuiltin<list<string> types> {
584 let Name = NAME # "_v",
585 IRName = "vleff",
586 IRNameMask = "vleff_mask",
587 HasNoMaskedOverloaded = false,
588 ManualCodegen = [{
589 {
590 IntrinsicTypes = {ResultType, Ops[2]->getType()};
591 Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
592 Value *NewVL = Ops[1];
593 Ops.erase(Ops.begin() + 1);
594 llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
595 llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
596 llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
597 // Store new_vl.
598 clang::CharUnits Align =
599 CGM.getNaturalTypeAlignment(getContext().getSizeType());
600 Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {1}),
601 Address(NewVL, Align));
602 return V;
603 }
604 }],
605 ManualCodegenMask = [{
606 {
607 // Move mask to right before vl.
608 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
609 IntrinsicTypes = {ResultType, Ops[4]->getType()};
610 Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
611 Value *NewVL = Ops[2];
612 Ops.erase(Ops.begin() + 2);
613 llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes);
614 llvm::Value *LoadValue = Builder.CreateCall(F, Ops, "");
615 llvm::Value *V = Builder.CreateExtractValue(LoadValue, {0});
616 // Store new_vl.
617 clang::CharUnits Align =
618 CGM.getNaturalTypeAlignment(getContext().getSizeType());
619 Builder.CreateStore(Builder.CreateExtractValue(LoadValue, {1}),
620 Address(NewVL, Align));
621 return V;
622 }
623 }] in {
624 foreach type = types in {
625 def : RVVBuiltin<"v", "vPCePz", type>;
626 // Skip floating types for unsigned versions.
627 if !not(IsFloat<type>.val) then {
628 def : RVVBuiltin<"Uv", "UvPCUePz", type>;
629 }
630 }
631 }
632}
633
634multiclass RVVVLSEBuiltin<list<string> types> {
635 let Name = NAME # "_v",
636 IRName = "vlse",
637 IRNameMask ="vlse_mask",
638 HasNoMaskedOverloaded = false,
639 ManualCodegen = [{
640 IntrinsicTypes = {ResultType, Ops[2]->getType()};
641 Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
642 }],
643 ManualCodegenMask= [{
644 // Move mask to right before vl.
645 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
646 IntrinsicTypes = {ResultType, Ops[4]->getType()};
647 Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
648 }] in {
649 foreach type = types in {
650 def : RVVBuiltin<"v", "vPCet", type>;
651 if !not(IsFloat<type>.val) then {
652 def : RVVBuiltin<"Uv", "UvPCUet", type>;
653 }
654 }
655 }
656}
657
658multiclass RVVIndexedLoad<string op> {
659 let ManualCodegen = [{
660 IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[2]->getType()};
661 Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
662 }],
663 ManualCodegenMask = [{
664 // Move mask to right before vl.
665 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
666 IntrinsicTypes = {ResultType, Ops[2]->getType(), Ops[4]->getType()};
667 Ops[1] = Builder.CreateBitCast(Ops[1], ResultType->getPointerTo());
668 }] in {
669 foreach type = TypeList in {
670 foreach eew_list = EEWList in {
671 defvar eew = eew_list[0];
672 defvar eew_type = eew_list[1];
673 let Name = op # eew # "_v", IRName = op, IRNameMask = op # "_mask" in {
674 def: RVVBuiltin<"v", "vPCe" # eew_type # "Uv", type>;
675 if !not(IsFloat<type>.val) then {
676 def: RVVBuiltin<"Uv", "UvPCUe" # eew_type # "Uv", type>;
677 }
678 }
679 }
680 }
681 }
682}
683
684let HasMaskedOffOperand = false,
685 ManualCodegen = [{
686 // Builtin: (ptr, value, vl). Intrinsic: (value, ptr, vl)
687 std::swap(Ops[0], Ops[1]);
688 Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
689 IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType()};
690 }],
691 ManualCodegenMask= [{
692 // Builtin: (mask, ptr, value, vl). Intrinsic: (value, ptr, mask, vl)
693 std::swap(Ops[0], Ops[2]);
694 Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
695 IntrinsicTypes = {Ops[0]->getType(), Ops[3]->getType()};
696 }] in {
697 class RVVVSEMaskBuiltin : RVVBuiltin<"m", "0PUem", "c"> {
698 let Name = "vse1_v";
699 let IRName = "vse1";
700 let HasMask = false;
701 }
702 multiclass RVVVSEBuiltin<list<string> types> {
703 let Name = NAME # "_v",
704 IRName = "vse",
705 IRNameMask = "vse_mask" in {
706 foreach type = types in {
707 def : RVVBuiltin<"v", "0Pev", type>;
708 if !not(IsFloat<type>.val) then {
709 def : RVVBuiltin<"Uv", "0PUeUv", type>;
710 }
711 }
712 }
713 }
714}
715
716multiclass RVVVSSEBuiltin<list<string> types> {
717 let Name = NAME # "_v",
718 IRName = "vsse",
719 IRNameMask = "vsse_mask",
720 HasMaskedOffOperand = false,
721 ManualCodegen = [{
722 // Builtin: (ptr, stride, value, vl). Intrinsic: (value, ptr, stride, vl)
723 std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
724 Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
725 IntrinsicTypes = {Ops[0]->getType(), Ops[3]->getType()};
726 }],
727 ManualCodegenMask= [{
728 // Builtin: (mask, ptr, stride, value, vl). Intrinsic: (value, ptr, stride, mask, vl)
729 std::swap(Ops[0], Ops[3]);
730 Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
731 IntrinsicTypes = {Ops[0]->getType(), Ops[4]->getType()};
732 }] in {
733 foreach type = types in {
734 def : RVVBuiltin<"v", "0Petv", type>;
735 if !not(IsFloat<type>.val) then {
736 def : RVVBuiltin<"Uv", "0PUetUv", type>;
737 }
738 }
739 }
740}
741
742multiclass RVVIndexedStore<string op> {
743 let HasMaskedOffOperand = false,
744 ManualCodegen = [{
745 // Builtin: (ptr, index, value, vl). Intrinsic: (value, ptr, index, vl)
746 std::rotate(Ops.begin(), Ops.begin() + 2, Ops.begin() + 3);
747 Ops[1] = Builder.CreateBitCast(Ops[1],Ops[0]->getType()->getPointerTo());
748 IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType(), Ops[3]->getType()};
749 }],
750 ManualCodegenMask= [{
751 // Builtin: (mask, ptr, index, value, vl). Intrinsic: (value, ptr, index, mask, vl)
752 std::swap(Ops[0], Ops[3]);
753 Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType()->getPointerTo());
754 IntrinsicTypes = {Ops[0]->getType(), Ops[2]->getType(), Ops[4]->getType()};
755 }] in {
756 foreach type = TypeList in {
757 foreach eew_list = EEWList in {
758 defvar eew = eew_list[0];
759 defvar eew_type = eew_list[1];
760 let Name = op # eew # "_v", IRName = op, IRNameMask = op # "_mask" in {
761 def : RVVBuiltin<"v", "0Pe" # eew_type # "Uvv", type>;
762 if !not(IsFloat<type>.val) then {
763 def : RVVBuiltin<"Uv", "0PUe" # eew_type # "UvUv", type>;
764 }
765 }
766 }
767 }
768 }
769}
770
771multiclass RVVAMOBuiltinSet<bit has_signed = false, bit has_unsigned = false,
772 bit has_fp = false> {
773 defvar type_list = !if(has_fp, ["i","l","f","d"], ["i","l"]);
774 foreach type = type_list in
775 foreach eew_list = EEWList in {
776 defvar eew = eew_list[0];
777 defvar eew_index = eew_list[1];
778 let Name = NAME # "ei" # eew # "_" # "v",
779 IRName = NAME,
780 IRNameMask = NAME # "_mask",
781 HasMaskedOffOperand = false,
782 ManualCodegen = [{
783 // base, bindex, value, vl
784 IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
785 Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
786 }],
787 ManualCodegenMask = [{
788 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
789 IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[4]->getType()};
790 Ops[0] = Builder.CreateBitCast(Ops[0], ResultType->getPointerTo());
791 }] in {
792 if has_signed then
793 def : RVVBuiltin<"v", "vPe" # eew_index # "Uvv", type>;
794 if !and(!not(IsFloat<type>.val), has_unsigned) then
795 def : RVVBuiltin<"Uv", "UvPUe" # eew_index # "UvUv", type>;
796 }
797 }
798}
799
800multiclass RVVPseudoUnaryBuiltin<string IR, string type_range> {
801 let Name = NAME,
802 IRName = IR,
803 IRNameMask = IR # "_mask",
804 ManualCodegen = [{
805 {
806 // op1, vl
807 IntrinsicTypes = {ResultType,
808 cast<llvm::VectorType>(ResultType)->getElementType(),
809 Ops[1]->getType()};
810 Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[1]));
811 break;
812 }
813 }],
814 ManualCodegenMask = [{
815 {
816 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
817 // maskedoff, op1, mask, vl
818 IntrinsicTypes = {ResultType,
819 cast<llvm::VectorType>(ResultType)->getElementType(),
820 Ops[3]->getType()};
821 Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[1]));
822 break;
823 }
824 }] in {
825 def : RVVBuiltin<"v", "vv", type_range>;
826 }
827}
828
829multiclass RVVPseudoVNotBuiltin<string IR, string type_range> {
830 let Name = NAME,
831 IRName = IR,
832 IRNameMask = IR # "_mask",
833 ManualCodegen = [{
834 {
835 // op1, vl
836 IntrinsicTypes = {ResultType,
837 cast<llvm::VectorType>(ResultType)->getElementType(),
838 Ops[1]->getType()};
839 Ops.insert(Ops.begin() + 1,
840 llvm::Constant::getAllOnesValue(IntrinsicTypes[1]));
841 break;
842 }
843 }],
844 ManualCodegenMask = [{
845 {
846 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
847 // maskedoff, op1, mask, vl
848 IntrinsicTypes = {ResultType,
849 cast<llvm::VectorType>(ResultType)->getElementType(),
850 Ops[3]->getType()};
851 Ops.insert(Ops.begin() + 2,
852 llvm::Constant::getAllOnesValue(IntrinsicTypes[1]));
853 break;
854 }
855 }] in {
856 def : RVVBuiltin<"v", "vv", type_range>;
857 def : RVVBuiltin<"Uv", "UvUv", type_range>;
858 }
859}
860
861multiclass RVVPseudoMaskBuiltin<string IR, string type_range> {
862 let Name = NAME,
863 IRName = IR,
864 HasMask = false,
865 ManualCodegen = [{
866 {
867 // op1, vl
868 IntrinsicTypes = {ResultType,
869 Ops[1]->getType()};
870 Ops.insert(Ops.begin() + 1, Ops[0]);
871 break;
872 }
873 }] in {
874 def : RVVBuiltin<"m", "mm", type_range>;
875 }
876}
877
878multiclass RVVPseudoVFUnaryBuiltin<string IR, string type_range> {
879 let Name = NAME,
880 IRName = IR,
881 IRNameMask = IR # "_mask",
882 ManualCodegen = [{
883 {
884 // op1, vl
885 IntrinsicTypes = {ResultType,
886 Ops[0]->getType(), Ops[1]->getType()};
887 Ops.insert(Ops.begin() + 1, Ops[0]);
888 break;
889 }
890 }],
891 ManualCodegenMask = [{
892 {
893 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
894 // maskedoff, op1, mask, vl
895 IntrinsicTypes = {ResultType,
896 Ops[1]->getType(),
897 Ops[3]->getType()};
898 Ops.insert(Ops.begin() + 2, Ops[1]);
899 break;
900 }
901 }] in {
902 def : RVVBuiltin<"v", "vv", type_range>;
903 }
904}
905
906multiclass RVVPseudoVWCVTBuiltin<string IR, string MName, string type_range,
907 list<list<string>> suffixes_prototypes> {
908 let Name = NAME,
909 MangledName = MName,
910 IRName = IR,
911 IRNameMask = IR # "_mask",
912 ManualCodegen = [{
913 {
914 // op1, vl
915 IntrinsicTypes = {ResultType,
916 Ops[0]->getType(),
917 cast<llvm::VectorType>(Ops[0]->getType())->getElementType(),
918 Ops[1]->getType()};
919 Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[2]));
920 break;
921 }
922 }],
923 ManualCodegenMask = [{
924 {
925 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
926 // maskedoff, op1, mask, vl
927 IntrinsicTypes = {ResultType,
928 Ops[1]->getType(),
929 cast<llvm::VectorType>(Ops[1]->getType())->getElementType(),
930 Ops[3]->getType()};
931 Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[2]));
932 break;
933 }
934 }] in {
935 foreach s_p = suffixes_prototypes in {
936 def : RVVBuiltin<s_p[0], s_p[1], type_range>;
937 }
938 }
939}
940
941multiclass RVVPseudoVNCVTBuiltin<string IR, string MName, string type_range,
942 list<list<string>> suffixes_prototypes> {
943 let Name = NAME,
944 MangledName = MName,
945 IRName = IR,
946 IRNameMask = IR # "_mask",
947 ManualCodegen = [{
948 {
949 // op1, vl
950 IntrinsicTypes = {ResultType,
951 Ops[0]->getType(),
952 Ops[1]->getType(),
953 Ops[1]->getType()};
954 Ops.insert(Ops.begin() + 1, llvm::Constant::getNullValue(IntrinsicTypes[2]));
955 break;
956 }
957 }],
958 ManualCodegenMask = [{
959 {
960 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.end() - 1);
961 // maskedoff, op1, mask, vl
962 IntrinsicTypes = {ResultType,
963 Ops[1]->getType(),
964 Ops[3]->getType(),
965 Ops[3]->getType()};
966 Ops.insert(Ops.begin() + 2, llvm::Constant::getNullValue(IntrinsicTypes[2]));
967 break;
968 }
969 }] in {
970 foreach s_p = suffixes_prototypes in {
971 def : RVVBuiltin<s_p[0], s_p[1], type_range>;
972 }
973 }
974}
975
976// 6. Configuration-Setting Instructions
977// 6.1. vsetvli/vsetvl instructions
978let HasVL = false,
979 HasMask = false,
980 HasSideEffects = true,
981 Log2LMUL = [0],
982 ManualCodegen = [{IntrinsicTypes = {ResultType};}] in // Set XLEN type
983{
984 // vsetvl is a macro because for it require constant integers in SEW and LMUL.
985 let HeaderCode =
986[{
987#define vsetvl_e8mf8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 5)
988#define vsetvl_e8mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 6)
989#define vsetvl_e8mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 7)
990#define vsetvl_e8m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 0)
991#define vsetvl_e8m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 1)
992#define vsetvl_e8m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 2)
993#define vsetvl_e8m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 3)
994
995#define vsetvl_e16mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 6)
996#define vsetvl_e16mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 7)
997#define vsetvl_e16m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 0)
998#define vsetvl_e16m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 1)
999#define vsetvl_e16m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 2)
1000#define vsetvl_e16m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 3)
1001
1002#define vsetvl_e32mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 7)
1003#define vsetvl_e32m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 0)
1004#define vsetvl_e32m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 1)
1005#define vsetvl_e32m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 2)
1006#define vsetvl_e32m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 3)
1007
1008#define vsetvl_e64m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 0)
1009#define vsetvl_e64m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 1)
1010#define vsetvl_e64m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 2)
1011#define vsetvl_e64m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 3)
1012
1013}] in
1014 def vsetvli : RVVBuiltin<"", "zzKzKz", "i">;
1015
1016 let HeaderCode =
1017[{
1018#define vsetvlmax_e8mf8() __builtin_rvv_vsetvlimax(0, 5)
1019#define vsetvlmax_e8mf4() __builtin_rvv_vsetvlimax(0, 6)
1020#define vsetvlmax_e8mf2() __builtin_rvv_vsetvlimax(0, 7)
1021#define vsetvlmax_e8m1() __builtin_rvv_vsetvlimax(0, 0)
1022#define vsetvlmax_e8m2() __builtin_rvv_vsetvlimax(0, 1)
1023#define vsetvlmax_e8m4() __builtin_rvv_vsetvlimax(0, 2)
1024#define vsetvlmax_e8m8() __builtin_rvv_vsetvlimax(0, 3)
1025
1026#define vsetvlmax_e16mf4() __builtin_rvv_vsetvlimax(1, 6)
1027#define vsetvlmax_e16mf2() __builtin_rvv_vsetvlimax(1, 7)
1028#define vsetvlmax_e16m1() __builtin_rvv_vsetvlimax(1, 0)
1029#define vsetvlmax_e16m2() __builtin_rvv_vsetvlimax(1, 1)
1030#define vsetvlmax_e16m4() __builtin_rvv_vsetvlimax(1, 2)
1031#define vsetvlmax_e16m8() __builtin_rvv_vsetvlimax(1, 3)
1032
1033#define vsetvlmax_e32mf2() __builtin_rvv_vsetvlimax(2, 7)
1034#define vsetvlmax_e32m1() __builtin_rvv_vsetvlimax(2, 0)
1035#define vsetvlmax_e32m2() __builtin_rvv_vsetvlimax(2, 1)
1036#define vsetvlmax_e32m4() __builtin_rvv_vsetvlimax(2, 2)
1037#define vsetvlmax_e32m8() __builtin_rvv_vsetvlimax(2, 3)
1038
1039#define vsetvlmax_e64m1() __builtin_rvv_vsetvlimax(3, 0)
1040#define vsetvlmax_e64m2() __builtin_rvv_vsetvlimax(3, 1)
1041#define vsetvlmax_e64m4() __builtin_rvv_vsetvlimax(3, 2)
1042#define vsetvlmax_e64m8() __builtin_rvv_vsetvlimax(3, 3)
1043
1044}] in
1045 def vsetvlimax : RVVBuiltin<"", "zKzKz", "i">;
1046}
1047
1048// 7. Vector Loads and Stores
1049// 7.4. Vector Unit-Stride Instructions
1050def vle1: RVVVLEMaskBuiltin;
1051defm vle8: RVVVLEBuiltin<["c"]>;
1052defm vle16: RVVVLEBuiltin<["s"]>;
1053defm vle32: RVVVLEBuiltin<["i","f"]>;
1054defm vle64: RVVVLEBuiltin<["l","d"]>;
1055
1056def vse1 : RVVVSEMaskBuiltin;
1057defm vse8 : RVVVSEBuiltin<["c"]>;
1058defm vse16: RVVVSEBuiltin<["s"]>;
1059defm vse32: RVVVSEBuiltin<["i","f"]>;
1060defm vse64: RVVVSEBuiltin<["l","d"]>;
1061
1062// 7.5. Vector Strided Instructions
1063defm vlse8: RVVVLSEBuiltin<["c"]>;
1064defm vlse16: RVVVLSEBuiltin<["s"]>;
1065defm vlse32: RVVVLSEBuiltin<["i","f"]>;
1066defm vlse64: RVVVLSEBuiltin<["l","d"]>;
1067
1068defm vsse8 : RVVVSSEBuiltin<["c"]>;
1069defm vsse16: RVVVSSEBuiltin<["s"]>;
1070defm vsse32: RVVVSSEBuiltin<["i","f"]>;
1071defm vsse64: RVVVSSEBuiltin<["l","d"]>;
1072
1073// 7.6. Vector Indexed Instructions
1074defm : RVVIndexedLoad<"vluxei">;
1075defm : RVVIndexedLoad<"vloxei">;
1076
1077defm : RVVIndexedStore<"vsuxei">;
1078defm : RVVIndexedStore<"vsoxei">;
1079
1080// 7.7. Unit-stride Fault-Only-First Loads
1081defm vle8ff: RVVVLEFFBuiltin<["c"]>;
1082defm vle16ff: RVVVLEFFBuiltin<["s"]>;
1083defm vle32ff: RVVVLEFFBuiltin<["i", "f"]>;
1084defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>;
1085
1086// 8. Vector AMO Operations
1087let RequiredExtension = "Zvamo" in {
1088defm vamoswap : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true, /* hasFP */ true>;
1089defm vamoadd : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1090defm vamoxor : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1091defm vamoand : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1092defm vamoor : RVVAMOBuiltinSet< /* hasSigned */ true, /* hasUnsigned */ true>;
1093defm vamomin : RVVAMOBuiltinSet< /* hasSigned */ true>;
1094defm vamomax : RVVAMOBuiltinSet< /* hasSigned */ true>;
1095defm vamominu : RVVAMOBuiltinSet< /* hasSigned */ false, /* hasUnsigned */ true>;
1096defm vamomaxu : RVVAMOBuiltinSet< /* hasSigned */ false, /* hasUnsigned */ true>;
1097}
1098
1099// 12. Vector Integer Arithmetic Instructions
1100// 12.1. Vector Single-Width Integer Add and Subtract
1101defm vadd : RVVIntBinBuiltinSet;
1102defm vsub : RVVIntBinBuiltinSet;
1103defm vrsub : RVVOutOp1BuiltinSet<"vrsub", "csil",
1104 [["vx", "v", "vve"],
1105 ["vx", "Uv", "UvUvUe"]]>;
1106defm vneg_v : RVVPseudoUnaryBuiltin<"vrsub", "csil">;
1107
1108// 12.2. Vector Widening Integer Add/Subtract
1109// Widening unsigned integer add/subtract, 2*SEW = SEW +/- SEW
1110defm vwaddu : RVVUnsignedWidenBinBuiltinSet;
1111defm vwsubu : RVVUnsignedWidenBinBuiltinSet;
1112// Widening signed integer add/subtract, 2*SEW = SEW +/- SEW
1113defm vwadd : RVVSignedWidenBinBuiltinSet;
1114defm vwsub : RVVSignedWidenBinBuiltinSet;
1115// Widening unsigned integer add/subtract, 2*SEW = 2*SEW +/- SEW
1116defm vwaddu : RVVUnsignedWidenOp0BinBuiltinSet;
1117defm vwsubu : RVVUnsignedWidenOp0BinBuiltinSet;
1118// Widening signed integer add/subtract, 2*SEW = 2*SEW +/- SEW
1119defm vwadd : RVVSignedWidenOp0BinBuiltinSet;
1120defm vwsub : RVVSignedWidenOp0BinBuiltinSet;
1121defm vwcvtu_x_x_v : RVVPseudoVWCVTBuiltin<"vwaddu", "vwcvtu_x", "csi",
1122 [["Uw", "UwUv"]]>;
1123defm vwcvt_x_x_v : RVVPseudoVWCVTBuiltin<"vwadd", "vwcvt_x", "csi",
1124 [["w", "wv"]]>;
1125
1126// 12.3. Vector Integer Extension
1127let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1128 def vsext_vf2 : RVVIntExt<"vsext", "w", "wv", "csi">;
1129 def vzext_vf2 : RVVIntExt<"vzext", "Uw", "UwUv", "csi">;
1130}
1131let Log2LMUL = [-3, -2, -1, 0, 1] in {
1132 def vsext_vf4 : RVVIntExt<"vsext", "q", "qv", "cs">;
1133 def vzext_vf4 : RVVIntExt<"vzext", "Uq", "UqUv", "cs">;
1134}
1135let Log2LMUL = [-3, -2, -1, 0] in {
1136 def vsext_vf8 : RVVIntExt<"vsext", "o", "ov", "c">;
1137 def vzext_vf8 : RVVIntExt<"vzext", "Uo", "UoUv", "c">;
1138}
1139
1140// 12.4. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
1141let HasMask = false in {
1142 defm vadc : RVVCarryinBuiltinSet;
1143 defm vmadc : RVVCarryOutInBuiltinSet<"vmadc_carry_in">;
1144 defm vmadc : RVVIntMaskOutBuiltinSet;
1145 defm vsbc : RVVCarryinBuiltinSet;
1146 defm vmsbc : RVVCarryOutInBuiltinSet<"vmsbc_borrow_in">;
1147 defm vmsbc : RVVIntMaskOutBuiltinSet;
1148}
1149
1150// 12.5. Vector Bitwise Logical Instructions
1151defm vand : RVVIntBinBuiltinSet;
1152defm vxor : RVVIntBinBuiltinSet;
1153defm vor : RVVIntBinBuiltinSet;
1154defm vnot_v : RVVPseudoVNotBuiltin<"vxor", "csil">;
1155
1156// 12.6. Vector Single-Width Bit Shift Instructions
1157defm vsll : RVVShiftBuiltinSet;
1158defm vsrl : RVVUnsignedShiftBuiltinSet;
1159defm vsra : RVVSignedShiftBuiltinSet;
1160
1161// 12.7. Vector Narrowing Integer Right Shift Instructions
1162defm vnsrl : RVVUnsignedNShiftBuiltinSet;
1163defm vnsra : RVVSignedNShiftBuiltinSet;
1164defm vncvt_x_x_w : RVVPseudoVNCVTBuiltin<"vnsrl", "vncvt_x", "csi",
1165 [["v", "vw"],
1166 ["Uv", "UvUw"]]>;
1167
1168// 12.8. Vector Integer Comparison Instructions
1169defm vmseq : RVVIntMaskOutBuiltinSet;
1170defm vmsne : RVVIntMaskOutBuiltinSet;
1171defm vmsltu : RVVUnsignedMaskOutBuiltinSet;
1172defm vmslt : RVVSignedMaskOutBuiltinSet;
1173defm vmsleu : RVVUnsignedMaskOutBuiltinSet;
1174defm vmsle : RVVSignedMaskOutBuiltinSet;
1175defm vmsgtu : RVVUnsignedMaskOutBuiltinSet;
1176defm vmsgt : RVVSignedMaskOutBuiltinSet;
1177defm vmsgeu : RVVUnsignedMaskOutBuiltinSet;
1178defm vmsge : RVVSignedMaskOutBuiltinSet;
1179
1180// 12.9. Vector Integer Min/Max Instructions
1181defm vminu : RVVUnsignedBinBuiltinSet;
1182defm vmin : RVVSignedBinBuiltinSet;
1183defm vmaxu : RVVUnsignedBinBuiltinSet;
1184defm vmax : RVVSignedBinBuiltinSet;
1185
1186// 12.10. Vector Single-Width Integer Multiply Instructions
1187defm vmul : RVVIntBinBuiltinSet;
1188defm vmulh : RVVSignedBinBuiltinSet;
1189defm vmulhu : RVVUnsignedBinBuiltinSet;
1190defm vmulhsu : RVVOutOp1BuiltinSet<"vmulhsu", "csil",
1191 [["vv", "v", "vvUv"],
1192 ["vx", "v", "vvUe"]]>;
1193
1194// 12.11. Vector Integer Divide Instructions
1195defm vdivu : RVVUnsignedBinBuiltinSet;
1196defm vdiv : RVVSignedBinBuiltinSet;
1197defm vremu : RVVUnsignedBinBuiltinSet;
1198defm vrem : RVVSignedBinBuiltinSet;
1199
1200// 12.12. Vector Widening Integer Multiply Instructions
1201let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1202defm vwmul : RVVOutOp0Op1BuiltinSet<"vwmul", "csi",
1203 [["vv", "w", "wvv"],
1204 ["vx", "w", "wve"]]>;
1205defm vwmulu : RVVOutOp0Op1BuiltinSet<"vwmulu", "csi",
1206 [["vv", "Uw", "UwUvUv"],
1207 ["vx", "Uw", "UwUvUe"]]>;
1208defm vwmulsu : RVVOutOp0Op1BuiltinSet<"vwmulsu", "csi",
1209 [["vv", "w", "wvUv"],
1210 ["vx", "w", "wvUe"]]>;
1211}
1212
1213// 12.13. Vector Single-Width Integer Multiply-Add Instructions
1214defm vmacc : RVVIntTerBuiltinSet;
1215defm vnmsac : RVVIntTerBuiltinSet;
1216defm vmadd : RVVIntTerBuiltinSet;
1217defm vnmsub : RVVIntTerBuiltinSet;
1218
1219// 12.14. Vector Widening Integer Multiply-Add Instructions
1220let HasMaskedOffOperand = false,
1221 Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1222defm vwmaccu : RVVOutOp1Op2BuiltinSet<"vwmaccu", "csi",
1223 [["vv", "Uw", "UwUwUvUv"],
1224 ["vx", "Uw", "UwUwUeUv"]]>;
1225defm vwmacc : RVVOutOp1Op2BuiltinSet<"vwmacc", "csi",
1226 [["vv", "w", "wwvv"],
1227 ["vx", "w", "wwev"]]>;
1228defm vwmaccsu : RVVOutOp1Op2BuiltinSet<"vwmaccsu", "csi",
1229 [["vv", "w", "wwvUv"],
1230 ["vx", "w", "wweUv"]]>;
1231defm vwmaccus : RVVOutOp1Op2BuiltinSet<"vwmaccus", "csi",
1232 [["vx", "w", "wwUev"]]>;
1233}
1234
1235// 12.15. Vector Integer Merge Instructions
1236// C/C++ Operand: (mask, op1, op2, vl), Intrinsic: (op1, op2, mask, vl)
1237let HasMask = false,
1238 ManualCodegen = [{
1239 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
1240 IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
1241 }] in {
1242 defm vmerge : RVVOutOp1BuiltinSet<"vmerge", "csil",
1243 [["vvm", "v", "vmvv"],
1244 ["vxm", "v", "vmve"],
1245 ["vvm", "Uv", "UvmUvUv"],
1246 ["vxm", "Uv", "UvmUvUe"]]>;
1247}
1248
1249// 12.16. Vector Integer Move Instructions
1250let HasMask = false in {
1251 let MangledName = "vmv_v" in {
1252 defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csil",
1253 [["v", "Uv", "UvUv"]]>;
1254 defm vmv_v : RVVOutBuiltinSet<"vmv_v_v", "csilfd",
1255 [["v", "v", "vv"]]>;
1256 }
1257 let HasNoMaskedOverloaded = false in
1258 defm vmv_v : RVVOutBuiltinSet<"vmv_v_x", "csil",
1259 [["x", "v", "ve"],
1260 ["x", "Uv", "UvUe"]]>;
1261}
1262
1263// 13. Vector Fixed-Point Arithmetic Instructions
1264// 13.1. Vector Single-Width Saturating Add and Subtract
1265defm vsaddu : RVVUnsignedBinBuiltinSet;
1266defm vsadd : RVVSignedBinBuiltinSet;
1267defm vssubu : RVVUnsignedBinBuiltinSet;
1268defm vssub : RVVSignedBinBuiltinSet;
1269
1270// 13.2. Vector Single-Width Averaging Add and Subtract
1271defm vaaddu : RVVUnsignedBinBuiltinSet;
1272defm vaadd : RVVSignedBinBuiltinSet;
1273defm vasubu : RVVUnsignedBinBuiltinSet;
1274defm vasub : RVVSignedBinBuiltinSet;
1275
1276// 13.3. Vector Single-Width Fractional Multiply with Rounding and Saturation
1277defm vsmul : RVVSignedBinBuiltinSet;
1278
1279// 13.4. Vector Single-Width Scaling Shift Instructions
1280defm vssrl : RVVUnsignedShiftBuiltinSet;
1281defm vssra : RVVSignedShiftBuiltinSet;
1282
1283// 13.5. Vector Narrowing Fixed-Point Clip Instructions
1284defm vnclipu : RVVUnsignedNShiftBuiltinSet;
1285defm vnclip : RVVSignedNShiftBuiltinSet;
1286
1287// 14. Vector Floating-Point Instructions
1288// 14.2. Vector Single-Width Floating-Point Add/Subtract Instructions
1289defm vfadd : RVVFloatingBinBuiltinSet;
1290defm vfsub : RVVFloatingBinBuiltinSet;
1291defm vfrsub : RVVFloatingBinVFBuiltinSet;
1292
1293// 14.3. Vector Widening Floating-Point Add/Subtract Instructions
1294// Widening FP add/subtract, 2*SEW = SEW +/- SEW
1295defm vfwadd : RVVFloatingWidenBinBuiltinSet;
1296defm vfwsub : RVVFloatingWidenBinBuiltinSet;
1297// Widening FP add/subtract, 2*SEW = 2*SEW +/- SEW
1298defm vfwadd : RVVFloatingWidenOp0BinBuiltinSet;
1299defm vfwsub : RVVFloatingWidenOp0BinBuiltinSet;
1300
1301// 14.4. Vector Single-Width Floating-Point Multiply/Divide Instructions
1302defm vfmul : RVVFloatingBinBuiltinSet;
1303defm vfdiv : RVVFloatingBinBuiltinSet;
1304defm vfrdiv : RVVFloatingBinVFBuiltinSet;
1305
1306// 14.5. Vector Widening Floating-Point Multiply
1307let Log2LMUL = [-1, 0, 1, 2] in {
1308 defm vfwmul : RVVOutOp0Op1BuiltinSet<"vfwmul", "f",
1309 [["vv", "w", "wvv"],
1310 ["vf", "w", "wve"]]>;
1311}
1312
1313// 14.6. Vector Single-Width Floating-Point Fused Multiply-Add Instructions
1314defm vfmacc : RVVFloatingTerBuiltinSet;
1315defm vfnmacc : RVVFloatingTerBuiltinSet;
1316defm vfmsac : RVVFloatingTerBuiltinSet;
1317defm vfnmsac : RVVFloatingTerBuiltinSet;
1318defm vfmadd : RVVFloatingTerBuiltinSet;
1319defm vfnmadd : RVVFloatingTerBuiltinSet;
1320defm vfmsub : RVVFloatingTerBuiltinSet;
1321defm vfnmsub : RVVFloatingTerBuiltinSet;
1322
1323// 14.7. Vector Widening Floating-Point Fused Multiply-Add Instructions
1324defm vfwmacc : RVVFloatingWidenTerBuiltinSet;
1325defm vfwnmacc : RVVFloatingWidenTerBuiltinSet;
1326defm vfwmsac : RVVFloatingWidenTerBuiltinSet;
1327defm vfwnmsac : RVVFloatingWidenTerBuiltinSet;
1328
1329// 14.8. Vector Floating-Point Square-Root Instruction
1330def vfsqrt : RVVFloatingUnaryVVBuiltin;
1331
1332// 14.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction
1333def vfrsqrt7 : RVVFloatingUnaryVVBuiltin;
1334
1335// 14.10. Vector Floating-Point Reciprocal Estimate Instruction
1336def vfrec7 : RVVFloatingUnaryVVBuiltin;
1337
1338// 14.11. Vector Floating-Point MIN/MAX Instructions
1339defm vfmin : RVVFloatingBinBuiltinSet;
1340defm vfmax : RVVFloatingBinBuiltinSet;
1341
1342// 14.12. Vector Floating-Point Sign-Injection Instructions
1343defm vfsgnj : RVVFloatingBinBuiltinSet;
1344defm vfsgnjn : RVVFloatingBinBuiltinSet;
1345defm vfsgnjx : RVVFloatingBinBuiltinSet;
1346defm vfneg_v : RVVPseudoVFUnaryBuiltin<"vfsgnjn", "fd">;
1347defm vfabs_v : RVVPseudoVFUnaryBuiltin<"vfsgnjx", "fd">;
1348
1349// 14.13. Vector Floating-Point Compare Instructions
1350defm vmfeq : RVVFloatingMaskOutBuiltinSet;
1351defm vmfne : RVVFloatingMaskOutBuiltinSet;
1352defm vmflt : RVVFloatingMaskOutBuiltinSet;
1353defm vmfle : RVVFloatingMaskOutBuiltinSet;
1354defm vmfgt : RVVFloatingMaskOutBuiltinSet;
1355defm vmfge : RVVFloatingMaskOutBuiltinSet;
1356
1357// 14.14. Vector Floating-Point Classify Instruction
1358let Name = "vfclass_v" in
1359 def vfclass : RVVOp0Builtin<"Uv", "Uvv", "fd">;
1360
1361// 14.15. Vector Floating-Point Merge Instructio
1362// C/C++ Operand: (mask, op1, op2, vl), Builtin: (op1, op2, mask, vl)
1363let HasMask = false,
1364 ManualCodegen = [{
1365 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
1366 IntrinsicTypes = {ResultType, Ops[1]->getType(), Ops[3]->getType()};
1367 }] in {
1368 defm vmerge : RVVOutOp1BuiltinSet<"vfmerge", "fd",
1369 [["vvm", "v", "vmvv"]]>;
1370 defm vfmerge : RVVOutOp1BuiltinSet<"vfmerge", "fd",
1371 [["vfm", "v", "vmve"]]>;
1372}
1373
1374// 14.16. Vector Floating-Point Move Instruction
1375let HasMask = false, HasNoMaskedOverloaded = false in
1376 defm vfmv_v : RVVOutBuiltinSet<"vfmv_v_f", "fd",
1377 [["f", "v", "ve"]]>;
1378
1379// 14.17. Single-Width Floating-Point/Integer Type-Convert Instructions
1380def vfcvt_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_xu">;
1381def vfcvt_x_f_v : RVVConvToSignedBuiltin<"vfcvt_x">;
1382def vfcvt_rtz_xu_f_v : RVVConvToUnsignedBuiltin<"vfcvt_rtz_xu">;
1383def vfcvt_rtz_x_f_v : RVVConvToSignedBuiltin<"vfcvt_rtz_x">;
1384def vfcvt_f_xu_v : RVVConvBuiltin<"Fv", "FvUv", "sil", "vfcvt_f">;
1385def vfcvt_f_x_v : RVVConvBuiltin<"Fv", "Fvv", "sil", "vfcvt_f">;
1386
1387// 14.18. Widening Floating-Point/Integer Type-Convert Instructions
1388let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1389 def vfwcvt_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_xu">;
1390 def vfwcvt_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_x">;
1391 def vfwcvt_rtz_xu_f_v : RVVConvToWidenUnsignedBuiltin<"vfwcvt_rtz_xu">;
1392 def vfwcvt_rtz_x_f_v : RVVConvToWidenSignedBuiltin<"vfwcvt_rtz_x">;
1393 def vfwcvt_f_xu_v : RVVConvBuiltin<"Fw", "FwUv", "csi", "vfwcvt_f">;
1394 def vfwcvt_f_x_v : RVVConvBuiltin<"Fw", "Fwv", "csi", "vfwcvt_f">;
1395 def vfwcvt_f_f_v : RVVConvBuiltin<"w", "wv", "hf", "vfwcvt_f">;
1396}
1397
1398// 14.19. Narrowing Floating-Point/Integer Type-Convert Instructions
1399let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
1400 def vfncvt_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_xu">;
1401 def vfncvt_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_x">;
1402 def vfncvt_rtz_xu_f_w : RVVConvToNarrowingUnsignedBuiltin<"vfncvt_rtz_xu">;
1403 def vfncvt_rtz_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_rtz_x">;
1404 def vfncvt_f_xu_w : RVVConvBuiltin<"Fv", "FvUw", "si", "vfncvt_f">;
1405 def vfncvt_f_x_w : RVVConvBuiltin<"Fv", "Fvw", "si", "vfncvt_f">;
1406 def vfncvt_f_f_w : RVVConvBuiltin<"v", "vw", "f", "vfncvt_f">;
1407 def vfncvt_rod_f_f_w : RVVConvBuiltin<"v", "vw", "f", "vfncvt_rod_f">;
1408}
1409
1410// 15. Vector Reduction Operations
1411// 15.1. Vector Single-Width Integer Reduction Instructions
1412defm vredsum : RVVIntReductionBuiltinSet;
1413defm vredmaxu : RVVUnsignedReductionBuiltin;
1414defm vredmax : RVVSignedReductionBuiltin;
1415defm vredminu : RVVUnsignedReductionBuiltin;
1416defm vredmin : RVVSignedReductionBuiltin;
1417defm vredand : RVVIntReductionBuiltinSet;
1418defm vredor : RVVIntReductionBuiltinSet;
1419defm vredxor : RVVIntReductionBuiltinSet;
1420
1421// 15.2. Vector Widening Integer Reduction Instructions
1422// Vector Widening Integer Reduction Operations
1423let HasMaskedOffOperand = false in {
1424 defm vwredsum : RVVOutOp1BuiltinSet<"vwredsum", "csi",
1425 [["vs", "vSw", "SwSwvSw"]]>;
1426 defm vwredsumu : RVVOutOp1BuiltinSet<"vwredsumu", "csi",
1427 [["vs", "UvUSw", "USwUSwUvUSw"]]>;
1428}
1429
1430// 15.3. Vector Single-Width Floating-Point Reduction Instructions
1431defm vfredmax : RVVFloatingReductionBuiltin;
1432defm vfredmin : RVVFloatingReductionBuiltin;
1433defm vfredsum : RVVFloatingReductionBuiltin;
1434defm vfredosum : RVVFloatingReductionBuiltin;
1435
1436// 15.4. Vector Widening Floating-Point Reduction Instructions
1437defm vfwredsum : RVVFloatingWidenReductionBuiltin;
1438defm vfwredosum : RVVFloatingWidenReductionBuiltin;
1439
1440// 16. Vector Mask Instructions
1441// 16.1. Vector Mask-Register Logical Instructions
1442def vmand : RVVMaskBinBuiltin;
1443def vmnand : RVVMaskBinBuiltin;
1444def vmandnot : RVVMaskBinBuiltin;
1445def vmxor : RVVMaskBinBuiltin;
1446def vmor : RVVMaskBinBuiltin;
1447def vmnor : RVVMaskBinBuiltin;
1448def vmornot : RVVMaskBinBuiltin;
1449def vmxnor : RVVMaskBinBuiltin;
1450// pseudoinstructions
1451def vmclr : RVVMaskNullaryBuiltin;
1452def vmset : RVVMaskNullaryBuiltin;
1453defm vmmv_m : RVVPseudoMaskBuiltin<"vmand", "c">;
1454defm vmnot_m : RVVPseudoMaskBuiltin<"vmnand", "c">;
1455
1456// 16.2. Vector mask population count vpopc
1457def vpopc : RVVMaskOp0Builtin<"um">;
1458
1459// 16.3. vfirst find-first-set mask bit
1460def vfirst : RVVMaskOp0Builtin<"lm">;
1461
1462// 16.4. vmsbf.m set-before-first mask bit
1463def vmsbf : RVVMaskUnaryBuiltin;
1464
1465// 16.5. vmsif.m set-including-first mask bit
1466def vmsif : RVVMaskUnaryBuiltin;
1467
1468// 16.6. vmsof.m set-only-first mask bit
1469def vmsof : RVVMaskUnaryBuiltin;
1470
1471let HasNoMaskedOverloaded = false in {
1472 // 16.8. Vector Iota Instruction
1473 defm viota : RVVOutBuiltinSet<"viota", "csil", [["m", "Uv", "Uvm"]]>;
1474
1475 // 16.9. Vector Element Index Instruction
1476 defm vid : RVVOutBuiltinSet<"vid", "csil", [["v", "v", "v"],
1477 ["v", "Uv", "Uv"]]>;
1478}
1479
1480// 17. Vector Permutation Instructions
1481// 17.1. Integer Scalar Move Instructions
1482let HasMask = false in {
1483 let HasVL = false, MangledName = "vmv_x" in
1484 defm vmv_x : RVVOp0BuiltinSet<"vmv_x_s", "csil",
1485 [["s", "ve", "ev"],
1486 ["s", "UvUe", "UeUv"]]>;
1487 let MangledName = "vmv_s" in
1488 defm vmv_s : RVVOutBuiltinSet<"vmv_s_x", "csil",
1489 [["x", "v", "vve"],
1490 ["x", "Uv", "UvUvUe"]]>;
1491}
1492
1493// 17.2. Floating-Point Scalar Move Instructions
1494let HasMask = false in {
1495 let HasVL = false, MangledName = "vfmv_f" in
1496 defm vfmv_f : RVVOp0BuiltinSet<"vfmv_f_s", "fd",
1497 [["s", "ve", "ev"]]>;
1498 let MangledName = "vfmv_s" in
1499 defm vfmv_s : RVVOutBuiltinSet<"vfmv_s_f", "fd",
1500 [["f", "v", "vve"],
1501 ["x", "Uv", "UvUvUe"]]>;
1502}
1503
1504// 17.3. Vector Slide Instructions
1505// 17.3.1. Vector Slideup Instructions
1506defm vslideup : RVVSlideBuiltinSet;
1507// 17.3.2. Vector Slidedown Instructions
1508defm vslidedown : RVVSlideBuiltinSet;
1509
1510// 17.3.3. Vector Slide1up Instructions
1511defm vslide1up : RVVSlideOneBuiltinSet;
1512defm vfslide1up : RVVFloatingBinVFBuiltinSet;
1513
1514// 17.3.4. Vector Slide1down Instruction
1515defm vslide1down : RVVSlideOneBuiltinSet;
1516defm vfslide1down : RVVFloatingBinVFBuiltinSet;
1517
1518// 17.4. Vector Register Gather Instructions
1519// signed and floating type
1520defm vrgather : RVVOutBuiltinSet<"vrgather_vv", "csilfd",
1521 [["vv", "v", "vvUv"]]>;
1522defm vrgather : RVVOutBuiltinSet<"vrgather_vx", "csilfd",
1523 [["vx", "v", "vvz"]]>;
1524defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csilfd",
1525 [["vv", "v", "vv(Log2EEW:4)Uv"]]>;
1526// unsigned type
1527defm vrgather : RVVOutBuiltinSet<"vrgather_vv", "csil",
1528 [["vv", "Uv", "UvUvUv"]]>;
1529defm vrgather : RVVOutBuiltinSet<"vrgather_vx", "csil",
1530 [["vx", "Uv", "UvUvz"]]>;
1531defm vrgatherei16 : RVVOutBuiltinSet<"vrgatherei16_vv", "csil",
1532 [["vv", "Uv", "UvUv(Log2EEW:4)Uv"]]>;
1533
1534// 17.5. Vector Compress Instruction
1535let HasMask = false,
1536 ManualCodegen = [{
1537 std::rotate(Ops.begin(), Ops.begin() + 1, Ops.begin() + 3);
1538 ID = Intrinsic::riscv_vcompress;
1539 IntrinsicTypes = {ResultType, Ops[3]->getType()};
1540 }] in {
1541 // signed and floating type
1542 defm vcompress : RVVOutBuiltinSet<"vcompress", "csilfd",
1543 [["vm", "v", "vmvv"]]>;
1544 // unsigned type
1545 defm vcompress : RVVOutBuiltinSet<"vcompress", "csil",
1546 [["vm", "Uv", "UvmUvUv"]]>;
1547}
1548
1549// Miscellaneous
1550let HasMask = false, HasVL = false, HasNoMaskedOverloaded = false,
1551 IRName = "" in {
1552 let Name = "vreinterpret_v",
1553 ManualCodegen = [{
1554 return Builder.CreateBitCast(Ops[0], ResultType);
1555 }] in {
1556 // Reinterpret between different type under the same SEW and LMUL
1557 def vreinterpret_i_u : RVVBuiltin<"Uvv", "vUv", "csil">;
1558 def vreinterpret_i_f : RVVBuiltin<"Fvv", "vFv", "il">;
1559 def vreinterpret_u_i : RVVBuiltin<"vUv", "Uvv", "csil">;
1560 def vreinterpret_u_f : RVVBuiltin<"FvUv", "UvFv", "il">;
1561 def vreinterpret_f_i : RVVBuiltin<"vFv", "Fvv", "il">;
1562 def vreinterpret_f_u : RVVBuiltin<"UvFv", "FvUv", "il">;
1563
1564 // Reinterpret between different SEW under the same LMUL
1565 foreach dst_sew = ["(FixedSEW:8)", "(FixedSEW:16)", "(FixedSEW:32)",
1566 "(FixedSEW:64)"] in {
1567 def vreinterpret_i_ # dst_sew : RVVBuiltin<"v" # dst_sew # "v", dst_sew # "vv", "csil">;
1568 def vreinterpret_u_ # dst_sew : RVVBuiltin<"Uv" # dst_sew # "Uv", dst_sew # "UvUv", "csil">;
1569 }
1570 }
1571
1572 let Name = "vundefined",
1573 ManualCodegen = [{
1574 return llvm::UndefValue::get(ResultType);
1575 }] in {
1576 def vundefined : RVVBuiltin<"v", "v", "csilfd">;
1577 def vundefined_u : RVVBuiltin<"Uv", "Uv", "csil">;
1578 }
1579
1580 // LMUL truncation
1581 // C/C++ Operand: VecTy, IR Operand: VecTy, Index
1582 let Name = "vlmul_trunc_v",
1583 ManualCodegen = [{ {
1584 ID = Intrinsic::experimental_vector_extract;
1585 IntrinsicTypes = {ResultType, Ops[0]->getType()};
1586 Ops.push_back(ConstantInt::get(Int64Ty, 0));
1587 return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
1588 } }] in {
1589 foreach dst_lmul = ["(SFixedLog2LMUL:-3)", "(SFixedLog2LMUL:-2)", "(SFixedLog2LMUL:-1)",
1590 "(SFixedLog2LMUL:0)", "(SFixedLog2LMUL:1)", "(SFixedLog2LMUL:2)"] in {
1591 def vlmul_trunc # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vv", "csilfd">;
1592 def vlmul_trunc_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUv", "csil">;
1593 }
1594 }
1595
1596 // LMUL extension
1597 // C/C++ Operand: SubVecTy, IR Operand: VecTy, SubVecTy, Index
1598 let Name = "vlmul_ext_v",
1599 ManualCodegen = [{
1600 ID = Intrinsic::experimental_vector_insert;
1601 IntrinsicTypes = {ResultType, Ops[0]->getType()};
1602 Ops.push_back(llvm::UndefValue::get(ResultType));
1603 std::swap(Ops[0], Ops[1]);
1604 Ops.push_back(ConstantInt::get(Int64Ty, 0));
1605 return Builder.CreateCall(CGM.getIntrinsic(ID, IntrinsicTypes), Ops, "");
1606 }] in {
1607 foreach dst_lmul = ["(LFixedLog2LMUL:-2)", "(LFixedLog2LMUL:-1)", "(LFixedLog2LMUL:-0)",
1608 "(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in {
1609 def vlmul_ext # dst_lmul : RVVBuiltin<"v" # dst_lmul # "v", dst_lmul # "vv", "csilfd">;
1610 def vlmul_ext_u # dst_lmul : RVVBuiltin<"Uv" # dst_lmul # "Uv", dst_lmul # "UvUv", "csil">;
1611 }
1612 }
1613}
1614