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