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