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