1//===--- arm_sve_sme_incl.td - ARM SVE/SME compiler interface -------------===// 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 common properites of TableGen definitions use for both 10// SVE and SME intrinsics. 11// 12// https://developer.arm.com/architectures/system-architectures/software-standards/acle 13// 14//===----------------------------------------------------------------------===// 15 16//===----------------------------------------------------------------------===// 17// Instruction definitions 18//===----------------------------------------------------------------------===// 19// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and 20// a sequence of typespecs. 21// 22// The name is the base name of the intrinsic, for example "svld1". This is 23// then mangled by the tblgen backend to add type information ("svld1_s16"). 24// 25// A typespec is a sequence of uppercase characters (modifiers) followed by one 26// lowercase character. A typespec encodes a particular "base type" of the 27// intrinsic. 28// 29// An example typespec is "Us" - unsigned short - svuint16_t. The available 30// typespec codes are given below. 31// 32// The string given to an Inst class is a sequence of typespecs. The intrinsic 33// is instantiated for every typespec in the sequence. For example "sdUsUd". 34// 35// The prototype is a string that defines the return type of the intrinsic 36// and the type of each argument. The return type and every argument gets a 37// "modifier" that can change in some way the "base type" of the intrinsic. 38// 39// The modifier 'd' means "default" and does not modify the base type in any 40// way. The available modifiers are given below. 41// 42// Typespecs 43// --------- 44// c: char 45// s: short 46// i: int 47// l: long 48// q: int128_t 49// f: float 50// h: half-float 51// d: double 52// b: bfloat 53 54// Typespec modifiers 55// ------------------ 56// P: boolean 57// U: unsigned 58// Q: svcount 59 60// Prototype modifiers 61// ------------------- 62// prototype: return (arg, arg, ...) 63// 64// 2,3,4: array of vectors 65// .: indicator for multi-vector modifier that will follow (e.g. 2.x) 66// v: void 67// x: vector of signed integers 68// u: vector of unsigned integers 69// d: default 70// c: const pointer type 71// P: predicate type 72// s: scalar of element type 73// a: scalar of element type (splat to vector type) 74// R: scalar of 1/2 width element type (splat to vector type) 75// r: scalar of 1/4 width element type (splat to vector type) 76// @: unsigned scalar of 1/4 width element type (splat to vector type) 77// e: 1/2 width unsigned elements, 2x element count 78// b: 1/4 width unsigned elements, 4x element count 79// h: 1/2 width elements, 2x element count 80// q: 1/4 width elements, 4x element count 81// o: 4x width elements, 1/4 element count 82// 83// w: vector of element type promoted to 64bits, vector maintains 84// signedness of its element type. 85// f: element type promoted to uint64_t (splat to vector type) 86// j: element type promoted to 64bits (splat to vector type) 87// K: element type bitcast to a signed integer (splat to vector type) 88// L: element type bitcast to an unsigned integer (splat to vector type) 89// 90// i: constant uint64_t 91// k: int32_t 92// l: int64_t 93// m: uint32_t 94// n: uint64_t 95 96// [: svuint8_t 97// t: svint32_t 98// z: svuint32_t 99// g: svuint64_t 100// O: svfloat16_t 101// M: svfloat32_t 102// N: svfloat64_t 103// $: svbfloat16_t 104 105// J: Prefetch type (sv_prfop) 106 107// %: pointer to void 108 109// A: pointer to int8_t 110// B: pointer to int16_t 111// C: pointer to int32_t 112// D: pointer to int64_t 113 114// E: pointer to uint8_t 115// F: pointer to uint16_t 116// G: pointer to uint32_t 117// H: pointer to uint64_t 118 119// Q: const pointer to void 120 121// S: const pointer to int8_t 122// T: const pointer to int16_t 123// U: const pointer to int32_t 124// V: const pointer to int64_t 125// 126// W: const pointer to uint8_t 127// X: const pointer to uint16_t 128// Y: const pointer to uint32_t 129// Z: const pointer to uint64_t 130 131// Prototype modifiers added for SVE2p1 132// {: 128b vector 133// }: svcount_t 134 135class MergeType<int val, string suffix=""> { 136 int Value = val; 137 string Suffix = suffix; 138} 139def MergeNone : MergeType<0>; 140def MergeAny : MergeType<1, "_x">; 141def MergeOp1 : MergeType<2, "_m">; 142def MergeZero : MergeType<3, "_z">; 143def MergeAnyExp : MergeType<4, "_x">; // Use merged builtin with explicit 144def MergeZeroExp : MergeType<5, "_z">; // generation of its inactive argument. 145 146class EltType<int val> { 147 int Value = val; 148} 149def EltTyInvalid : EltType<0>; 150def EltTyInt8 : EltType<1>; 151def EltTyInt16 : EltType<2>; 152def EltTyInt32 : EltType<3>; 153def EltTyInt64 : EltType<4>; 154def EltTyInt128 : EltType<5>; 155def EltTyFloat16 : EltType<6>; 156def EltTyFloat32 : EltType<7>; 157def EltTyFloat64 : EltType<8>; 158def EltTyBool8 : EltType<9>; 159def EltTyBool16 : EltType<10>; 160def EltTyBool32 : EltType<11>; 161def EltTyBool64 : EltType<12>; 162def EltTyBFloat16 : EltType<13>; 163 164class MemEltType<int val> { 165 int Value = val; 166} 167def MemEltTyDefault : MemEltType<0>; 168def MemEltTyInt8 : MemEltType<1>; 169def MemEltTyInt16 : MemEltType<2>; 170def MemEltTyInt32 : MemEltType<3>; 171def MemEltTyInt64 : MemEltType<4>; 172 173class FlagType<int val> { 174 int Value = val; 175} 176 177// These must be kept in sync with the flags in utils/TableGen/SveEmitter.h 178// and include/clang/Basic/TargetBuiltins.h 179def NoFlags : FlagType<0x00000000>; 180def FirstEltType : FlagType<0x00000001>; 181// : : 182// : : 183def EltTypeMask : FlagType<0x0000000f>; 184def FirstMemEltType : FlagType<0x00000010>; 185// : : 186// : : 187def MemEltTypeMask : FlagType<0x00000070>; 188def FirstMergeTypeMask : FlagType<0x00000080>; 189// : : 190// : : 191def MergeTypeMask : FlagType<0x00000380>; 192def FirstSplatOperand : FlagType<0x00000400>; 193// : : 194// These flags are used to specify which scalar operand 195// needs to be duplicated/splatted into a vector. 196// : : 197def SplatOperandMask : FlagType<0x00001C00>; 198def IsLoad : FlagType<0x00002000>; 199def IsStore : FlagType<0x00004000>; 200def IsGatherLoad : FlagType<0x00008000>; 201def IsScatterStore : FlagType<0x00010000>; 202def IsStructLoad : FlagType<0x00020000>; 203def IsStructStore : FlagType<0x00040000>; 204def IsZExtReturn : FlagType<0x00080000>; // Return value is sign-extend by default 205def IsOverloadNone : FlagType<0x00100000>; // Intrinsic does not take any overloaded types. 206def IsOverloadWhileOrMultiVecCvt : FlagType<0x00200000>; // Use {default type, typeof(operand1)} as overloaded types. 207def IsOverloadWhileRW : FlagType<0x00400000>; // Use {pred(default type), typeof(operand0)} as overloaded types. 208def IsOverloadCvt : FlagType<0x00800000>; // Use {typeof(operand0), typeof(last operand)} as overloaded types. 209def OverloadKindMask : FlagType<0x00E00000>; // When the masked values are all '0', the default type is used as overload type. 210def IsByteIndexed : FlagType<0x01000000>; 211def IsAppendSVALL : FlagType<0x02000000>; // Appends SV_ALL as the last operand. 212def IsInsertOp1SVALL : FlagType<0x04000000>; // Inserts SV_ALL as the second operand. 213def IsPrefetch : FlagType<0x08000000>; // Contiguous prefetches. 214def IsGatherPrefetch : FlagType<0x10000000>; 215def ReverseCompare : FlagType<0x20000000>; // Compare operands must be swapped. 216def ReverseUSDOT : FlagType<0x40000000>; // Unsigned/signed operands must be swapped. 217def IsUndef : FlagType<0x80000000>; // Codegen `undef` of given type. 218def IsTupleCreate : FlagType<0x100000000>; 219def IsTupleGet : FlagType<0x200000000>; 220def IsTupleSet : FlagType<0x400000000>; 221def ReverseMergeAnyBinOp : FlagType<0x800000000>; // e.g. Implement SUBR_X using SUB_X. 222def ReverseMergeAnyAccOp : FlagType<0x1000000000>; // e.g. Implement MSB_X using MLS_X. 223def IsStreaming : FlagType<0x2000000000>; 224def IsStreamingCompatible : FlagType<0x4000000000>; 225def IsReadZA : FlagType<0x8000000000>; 226def IsWriteZA : FlagType<0x10000000000>; 227def IsReductionQV : FlagType<0x20000000000>; 228def VerifyRuntimeMode : FlagType<0x40000000000>; // Use for intrinsics that are common between SVE and SME. 229def IsInZA : FlagType<0x80000000000>; 230def IsOutZA : FlagType<0x100000000000>; 231def IsInOutZA : FlagType<0x200000000000>; 232def IsInZT0 : FlagType<0x400000000000>; 233def IsOutZT0 : FlagType<0x800000000000>; 234def IsInOutZT0 : FlagType<0x1000000000000>; 235 236// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h 237class ImmCheckType<int val> { 238 int Value = val; 239} 240def ImmCheck0_31 : ImmCheckType<0>; // 0..31 (used for e.g. predicate patterns) 241def ImmCheck1_16 : ImmCheckType<1>; // 1..16 242def ImmCheckExtract : ImmCheckType<2>; // 0..(2048/sizeinbits(elt) - 1) 243def ImmCheckShiftRight : ImmCheckType<3>; // 1..sizeinbits(elt) 244def ImmCheckShiftRightNarrow : ImmCheckType<4>; // 1..sizeinbits(elt)/2 245def ImmCheckShiftLeft : ImmCheckType<5>; // 0..(sizeinbits(elt) - 1) 246def ImmCheck0_7 : ImmCheckType<6>; // 0..7 247def ImmCheckLaneIndex : ImmCheckType<7>; // 0..(128/(1*sizeinbits(elt)) - 1) 248def ImmCheckLaneIndexCompRotate : ImmCheckType<8>; // 0..(128/(2*sizeinbits(elt)) - 1) 249def ImmCheckLaneIndexDot : ImmCheckType<9>; // 0..(128/(4*sizeinbits(elt)) - 1) 250def ImmCheckComplexRot90_270 : ImmCheckType<10>; // [90,270] 251def ImmCheckComplexRotAll90 : ImmCheckType<11>; // [0, 90, 180,270] 252def ImmCheck0_13 : ImmCheckType<12>; // 0..13 253def ImmCheck0_1 : ImmCheckType<13>; // 0..1 254def ImmCheck0_2 : ImmCheckType<14>; // 0..2 255def ImmCheck0_3 : ImmCheckType<15>; // 0..3 256def ImmCheck0_0 : ImmCheckType<16>; // 0..0 257def ImmCheck0_15 : ImmCheckType<17>; // 0..15 258def ImmCheck0_255 : ImmCheckType<18>; // 0..255 259def ImmCheck2_4_Mul2 : ImmCheckType<19>; // 2, 4 260def ImmCheck1_1 : ImmCheckType<20>; // 1..1 261def ImmCheck1_3 : ImmCheckType<21>; // 1..3 262def ImmCheck1_7 : ImmCheckType<22>; // 1..7 263 264class ImmCheck<int arg, ImmCheckType kind, int eltSizeArg = -1> { 265 int Arg = arg; 266 int EltSizeArg = eltSizeArg; 267 ImmCheckType Kind = kind; 268} 269 270defvar InvalidMode = ""; 271 272class Inst<string n, string p, string t, MergeType mt, string i, 273 list<FlagType> ft, list<ImmCheck> ch, MemEltType met = MemEltTyDefault> { 274 string Name = n; 275 string Prototype = p; 276 string Types = t; 277 string SVETargetGuard = "sve"; 278 string SMETargetGuard = "sme"; 279 int Merge = mt.Value; 280 string MergeSuffix = mt.Suffix; 281 string LLVMIntrinsic = i; 282 list<FlagType> Flags = ft; 283 list<ImmCheck> ImmChecks = ch; 284 int MemEltType = met.Value; 285} 286 287// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8") 288class SInst<string n, string p, string t, MergeType mt, string i = "", 289 list<FlagType> ft = [], list<ImmCheck> ch = []> 290 : Inst<n, p, t, mt, i, ft, ch, MemEltTyDefault> { 291} 292 293// MInst: Instructions which access memory 294class MInst<string n, string p, string t, list<FlagType> f, 295 MemEltType met = MemEltTyDefault, string i = "", 296 list<ImmCheck> ch = []> 297 : Inst<n, p, t, MergeNone, i, f, ch, met> { 298} 299