arm_mve.td revision 360784
1//===- arm_mve.td - ACLE intrinsic functions for MVE architecture ---------===// 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 set of ACLE-specified source-level intrinsic 10// functions wrapping the MVE vector instruction set and scalar shift 11// operations. 12// 13// Refer to comments in arm_mve_defs.td for the infrastructure used in 14// here, and to MveEmitter.cpp for how those are used in turn to 15// generate code. 16// 17//===----------------------------------------------------------------------===// 18 19include "arm_mve_defs.td" 20 21let params = T.Usual in 22foreach n = [ 2, 4 ] in { 23 def "vst"#n#"q": Intrinsic<Void, (args Ptr<Scalar>, MultiVector<n>), 24 (CustomCodegen<"VST24"> n:$NumVectors, 25 "Intrinsic::arm_mve_vst"#n#"q":$IRIntr)>; 26 def "vld"#n#"q": Intrinsic<MultiVector<n>, (args CPtr<Scalar>), 27 (CustomCodegen<"VLD24"> n:$NumVectors, 28 "Intrinsic::arm_mve_vld"#n#"q":$IRIntr)>; 29} 30 31multiclass bit_op_fp<IRBuilder bitop> { 32def "": Intrinsic<Vector, (args Vector:$a, Vector:$b), 33 (bitcast (bitop (bitcast $a, UVector), (bitcast $b, UVector)), Vector)>; 34} 35 36multiclass bit_op_fp_with_inv<IRBuilder bitop> { 37def "": Intrinsic<Vector, (args Vector:$a, Vector:$b), 38 (bitcast (bitop (bitcast $a, UVector), (not (bitcast $b, UVector))), Vector)>; 39} 40 41let params = T.Signed in { 42def vqaddq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 43 (IRIntBase<"sadd_sat", [Vector]> $a, $b)>; 44def vqsubq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 45 (IRIntBase<"ssub_sat", [Vector]> $a, $b)>; 46} 47let params = T.Unsigned in { 48def vqaddq_u: Intrinsic<Vector, (args Vector:$a, Vector:$b), 49 (IRIntBase<"uadd_sat", [Vector]> $a, $b)>, 50 NameOverride<"vqaddq">; 51def vqsubq_u: Intrinsic<Vector, (args Vector:$a, Vector:$b), 52 (IRIntBase<"usub_sat", [Vector]> $a, $b)>, 53 NameOverride<"vqsubq">; 54} 55 56// Some intrinsics below are implemented not as IR fragments, but as 57// special-purpose IR intrinsics. This is because such a general form 58// (such as NEON uses) required a variable-width vector size, and we are 59// restricted to 128 bit. Although we can possibly get clever with lane 60// operations, the consequent IR representation would be very hard to 61// write sensibly. In particular, doubling a vector's width would be a 62// mess. Other intrinsics just don't translate nicely into IR. 63let params = T.Int in { 64def vaddq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (add $a, $b)>; 65def vhaddq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 66 (IRInt<"vhadd", [Vector]> $a, $b, (unsignedflag Scalar))>; 67def vrhaddq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 68 (IRInt<"vrhadd", [Vector]> $a, $b, (unsignedflag Scalar))>; 69def vandq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (and $a, $b)>; 70def vbicq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (and $a, (not $b))>; 71def veorq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (xor $a, $b)>; 72def vornq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (or $a, (not $b))>; 73def vorrq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (or $a, $b)>; 74def vsubq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (sub $a, $b)>; 75def vhsubq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 76 (IRInt<"vhsub", [Vector]> $a, $b, (unsignedflag Scalar))>; 77def vmulq: Intrinsic<Vector, (args Vector:$a, Vector:$b), (mul $a, $b)>; 78def vmulhq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 79 (IRInt<"vmulh", [Vector]> $a, $b, (unsignedflag Scalar))>; 80def vrmulhq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 81 (IRInt<"vrmulh", [Vector]> $a, $b, (unsignedflag Scalar))>; 82def vmullbq_int: Intrinsic<DblVector, (args Vector:$a, Vector:$b), 83 (IRInt<"vmull", [DblVector, Vector]> 84 $a, $b, (unsignedflag Scalar), 0)>; 85def vmulltq_int: Intrinsic<DblVector, (args Vector:$a, Vector:$b), 86 (IRInt<"vmull", [DblVector, Vector]> 87 $a, $b, (unsignedflag Scalar), 1)>; 88} 89let params = T.Signed in { 90def vqdmulhq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 91 (IRInt<"vqdmulh", [Vector]> $a, $b)>; 92def vqrdmulhq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 93 (IRInt<"vqrdmulh", [Vector]> $a, $b)>; 94} 95 96let params = T.Poly, overrideKindLetter = "p" in { 97def vmullbq_poly: Intrinsic<DblVector, (args Vector:$a, Vector:$b), 98 (IRInt<"vmull_poly", [DblVector, Vector]> 99 $a, $b, 0)>; 100def vmulltq_poly: Intrinsic<DblVector, (args Vector:$a, Vector:$b), 101 (IRInt<"vmull_poly", [DblVector, Vector]> 102 $a, $b, 1)>; 103} 104 105let params = T.Float in { 106def vaddqf: Intrinsic<Vector, (args Vector:$a, Vector:$b), (fadd $a, $b)>, 107 NameOverride<"vaddq">; 108defm vandqf: bit_op_fp<and>, NameOverride<"vandq">; 109defm vbicqf: bit_op_fp_with_inv<and>, NameOverride<"vbicq">; 110defm veorqf: bit_op_fp<xor>, NameOverride<"veorq">; 111defm vornqf: bit_op_fp_with_inv<or>, NameOverride<"vornq">; 112defm vorrqf: bit_op_fp<or>, NameOverride<"vorrq">; 113def vsubqf: Intrinsic<Vector, (args Vector:$a, Vector:$b), (fsub $a, $b)>, 114 NameOverride<"vsubq">; 115def vmulqf: Intrinsic<Vector, (args Vector:$a, Vector:$b), (fmul $a, $b)>, 116 NameOverride<"vmulq">; 117} 118 119// The bitcasting below is not overcomplicating the IR because while 120// Vector and UVector may be different vector types at the C level i.e. 121// vectors of same size signed/unsigned ints. Once they're lowered 122// to IR, they are just bit vectors with no sign at all, so the 123// bitcasts will be automatically elided by IRBuilder. 124multiclass predicated_bit_op_fp<string int_op> { 125def "": Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b, 126 Predicate:$pred), 127 (bitcast (IRInt<int_op, [UVector, Predicate]> 128 (bitcast $a, UVector), 129 (bitcast $b, UVector), 130 $pred, 131 (bitcast $inactive, UVector)), Vector)>; 132} 133 134// Plain intrinsics 135let params = T.Usual in { 136def vabdq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 137 (IRInt<"vabd", [Vector]> $a, $b, (unsignedflag Scalar))>; 138} 139 140multiclass VectorVectorArithmetic<string operation, dag extraArgs = (?), 141 int wantXVariant = 1> { 142 defm "" : IntrinsicMX< 143 Vector, (args Vector:$a, Vector:$b, Predicate:$pred), 144 !con((IRInt<operation, [Vector, Predicate]> $a, $b), 145 extraArgs, (? $pred, $inactive)), wantXVariant>; 146} 147 148multiclass VectorVectorArithmeticBitcast<string operation> { 149 defm "" : IntrinsicMX<Vector, (args Vector:$a, Vector:$b, 150 Predicate:$pred), 151 (bitcast (IRInt<operation, [UVector, Predicate]> 152 (bitcast $a, UVector), 153 (bitcast $b, UVector), 154 $pred, 155 (bitcast $inactive, UVector)), Vector)>; 156} 157 158// Predicated intrinsics 159let params = T.Usual in { 160 defm vabdq : VectorVectorArithmetic<"abd_predicated", (? (unsignedflag Scalar))>; 161 defm vaddq : VectorVectorArithmetic<"add_predicated">; 162 defm vsubq : VectorVectorArithmetic<"sub_predicated">; 163 defm vmulq : VectorVectorArithmetic<"mul_predicated">; 164 defm vandq : VectorVectorArithmeticBitcast<"and_predicated">; 165 defm vbicq : VectorVectorArithmeticBitcast<"bic_predicated">; 166 defm veorq : VectorVectorArithmeticBitcast<"eor_predicated">; 167 defm vornq : VectorVectorArithmeticBitcast<"orn_predicated">; 168 defm vorrq : VectorVectorArithmeticBitcast<"orr_predicated">; 169} 170 171multiclass DblVectorVectorArithmetic<string operation, dag extraArgs = (?)> { 172 defm "" : IntrinsicMX< 173 DblVector, (args Vector:$a, Vector:$b, Predicate:$pred), 174 !con((IRInt<operation, [DblVector, Vector, Predicate]> $a, $b), 175 extraArgs, (? $pred, $inactive))>; 176} 177 178// Predicated intrinsics - Int types only 179let params = T.Int in { 180 defm vminq : VectorVectorArithmetic<"min_predicated", (? (unsignedflag Scalar))>; 181 defm vmaxq : VectorVectorArithmetic<"max_predicated", (? (unsignedflag Scalar))>; 182 defm vmulhq : VectorVectorArithmetic<"mulh_predicated", (? (unsignedflag Scalar))>; 183 defm vrmulhq : VectorVectorArithmetic<"rmulh_predicated", (? (unsignedflag Scalar))>; 184 defm vqaddq : VectorVectorArithmetic<"qadd_predicated", (? (unsignedflag Scalar)), 0>; 185 defm vhaddq : VectorVectorArithmetic<"hadd_predicated", (? (unsignedflag Scalar))>; 186 defm vrhaddq : VectorVectorArithmetic<"rhadd_predicated", (? (unsignedflag Scalar))>; 187 defm vqsubq : VectorVectorArithmetic<"qsub_predicated", (? (unsignedflag Scalar)), 0>; 188 defm vhsubq : VectorVectorArithmetic<"hsub_predicated", (? (unsignedflag Scalar))>; 189 defm vmullbq_int : DblVectorVectorArithmetic<"mull_int_predicated", (? (unsignedflag Scalar), (u32 0))>; 190 defm vmulltq_int : DblVectorVectorArithmetic<"mull_int_predicated", (? (unsignedflag Scalar), (u32 1))>; 191} 192let params = T.Signed in { 193 defm vqdmulhq : VectorVectorArithmetic<"qdmulh_predicated", (?), 0>; 194 defm vqrdmulhq : VectorVectorArithmetic<"qrdmulh_predicated", (?), 0>; 195} 196 197let params = T.Poly, overrideKindLetter = "p" in { 198 defm vmullbq_poly : DblVectorVectorArithmetic<"mull_poly_predicated", (? (u32 0))>; 199 defm vmulltq_poly : DblVectorVectorArithmetic<"mull_poly_predicated", (? (u32 1))>; 200} 201 202// Predicated intrinsics - Float types only 203let params = T.Float in { 204 defm vminnmq : VectorVectorArithmetic<"min_predicated", (? (u32 0))>; 205 defm vmaxnmq : VectorVectorArithmetic<"max_predicated", (? (u32 0))>; 206} 207 208let params = T.Int in { 209def vminvq: Intrinsic<Scalar, (args Scalar:$prev, Vector:$vec), 210 (Scalar (IRInt<"minv", [Vector], 1> $prev, $vec))>; 211def vmaxvq: Intrinsic<Scalar, (args Scalar:$prev, Vector:$vec), 212 (Scalar (IRInt<"maxv", [Vector], 1> $prev, $vec))>; 213} 214 215foreach half = [ "b", "t" ] in { 216 defvar halfconst = !if(!eq(half, "b"), 0, 1); 217 218 let params = [f32], pnt = PNT_None in { 219 def vcvt#half#q_f16: Intrinsic< 220 VecOf<f16>, (args VecOf<f16>:$inactive, Vector:$a), 221 (IRInt<"vcvt_narrow"> $inactive, $a, halfconst)>; 222 def vcvt#half#q_m_f16: Intrinsic< 223 VecOf<f16>, (args VecOf<f16>:$inactive, Vector:$a, PredOf<f32>:$pred), 224 (IRInt<"vcvt_narrow_predicated"> $inactive, $a, halfconst, $pred)>; 225 } // params = [f32], pnt = PNT_None 226} // loop over half = "b", "t" 227 228multiclass compare_with_pred<string condname, dag arguments, 229 dag cmp, string suffix> { 230 // Make the predicated and unpredicated versions of a single comparison. 231 def: Intrinsic<Predicate, arguments, 232 (u16 (IRInt<"pred_v2i", [Predicate]> cmp))>, 233 NameOverride<"vcmp" # condname # "q" # suffix>; 234 def: Intrinsic<Predicate, !con(arguments, (args Predicate:$inpred)), 235 (u16 (IRInt<"pred_v2i", [Predicate]> (and $inpred, cmp)))>, 236 NameOverride<"vcmp" # condname # "q_m" # suffix>; 237} 238 239multiclass compare<string condname, IRBuilder cmpop> { 240 // Make all four variants of a comparison: the vector/vector and 241 // vector/scalar forms, each using compare_with_pred to make a 242 // predicated and unpredicated version. 243 defm: compare_with_pred<condname, (args Vector:$va, Vector:$vb), 244 (cmpop $va, $vb), "">; 245 let pnt = PNT_NType in { 246 defm: compare_with_pred<condname, (args Vector:$va, unpromoted<Scalar>:$sb), 247 (cmpop $va, (splat $sb)), "_n">; 248 } 249} 250let params = T.Int in { 251 defm: compare<"eq", icmp_eq>; 252 defm: compare<"ne", icmp_ne>; 253} 254let params = T.Signed in { 255 defm: compare<"gt", icmp_sgt>; 256 defm: compare<"ge", icmp_sge>; 257 defm: compare<"lt", icmp_slt>; 258 defm: compare<"le", icmp_sle>; 259} 260let params = T.Unsigned in { 261 defm: compare<"hi", icmp_ugt>; 262 defm: compare<"cs", icmp_uge>; 263} 264let params = T.Float in { 265 defm: compare<"eq", fcmp_eq>; 266 defm: compare<"ne", fcmp_ne>; 267 defm: compare<"gt", fcmp_gt>; 268 defm: compare<"ge", fcmp_ge>; 269 defm: compare<"lt", fcmp_lt>; 270 defm: compare<"le", fcmp_le>; 271} 272 273let params = T.Signed in { 274 def vminq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 275 (select (icmp_sle $a, $b), $a, $b)>; 276 def vmaxq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 277 (select (icmp_sge $a, $b), $a, $b)>; 278} 279let params = T.Unsigned in { 280 def vminqu: Intrinsic<Vector, (args Vector:$a, Vector:$b), 281 (select (icmp_ule $a, $b), $a, $b)>, 282 NameOverride<"vminq">; 283 def vmaxqu: Intrinsic<Vector, (args Vector:$a, Vector:$b), 284 (select (icmp_uge $a, $b), $a, $b)>, 285 NameOverride<"vmaxq">; 286} 287let params = T.Float in { 288 def vminnmq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 289 (IRIntBase<"minnum", [Vector]> $a, $b)>; 290 def vmaxnmq: Intrinsic<Vector, (args Vector:$a, Vector:$b), 291 (IRIntBase<"maxnum", [Vector]> $a, $b)>; 292} 293 294def vpselq: Intrinsic<Vector, (args Vector:$t, Vector:$f, Predicate:$pred), 295 (select $pred, $t, $f)> { let params = T.Usual; } 296def vpselq_64: Intrinsic< 297 Vector, (args Vector:$t, Vector:$f, PredOf<u32>:$pred), 298 (bitcast (select $pred, (bitcast $t, VecOf<u32>), 299 (bitcast $f, VecOf<u32>)), Vector)>, 300 NameOverride<"vpselq"> { let params = T.All64; } 301 302let params = [Void], pnt = PNT_None in { 303 304 multiclass vctp<Type pred, string intname> { 305 def "": Intrinsic<pred, (args u32:$val), 306 (u16 (IRInt<"pred_v2i", [pred]> (IRIntBase<intname> $val)))>; 307 def _m: Intrinsic<pred, (args u32:$val, pred:$inpred), 308 (u16 (IRInt<"pred_v2i", [pred]> (and $inpred, 309 (IRIntBase<intname> $val))))>; 310 } 311 defm vctp8q: vctp<PredOf<u8>, "arm_mve_vctp8">; 312 defm vctp16q: vctp<PredOf<u16>, "arm_mve_vctp16">; 313 defm vctp32q: vctp<PredOf<u32>, "arm_mve_vctp32">; 314 defm vctp64q: vctp<PredOf<u64>, "arm_mve_vctp64">; 315 316 def vpnot: Intrinsic<PredOf<u8>, (args unpromoted<PredOf<u8>>:$pred), 317 (xor $pred, (u16 65535))>; 318 319} 320 321multiclass contiguous_load<string mnemonic, PrimitiveType memtype, 322 list<Type> same_size, list<Type> wider> { 323 // Intrinsics named with explicit memory and element sizes that match: 324 // vldrbq_?8, vldrhq_?16, vldrwq_?32. 325 let params = same_size, pnt = PNT_None in { 326 def: Intrinsic<Vector, (args CPtr<CopyKind<same_size[0], Scalar>>:$addr), 327 (load (address (CPtr<Vector> $addr), !srl(memtype.size,3)))>, 328 NameOverride<mnemonic>; 329 def: Intrinsic<Vector, (args CPtr<CopyKind<same_size[0], Scalar>>:$addr, 330 Predicate:$pred), 331 (IRIntBase<"masked_load", [Vector, CPtr<Vector>]> 332 (CPtr<Vector> $addr), !srl(memtype.size,3), 333 $pred, (zeroinit Vector))>, 334 NameOverride<mnemonic # "_z">; 335 } 336 337 // Synonyms for the above, with the generic name vld1q that just means 338 // 'memory and element sizes match', and allows convenient polymorphism with 339 // the memory and element types covariant. 340 let params = same_size in { 341 def: Intrinsic<Vector, (args CPtr<CopyKind<same_size[0], Scalar>>:$addr), 342 (load (address (CPtr<Vector> $addr), !srl(memtype.size,3)))>, 343 NameOverride<"vld1q">; 344 def: Intrinsic<Vector, (args CPtr<CopyKind<same_size[0], Scalar>>:$addr, 345 Predicate:$pred), 346 (IRIntBase<"masked_load", [Vector, CPtr<Vector>]> 347 (CPtr<Vector> $addr), !srl(memtype.size,3), 348 $pred, (zeroinit Vector))>, 349 NameOverride<"vld1q_z">; 350 } 351 352 // Intrinsics with the memory size narrower than the vector element, so that 353 // they load less than 128 bits of memory and sign/zero extend each loaded 354 // value into a wider vector lane. 355 let params = wider, pnt = PNT_None in { 356 def: Intrinsic<Vector, (args CPtr<CopyKind<same_size[0], Scalar>>:$addr), 357 (extend (load (address (CPtr<NarrowedVecOf<memtype,Vector>> 358 $addr), !srl(memtype.size,3))), 359 Vector, (unsignedflag Scalar))>, 360 NameOverride<mnemonic>; 361 def: Intrinsic<Vector, (args CPtr<CopyKind<same_size[0], Scalar>>:$addr, 362 Predicate:$pred), 363 (extend (IRIntBase<"masked_load", 364 [NarrowedVecOf<memtype,Vector>, 365 CPtr<NarrowedVecOf<memtype,Vector>>]> 366 (CPtr<NarrowedVecOf<memtype,Vector>> $addr), 367 !srl(memtype.size,3), $pred, 368 (zeroinit NarrowedVecOf<memtype,Vector>)), 369 Vector, (unsignedflag Scalar))>, 370 NameOverride<mnemonic # "_z">; 371 } 372} 373 374defm: contiguous_load<"vldrbq", u8, T.All8, !listconcat(T.Int16, T.Int32)>; 375defm: contiguous_load<"vldrhq", u16, T.All16, T.Int32>; 376defm: contiguous_load<"vldrwq", u32, T.All32, []>; 377 378multiclass contiguous_store<string mnemonic, PrimitiveType memtype, 379 list<Type> same_size, list<Type> wider> { 380 // Intrinsics named with explicit memory and element sizes that match: 381 // vstrbq_?8, vstrhq_?16, vstrwq_?32. 382 let params = same_size in { 383 def: Intrinsic<Void, (args Ptr<CopyKind<same_size[0], Scalar>>:$addr, 384 Vector:$value), 385 (store $value, 386 (address (Ptr<Vector> $addr), !srl(memtype.size,3)))>, 387 NameOverride<mnemonic>; 388 def: Intrinsic<Void, (args Ptr<CopyKind<same_size[0], Scalar>>:$addr, 389 Vector:$value, Predicate:$pred), 390 (IRIntBase<"masked_store", [Vector, Ptr<Vector>]> 391 $value, (Ptr<Vector> $addr), 392 !srl(memtype.size,3), $pred)>, 393 NameOverride<mnemonic # "_p">; 394 } 395 396 // Synonyms for the above, with the generic name vst1q that just means 397 // 'memory and element sizes match', and allows convenient polymorphism with 398 // the memory and element types covariant. 399 let params = same_size in { 400 def: Intrinsic<Void, (args Ptr<CopyKind<same_size[0], Scalar>>:$addr, 401 Vector:$value), 402 (store $value, 403 (address (Ptr<Vector> $addr), !srl(memtype.size,3)))>, 404 NameOverride<"vst1q">; 405 def: Intrinsic<Void, (args Ptr<CopyKind<same_size[0], Scalar>>:$addr, 406 Vector:$value, Predicate:$pred), 407 (IRIntBase<"masked_store", [Vector, Ptr<Vector>]> 408 $value, (Ptr<Vector> $addr), 409 !srl(memtype.size,3), $pred)>, 410 NameOverride<"vst1q_p">; 411 } 412 413 // Intrinsics with the memory size narrower than the vector element, so that 414 // they store less than 128 bits of memory, truncating each vector lane into 415 // a narrower value to store. 416 let params = wider in { 417 def: Intrinsic<Void, (args Ptr<CopyKind<same_size[0], Scalar>>:$addr, 418 Vector:$value), 419 (store (trunc $value, NarrowedVecOf<memtype,Vector>), 420 (address (Ptr<NarrowedVecOf<memtype,Vector>> $addr), 421 !srl(memtype.size,3)))>, 422 NameOverride<mnemonic>; 423 def: Intrinsic<Void, (args Ptr<CopyKind<same_size[0], Scalar>>:$addr, 424 Vector:$value, Predicate:$pred), 425 (IRIntBase<"masked_store", 426 [NarrowedVecOf<memtype,Vector>, 427 Ptr<NarrowedVecOf<memtype,Vector>>]> 428 (trunc $value, NarrowedVecOf<memtype,Vector>), 429 (Ptr<NarrowedVecOf<memtype,Vector>> $addr), 430 !srl(memtype.size,3), $pred)>, 431 NameOverride<mnemonic # "_p">; 432 } 433} 434 435defm: contiguous_store<"vstrbq", u8, T.All8, !listconcat(T.Int16, T.Int32)>; 436defm: contiguous_store<"vstrhq", u16, T.All16, T.Int32>; 437defm: contiguous_store<"vstrwq", u32, T.All32, []>; 438 439multiclass gather_base<list<Type> types, int size> { 440 let params = types, pnt = PNT_None in { 441 def _gather_base: Intrinsic< 442 Vector, (args UVector:$addr, imm_mem7bit<size>:$offset), 443 (IRInt<"vldr_gather_base", [Vector, UVector]> $addr, $offset)>; 444 445 def _gather_base_z: Intrinsic< 446 Vector, (args UVector:$addr, imm_mem7bit<size>:$offset, Predicate:$pred), 447 (IRInt<"vldr_gather_base_predicated", [Vector, UVector, Predicate]> 448 $addr, $offset, $pred)>; 449 450 def _gather_base_wb: Intrinsic< 451 Vector, (args Ptr<UVector>:$addr, imm_mem7bit<size>:$offset), 452 (seq (IRInt<"vldr_gather_base_wb", [Vector, UVector]> 453 (load $addr), $offset):$pair, 454 (store (xval $pair, 1), $addr), 455 (xval $pair, 0))>; 456 457 def _gather_base_wb_z: Intrinsic< 458 Vector, (args Ptr<UVector>:$addr, imm_mem7bit<size>:$offset, 459 Predicate:$pred), 460 (seq (IRInt<"vldr_gather_base_wb_predicated", 461 [Vector, UVector, Predicate]> 462 (load $addr), $offset, $pred):$pair, 463 (store (xval $pair, 1), $addr), 464 (xval $pair, 0))>; 465 } 466} 467 468defm vldrwq: gather_base<T.All32, 4>; 469defm vldrdq: gather_base<T.All64, 8>; 470 471multiclass scatter_base<list<Type> types, int size> { 472 let params = types in { 473 def _scatter_base: Intrinsic< 474 Void, (args UVector:$addr, imm_mem7bit<size>:$offset, Vector:$data), 475 (IRInt<"vstr_scatter_base", [UVector, Vector]> $addr, $offset, $data)>; 476 477 def _scatter_base_p: Intrinsic< 478 Void, (args UVector:$addr, imm_mem7bit<size>:$offset, Vector:$data, 479 Predicate:$pred), 480 (IRInt<"vstr_scatter_base_predicated", [UVector, Vector, Predicate]> 481 $addr, $offset, $data, $pred)>; 482 483 def _scatter_base_wb: Intrinsic< 484 Void, (args Ptr<UVector>:$addr, imm_mem7bit<size>:$offset, Vector:$data), 485 (seq (IRInt<"vstr_scatter_base_wb", [UVector, Vector]> 486 (load $addr), $offset, $data):$wbaddr, 487 (store $wbaddr, $addr))>; 488 489 def _scatter_base_wb_p: Intrinsic< 490 Void, (args Ptr<UVector>:$addr, imm_mem7bit<size>:$offset, 491 Vector:$data, Predicate:$pred), 492 (seq (IRInt<"vstr_scatter_base_wb_predicated", 493 [UVector, Vector, Predicate]> 494 (load $addr), $offset, $data, $pred):$wbaddr, 495 (store $wbaddr, $addr))>; 496 } 497} 498 499defm vstrwq: scatter_base<T.All32, 4>; 500defm vstrdq: scatter_base<T.All64, 8>; 501 502multiclass gather_offset_unshifted<list<Type> types, PrimitiveType memtype> { 503 let params = types in { 504 def _gather_offset: Intrinsic< 505 Vector, (args CPtr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets), 506 (IRInt<"vldr_gather_offset", 507 [Vector, CPtr<CopyKind<memtype, Scalar>>, UVector]> 508 $base, $offsets, memtype.size, 0, (unsignedflag Scalar))>; 509 def _gather_offset_z: Intrinsic< 510 Vector, (args CPtr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets, 511 Predicate:$pred), 512 (IRInt<"vldr_gather_offset_predicated", 513 [Vector, CPtr<CopyKind<memtype, Scalar>>, UVector, Predicate]> 514 $base, $offsets, memtype.size, 0, (unsignedflag Scalar), $pred)>; 515 } 516} 517 518multiclass gather_offset_shifted<list<Type> types, PrimitiveType memtype, 519 int shift> { 520 let params = types in { 521 def _gather_shifted_offset: Intrinsic< 522 Vector, (args CPtr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets), 523 (IRInt<"vldr_gather_offset", 524 [Vector, CPtr<CopyKind<memtype, Scalar>>, UVector]> 525 $base, $offsets, memtype.size, shift, (unsignedflag Scalar))>; 526 def _gather_shifted_offset_z: Intrinsic< 527 Vector, (args CPtr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets, 528 Predicate:$pred), 529 (IRInt<"vldr_gather_offset_predicated", 530 [Vector, CPtr<CopyKind<memtype, Scalar>>, UVector, Predicate]> 531 $base, $offsets, memtype.size, shift, (unsignedflag Scalar), $pred)>; 532 } 533} 534 535multiclass gather_offset_both<list<Type> types, PrimitiveType memtype, 536 int shift> { 537 defm "": gather_offset_unshifted<types, memtype>; 538 defm "": gather_offset_shifted<types, memtype, shift>; 539} 540 541defm vldrbq: gather_offset_unshifted<!listconcat(T.All8, T.Int16, T.Int32), u8>; 542defm vldrhq: gather_offset_both<!listconcat(T.All16, T.Int32), u16, 1>; 543defm vldrwq: gather_offset_both<T.All32, u32, 2>; 544defm vldrdq: gather_offset_both<T.Int64, u64, 3>; 545 546multiclass scatter_offset_unshifted<list<Type> types, PrimitiveType memtype> { 547 let params = types in { 548 def _scatter_offset: Intrinsic< 549 Void, (args Ptr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets, 550 Vector:$data), 551 (IRInt<"vstr_scatter_offset", 552 [Ptr<CopyKind<memtype, Scalar>>, UVector, Vector]> 553 $base, $offsets, $data, memtype.size, 0)>; 554 def _scatter_offset_p: Intrinsic< 555 Void, (args Ptr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets, 556 Vector:$data, Predicate:$pred), 557 (IRInt<"vstr_scatter_offset_predicated", 558 [Ptr<CopyKind<memtype, Scalar>>, UVector, Vector, Predicate]> 559 $base, $offsets, $data, memtype.size, 0, $pred)>; 560 } 561} 562 563multiclass scatter_offset_shifted<list<Type> types, PrimitiveType memtype, 564 int shift> { 565 let params = types in { 566 def _scatter_shifted_offset: Intrinsic< 567 Void, (args Ptr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets, 568 Vector:$data), 569 (IRInt<"vstr_scatter_offset", 570 [Ptr<CopyKind<memtype, Scalar>>, UVector, Vector]> 571 $base, $offsets, $data, memtype.size, shift)>; 572 def _scatter_shifted_offset_p: Intrinsic< 573 Void, (args Ptr<CopyKind<memtype, Scalar>>:$base, UVector:$offsets, 574 Vector:$data, Predicate:$pred), 575 (IRInt<"vstr_scatter_offset_predicated", 576 [Ptr<CopyKind<memtype, Scalar>>, UVector, Vector, Predicate]> 577 $base, $offsets, $data, memtype.size, shift, $pred)>; 578 } 579} 580 581multiclass scatter_offset_both<list<Type> types, PrimitiveType memtype, 582 int shift> { 583 defm "": scatter_offset_unshifted<types, memtype>; 584 defm "": scatter_offset_shifted<types, memtype, shift>; 585} 586 587defm vstrbq: scatter_offset_unshifted<!listconcat(T.All8,T.Int16,T.Int32), u8>; 588defm vstrhq: scatter_offset_both<!listconcat(T.All16, T.Int32), u16, 1>; 589defm vstrwq: scatter_offset_both<T.All32, u32, 2>; 590defm vstrdq: scatter_offset_both<T.Int64, u64, 3>; 591 592let params = T.Int in { 593 def vshlq_n: Intrinsic<Vector, (args Vector:$v, imm_0toNm1:$sh), 594 (shl $v, (splat (Scalar $sh)))>; 595 defm vshlq: IntrinsicMX<Vector, (args Vector:$v, imm_0toNm1:$sh, 596 Predicate:$pred), 597 (IRInt<"shl_imm_predicated", [Vector, Predicate]> 598 $v, $sh, $pred, $inactive), 1, "_n">; 599 600 let pnt = PNT_NType in { 601 def vshrq_n: Intrinsic<Vector, (args Vector:$v, imm_1toN:$sh), 602 (immshr $v, $sh, (unsignedflag Scalar))>; 603 defm vshrq: IntrinsicMX<Vector, (args Vector:$v, imm_1toN:$sh, 604 Predicate:$pred), 605 (IRInt<"shr_imm_predicated", [Vector, Predicate]> 606 $v, $sh, (unsignedflag Scalar), $pred, $inactive), 1, "_n">; 607 } 608} 609 610let params = T.Int in { 611 def vqshlq_n: Intrinsic<Vector, (args Vector:$v, imm_0toNm1:$sh), 612 (IRInt<"vqshl_imm", [Vector]> $v, $sh, (unsignedflag Scalar))>; 613 def vqshlq_m_n: Intrinsic<Vector, (args Vector:$inactive, Vector:$v, 614 imm_0toNm1:$sh, Predicate:$pred), 615 (IRInt<"vqshl_imm_predicated", [Vector, Predicate]> 616 $v, $sh, (unsignedflag Scalar), $pred, $inactive)>; 617 618 let pnt = PNT_NType in { 619 def vrshrq_n: Intrinsic<Vector, (args Vector:$v, imm_1toN:$sh), 620 (IRInt<"vrshr_imm", [Vector]> $v, $sh, (unsignedflag Scalar))>; 621 defm vrshrq: IntrinsicMX<Vector, (args Vector:$v, imm_1toN:$sh, 622 Predicate:$pred), 623 (IRInt<"vrshr_imm_predicated", [Vector, Predicate]> 624 $v, $sh, (unsignedflag Scalar), $pred, $inactive), 1, "_n">; 625 } 626} 627 628let params = T.Signed, pnt = PNT_NType in { 629 def vqshluq_n: Intrinsic<UVector, (args Vector:$v, imm_0toNm1:$sh), 630 (IRInt<"vqshlu_imm", [Vector]> $v, $sh)>; 631 def vqshluq_m_n: Intrinsic<UVector, (args UVector:$inactive, Vector:$v, 632 imm_0toNm1:$sh, Predicate:$pred), 633 (IRInt<"vqshlu_imm_predicated", [Vector, Predicate]> 634 $v, $sh, $pred, $inactive)>; 635} 636 637multiclass vshll_imm<int top> { 638 let params = !listconcat(T.Int8, T.Int16), pnt = PNT_NType in { 639 def _n: Intrinsic<DblVector, (args Vector:$v, imm_1toN:$sh), 640 (IRInt<"vshll_imm", [DblVector, Vector]> 641 $v, $sh, (unsignedflag Scalar), top)>; 642 defm "": IntrinsicMX<DblVector, (args Vector:$v, imm_1toN:$sh, 643 Predicate:$pred), 644 (IRInt<"vshll_imm_predicated", [DblVector, Vector, Predicate]> 645 $v, $sh, (unsignedflag Scalar), top, $pred, $inactive), 1, "_n">; 646 } 647} 648defm vshllbq : vshll_imm<0>; 649defm vshlltq : vshll_imm<1>; 650 651multiclass DyadicImmShift<Type outtype, Immediate imm, string intname = NAME, 652 dag extraargs = (?)> { 653 defvar intparams = !if(!eq(!cast<string>(outtype), !cast<string>(Vector)), 654 [Vector], [outtype, Vector]); 655 656 def q_n: Intrinsic< 657 outtype, (args outtype:$a, Vector:$b, imm:$sh), 658 !con((IRInt<intname, intparams> $a, $b, $sh), extraargs)>; 659 660 def q_m_n: Intrinsic< 661 outtype, (args outtype:$a, Vector:$b, imm:$sh, Predicate:$pred), 662 !con((IRInt<intname # "_predicated", intparams # [Predicate]> 663 $a, $b, $sh), extraargs, (? $pred))>; 664} 665 666multiclass VSHRN<Type outtype, Immediate imm, dag extraargs> { 667 defm b: DyadicImmShift<outtype, imm, "vshrn", !con(extraargs, (? 0))>; 668 defm t: DyadicImmShift<outtype, imm, "vshrn", !con(extraargs, (? 1))>; 669} 670 671let params = [s16, s32, u16, u32], pnt = PNT_NType in { 672 defvar U = (unsignedflag Scalar); 673 defm vshrn : VSHRN<HalfVector, imm_1toHalfN, (? 0,0,U,U)>; 674 defm vqshrn : VSHRN<HalfVector, imm_1toHalfN, (? 1,0,U,U)>; 675 defm vrshrn : VSHRN<HalfVector, imm_1toHalfN, (? 0,1,U,U)>; 676 defm vqrshrn : VSHRN<HalfVector, imm_1toHalfN, (? 1,1,U,U)>; 677} 678let params = [s16, s32], pnt = PNT_NType in { 679 defm vqshrun : VSHRN<UHalfVector, imm_1toHalfN, (? 1,0,1,0)>; 680 defm vqrshrun : VSHRN<UHalfVector, imm_1toHalfN, (? 1,1,1,0)>; 681} 682let params = T.Int, pnt = PNT_NType in { 683 defm vsli : DyadicImmShift<Vector, imm_0toNm1>; 684 defm vsri : DyadicImmShift<Vector, imm_1toN>; 685} 686 687multiclass VSHL_non_imm<string scalarSuffix, int q, int r, 688 PolymorphicNameType pnt_scalar_unpred = PNT_Type> { 689 let pnt = pnt_scalar_unpred in { 690 def scalarSuffix: Intrinsic< 691 Vector, (args Vector:$in, s32:$sh), 692 (IRInt<"vshl_scalar", [Vector]> $in, $sh, 693 q, r, (unsignedflag Scalar))>; 694 } 695 def "_m" # scalarSuffix: Intrinsic< 696 Vector, (args Vector:$in, s32:$sh, Predicate:$pred), 697 (IRInt<"vshl_scalar_predicated", [Vector, Predicate]> $in, $sh, 698 q, r, (unsignedflag Scalar), $pred)>; 699 700 def "": Intrinsic< 701 Vector, (args Vector:$in, SVector:$sh), 702 (IRInt<"vshl_vector", [Vector, SVector]> $in, $sh, 703 q, r, (unsignedflag Scalar))>; 704 defm "": IntrinsicMX< 705 Vector, (args Vector:$in, SVector:$sh, Predicate:$pred), 706 (IRInt<"vshl_vector_predicated", [Vector, SVector, Predicate]> $in, $sh, 707 q, r, (unsignedflag Scalar), $pred, $inactive), 708 // The saturating shift intrinsics don't have an x variant, so we 709 // set wantXVariant to 1 iff q == 0 710 !eq(q, 0)>; 711} 712 713let params = T.Int in { 714 defm vshlq : VSHL_non_imm<"_r", 0, 0>; 715 defm vqshlq : VSHL_non_imm<"_r", 1, 0>; 716 defm vrshlq : VSHL_non_imm<"_n", 0, 1, PNT_NType>; 717 defm vqrshlq : VSHL_non_imm<"_n", 1, 1, PNT_NType>; 718} 719 720// Base class for the scalar shift intrinsics. 721class ScalarShift<Type argtype, dag shiftCountArg, dag shiftCodeGen>: 722 Intrinsic<argtype, !con((args argtype:$value), shiftCountArg), shiftCodeGen> { 723 let params = [Void]; 724 let pnt = PNT_None; 725} 726 727// Subclass that includes the machinery to take a 64-bit input apart 728// into halves, retrieve the two halves of a shifted output as a pair, 729// and glue the pieces of the pair back into an i64 for output. 730class LongScalarShift<Type argtype, dag shiftCountArg, dag shiftCodeGen>: 731 ScalarShift<argtype, shiftCountArg, 732 (seq (u32 (lshr $value, (argtype 32))):$hi, 733 (u32 $value):$lo, 734 shiftCodeGen:$pair, 735 (or (shl (u64 (xval $pair, 1)), (u64 32)), 736 (u64 (xval $pair, 0))))>; 737 738// The family of saturating/rounding scalar shifts that take an 739// immediate shift count. They come in matched 32- and 64-bit pairs. 740multiclass ScalarSaturatingShiftImm<Type arg32, Type arg64> { 741 def "": ScalarShift<arg32, (args imm_1to32:$sh), 742 (IRInt<NAME> $value, $sh)>; 743 def l: LongScalarShift<arg64, (args imm_1to32:$sh), 744 (IRInt<NAME # "l"> $lo, $hi, $sh)>; 745} 746defm uqshl: ScalarSaturatingShiftImm<u32, u64>; 747defm urshr: ScalarSaturatingShiftImm<u32, u64>; 748defm sqshl: ScalarSaturatingShiftImm<s32, s64>; 749defm srshr: ScalarSaturatingShiftImm<s32, s64>; 750 751// The family of saturating/rounding scalar shifts that take a 752// register shift count. They also have 32- and 64-bit forms, but the 753// 64-bit form also has a version that saturates to 48 bits, so the IR 754// intrinsic takes an extra saturation-type operand. 755multiclass ScalarSaturatingShiftReg<Type arg32, Type arg64> { 756 def "": ScalarShift<arg32, (args s32:$sh), 757 (IRInt<NAME> $value, $sh)>; 758 def l: LongScalarShift<arg64, (args s32:$sh), 759 (IRInt<NAME # "l"> $lo, $hi, $sh, 64)>; 760 def l_sat48: LongScalarShift<arg64, (args s32:$sh), 761 (IRInt<NAME # "l"> $lo, $hi, $sh, 48)>; 762} 763defm uqrshl: ScalarSaturatingShiftReg<u32, u64>; 764defm sqrshr: ScalarSaturatingShiftReg<s32, s64>; 765 766// The intrinsics for LSLL and ASRL come in 64-bit versions only, with 767// no saturation count. 768def lsll: LongScalarShift<u64, (args s32:$sh), (IRInt<"lsll"> $lo, $hi, $sh)>; 769def asrl: LongScalarShift<s64, (args s32:$sh), (IRInt<"asrl"> $lo, $hi, $sh)>; 770 771let params = T.Int32 in { 772def vadcq: Intrinsic<Vector, (args Vector:$a, Vector:$b, Ptr<uint>:$carry), 773 (seq (IRInt<"vadc", [Vector]> $a, $b, (shl (load $carry), 29)):$pair, 774 (store (and 1, (lshr (xval $pair, 1), 29)), $carry), 775 (xval $pair, 0))>; 776def vadciq: Intrinsic<Vector, (args Vector:$a, Vector:$b, Ptr<uint>:$carry), 777 (seq (IRInt<"vadc", [Vector]> $a, $b, 0):$pair, 778 (store (and 1, (lshr (xval $pair, 1), 29)), $carry), 779 (xval $pair, 0))>; 780def vadcq_m: Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b, 781 Ptr<uint>:$carry, Predicate:$pred), 782 (seq (IRInt<"vadc_predicated", [Vector, Predicate]> $inactive, $a, $b, 783 (shl (load $carry), 29), $pred):$pair, 784 (store (and 1, (lshr (xval $pair, 1), 29)), $carry), 785 (xval $pair, 0))>; 786def vadciq_m: Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b, 787 Ptr<uint>:$carry, Predicate:$pred), 788 (seq (IRInt<"vadc_predicated", [Vector, Predicate]> $inactive, $a, $b, 789 0, $pred):$pair, 790 (store (and 1, (lshr (xval $pair, 1), 29)), $carry), 791 (xval $pair, 0))>; 792} 793 794multiclass VectorComplexAddPred<dag not_halving, dag angle> { 795 def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b), 796 (IRInt<"vcaddq", [Vector]> not_halving, angle, $a, $b)>; 797 defm "" : IntrinsicMX<Vector, (args Vector:$a, Vector:$b, Predicate:$pred), 798 (IRInt<"vcaddq_predicated", [Vector, Predicate]> 799 not_halving, angle, $inactive, $a, $b, $pred)>; 800} 801 802multiclass VectorComplexMulPred<dag angle> { 803 def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b), 804 (IRInt<"vcmulq", [Vector]> angle, $a, $b)>; 805 defm "" : IntrinsicMX<Vector, (args Vector:$a, Vector:$b, Predicate:$pred), 806 (IRInt<"vcmulq_predicated", [Vector, Predicate]> angle, $inactive, $a, $b, 807 $pred)>; 808} 809 810multiclass VectorComplexMLAPred<dag angle> { 811 def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b, Vector:$c), 812 (IRInt<"vcmlaq", [Vector]> angle, $a, $b, $c)>; 813 def _m : Intrinsic<Vector, (args Vector:$a, Vector:$b, Vector:$c, 814 Predicate:$pred), 815 (IRInt<"vcmlaq_predicated", [Vector, Predicate]> angle, $a, $b, $c, $pred)>; 816} 817 818multiclass VectorComplexAddAngle<dag not_halving> { 819 defm _rot90 : VectorComplexAddPred<not_halving, (u32 0)>; 820 defm _rot270 : VectorComplexAddPred<not_halving, (u32 1)>; 821} 822 823multiclass VectorComplexMulAngle { 824 defm "" : VectorComplexMulPred<(u32 0)>; 825 defm _rot90 : VectorComplexMulPred<(u32 1)>; 826 defm _rot180 : VectorComplexMulPred<(u32 2)>; 827 defm _rot270 : VectorComplexMulPred<(u32 3)>; 828} 829 830multiclass VectorComplexMLAAngle { 831 defm "" : VectorComplexMLAPred<(u32 0)>; 832 defm _rot90 : VectorComplexMLAPred<(u32 1)>; 833 defm _rot180 : VectorComplexMLAPred<(u32 2)>; 834 defm _rot270 : VectorComplexMLAPred<(u32 3)>; 835} 836 837let params = T.Usual in 838defm vcaddq : VectorComplexAddAngle<(u32 1)>; 839 840let params = T.Signed in 841defm vhcaddq : VectorComplexAddAngle<(u32 0)>; 842 843let params = T.Float in { 844defm vcmulq : VectorComplexMulAngle; 845defm vcmlaq : VectorComplexMLAAngle; 846} 847 848multiclass MVEBinaryVectorHoriz32<dag subtract, dag exchange, string xsuffix> { 849 def xsuffix#"q" 850 : Intrinsic<Scalar32, (args Vector:$a, Vector:$b), 851 (IRInt<"vmldava", [Vector]> 852 (unsignedflag Scalar), subtract, exchange, 853 (zeroinit Scalar32), $a, $b)>; 854 def xsuffix#"q_p" 855 : Intrinsic<Scalar32, (args Vector:$a, Vector:$b, Predicate:$pred), 856 (IRInt<"vmldava_predicated", [Vector, Predicate]> 857 (unsignedflag Scalar), subtract, exchange, 858 (zeroinit Scalar32), $a, $b, $pred)>; 859 860 def "a"#xsuffix#"q" 861 : Intrinsic<Scalar32, (args Scalar32:$a, Vector:$b, Vector:$c), 862 (IRInt<"vmldava", [Vector]> 863 (unsignedflag Scalar), subtract, exchange, 864 $a, $b, $c)>; 865 def "a"#xsuffix#"q_p" 866 : Intrinsic<Scalar32, (args Scalar32:$a, Vector:$b, Vector:$c, 867 Predicate:$pred), 868 (IRInt<"vmldava_predicated", [Vector, Predicate]> 869 (unsignedflag Scalar), subtract, exchange, 870 $a, $b, $c, $pred)>; 871} 872 873class IntrSplit64<Type resty, dag args, dag codegen> 874 : Intrinsic<resty, args, 875 (seq (u32 (lshr $a, (u64 32))):$hi, 876 (u32 $a):$lo, 877 codegen:$pair, 878 (or (shl (u64 (xval $pair, 1)), (u64 32)), 879 (u64 (xval $pair, 0))))>; 880 881class IntrSplit64ZeroInit<Type resty, dag args, dag codegen> 882 : Intrinsic<resty, args, 883 (seq (zeroinit u32):$hi, 884 (zeroinit u32):$lo, 885 codegen:$pair, 886 (or (shl (u64 (xval $pair, 1)), (u64 32)), 887 (u64 (xval $pair, 0))))>; 888 889multiclass MVEBinaryVectorHoriz64Base<dag subtract, dag exchange, 890 string xsuffix, string irname> { 891 def xsuffix#"q" 892 : IntrSplit64ZeroInit<Scalar64, (args Vector:$a, Vector:$b), 893 (IRInt<irname, [Vector]> 894 (unsignedflag Scalar), subtract, exchange, 895 $lo, $hi, $a, $b)>; 896 def xsuffix#"q_p" 897 : IntrSplit64ZeroInit<Scalar64, (args Vector:$a, Vector:$b, 898 Predicate:$pred), 899 (IRInt<irname#"_predicated", [Vector, Predicate]> 900 (unsignedflag Scalar), subtract, exchange, 901 $lo, $hi, $a, $b, $pred)>; 902 903 def "a"#xsuffix#"q" 904 : IntrSplit64<Scalar64, (args Scalar64:$a, Vector:$b, Vector:$c), 905 (IRInt<irname, [Vector]> 906 (unsignedflag Scalar), subtract, exchange, 907 $lo, $hi, $b, $c)>; 908 def "a"#xsuffix#"q_p" 909 : IntrSplit64<Scalar64, (args Scalar64:$a, Vector:$b, Vector:$c, 910 Predicate:$pred), 911 (IRInt<irname#"_predicated", [Vector, Predicate]> 912 (unsignedflag Scalar), subtract, exchange, 913 $lo, $hi, $b, $c, $pred)>; 914} 915 916multiclass MVEBinaryVectorHoriz64<dag subtract, dag exchange, string xsuffix> { 917 defm "" : MVEBinaryVectorHoriz64Base<subtract, exchange, xsuffix, "vmlldava">; 918} 919 920multiclass MVEBinaryVectorHoriz64R<dag subtract, dag exchange, string xsuffix> { 921 defm "" : MVEBinaryVectorHoriz64Base<subtract, exchange, xsuffix, 922 "vrmlldavha">; 923} 924 925let params = T.Int in { 926def vabavq : Intrinsic<u32, (args u32:$a, Vector:$b, Vector:$c), 927 (IRInt<"vabav", [Vector]> (unsignedflag Scalar), $a, $b, $c)>; 928def vabavq_p : Intrinsic<u32, (args u32:$a, Vector:$b, Vector:$c, 929 Predicate:$pred), 930 (IRInt<"vabav_predicated", [Vector, Predicate]> 931 (unsignedflag Scalar), $a, $b, $c, $pred)>; 932 933defm vmladav : MVEBinaryVectorHoriz32<V.False, V.False, "">; 934} 935 936let params = T.Signed in { 937defm vmladav : MVEBinaryVectorHoriz32<V.False, V.True, "x">; 938defm vmlsdav : MVEBinaryVectorHoriz32<V.True, V.False, "">; 939defm vmlsdav : MVEBinaryVectorHoriz32<V.True, V.True, "x">; 940} 941 942let params = [u16, s16, u32, s32] in 943defm vmlaldav : MVEBinaryVectorHoriz64<V.False, V.False, "">; 944 945let params = [s16, s32] in { 946defm vmlaldav : MVEBinaryVectorHoriz64<V.False, V.True, "x">; 947defm vmlsldav : MVEBinaryVectorHoriz64<V.True, V.False, "">; 948defm vmlsldav : MVEBinaryVectorHoriz64<V.True, V.True, "x">; 949} 950 951let params = T.Int32 in 952defm vrmlaldavh : MVEBinaryVectorHoriz64R<V.False, V.False, "">; 953 954let params = [s32] in { 955defm vrmlaldavh : MVEBinaryVectorHoriz64R<V.False, V.True, "x">; 956defm vrmlsldavh : MVEBinaryVectorHoriz64R<V.True, V.False, "">; 957defm vrmlsldavh : MVEBinaryVectorHoriz64R<V.True, V.True, "x">; 958} 959 960foreach desttype = T.All in { 961 // We want a vreinterpretq between every pair of supported vector types 962 // _except_ that there shouldn't be one from a type to itself. 963 // 964 // So this foldl expression implements what you'd write in Python as 965 // [srctype for srctype in T.All if srctype != desttype] 966 let params = !foldl([]<Type>, T.All, tlist, srctype, !listconcat(tlist, 967 !if(!eq(!cast<string>(desttype),!cast<string>(srctype)),[],[srctype]))) 968 in { 969 def "vreinterpretq_" # desttype: Intrinsic< 970 VecOf<desttype>, (args Vector:$x), (bitcast $x, VecOf<desttype>)>; 971 } 972} 973 974let params = T.All in { 975 let pnt = PNT_None in { 976 def vcreateq: Intrinsic<Vector, (args u64:$a, u64:$b), 977 (bitcast (ielt_const (ielt_const (undef VecOf<u64>), $a, 0), 978 $b, 1), Vector)>; 979 def vuninitializedq: Intrinsic<Vector, (args), (undef Vector)>; 980 } 981 982 // This is the polymorphic form of vuninitializedq, which takes no type 983 // suffix, but takes an _unevaluated_ vector parameter and returns an 984 // uninitialized vector of the same vector type. 985 // 986 // This intrinsic has no _non_-polymorphic form exposed to the user. But each 987 // separately typed version of it still has to have its own clang builtin id, 988 // which can't be called vuninitializedq_u32 or similar because that would 989 // collide with the explicit nullary versions above. So I'm calling them 990 // vuninitializedq_polymorphic_u32 (and so on) for builtin id purposes; that 991 // full name never appears in the header file due to the polymorphicOnly 992 // flag, and the _polymorphic suffix is omitted from the shortened name by 993 // the custom PolymorphicNameType here. 994 let polymorphicOnly = 1, nonEvaluating = 1, 995 pnt = PolymorphicNameType<1, "polymorphic"> in { 996 def vuninitializedq_polymorphic: Intrinsic< 997 Vector, (args Vector), (undef Vector)>; 998 } 999 1000 def vgetq_lane: Intrinsic<Scalar, (args Vector:$v, imm_lane:$lane), 1001 (xelt_var $v, $lane)>; 1002 def vsetq_lane: Intrinsic<Vector, (args unpromoted<Scalar>:$e, Vector:$v, imm_lane:$lane), 1003 (ielt_var $v, $e, $lane)>; 1004} 1005