diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Basic/arm_mve_defs.td')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/Basic/arm_mve_defs.td | 109 |
1 files changed, 97 insertions, 12 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Basic/arm_mve_defs.td b/contrib/llvm-project/clang/include/clang/Basic/arm_mve_defs.td index a9afddb57968..4038a18027f8 100644 --- a/contrib/llvm-project/clang/include/clang/Basic/arm_mve_defs.td +++ b/contrib/llvm-project/clang/include/clang/Basic/arm_mve_defs.td @@ -57,6 +57,10 @@ class CGHelperFn<string func> : IRBuilderBase { // an argument. let prefix = func # "(Builder, "; } +class CGFHelperFn<string func> : IRBuilderBase { + // Like CGHelperFn, but also takes the CodeGenFunction itself. + let prefix = func # "(Builder, this, "; +} def add: IRBuilder<"CreateAdd">; def mul: IRBuilder<"CreateMul">; def not: IRBuilder<"CreateNot">; @@ -89,10 +93,14 @@ def ielt_var: IRBuilder<"CreateInsertElement">; def xelt_var: IRBuilder<"CreateExtractElement">; def trunc: IRBuilder<"CreateTrunc">; def bitcast: IRBuilder<"CreateBitCast">; +def vreinterpret: CGFHelperFn<"ARMMVEVectorReinterpret">; def extend: CGHelperFn<"SignOrZeroExtend"> { let special_params = [IRBuilderIntParam<2, "bool">]; } def zeroinit: IRFunction<"llvm::Constant::getNullValue">; +def int_min: CGHelperFn<"ARMMVEConstantSplat<1,0>">; +def int_max: CGHelperFn<"ARMMVEConstantSplat<0,1>">; +def uint_max: CGHelperFn<"ARMMVEConstantSplat<1,1>">; def undef: IRFunction<"UndefValue::get">; def icmp_eq: IRBuilder<"CreateICmpEQ">; def icmp_ne: IRBuilder<"CreateICmpNE">; @@ -112,6 +120,36 @@ def fcmp_lt: IRBuilder<"CreateFCmpOLT">; def fcmp_le: IRBuilder<"CreateFCmpOLE">; def splat: CGHelperFn<"ARMMVEVectorSplat">; def select: IRBuilder<"CreateSelect">; +def fneg: IRBuilder<"CreateFNeg">; +def sitofp: IRBuilder<"CreateSIToFP">; +def uitofp: IRBuilder<"CreateUIToFP">; +def fptosi: IRBuilder<"CreateFPToSI">; +def fptoui: IRBuilder<"CreateFPToUI">; +def vrev: CGHelperFn<"ARMMVEVectorElementReverse"> { + let special_params = [IRBuilderIntParam<1, "unsigned">]; +} +def unzip: CGHelperFn<"VectorUnzip"> { + let special_params = [IRBuilderIntParam<1, "bool">]; +} +def zip: CGHelperFn<"VectorZip">; + +// Trivial 'codegen' function that just returns its argument. Useful +// for wrapping up a variable name like $foo into a thing you can pass +// around as type 'dag'. +def id: IRBuilderBase { + // All the other cases of IRBuilderBase use 'prefix' to specify a function + // call, including the open parenthesis. MveEmitter puts the closing paren on + // the end. So if we _just_ specify an open paren with no function name + // before it, then the generated C++ code will simply wrap the input value in + // parentheses, returning it unchanged. + let prefix = "("; +} + +// Helper for making boolean flags in IR +def i1: IRBuilderBase { + let prefix = "llvm::ConstantInt::get(Builder.getInt1Ty(), "; + let special_params = [IRBuilderIntParam<0, "bool">]; +} // A node that makes an Address out of a pointer-typed Value, by // providing an alignment as the second argument. @@ -162,6 +200,10 @@ def seq; // and 0 for a signed (or floating) one. def unsignedflag; +// 'bitsize' also takes a scalar type, and expands into an integer +// constant giving its size in bits. +def bitsize; + // If you put CustomCodegen<"foo"> in an intrinsic's codegen field, it // indicates that the IR generation for that intrinsic is done by handwritten // C++ and not autogenerated at all. The effect in the MVE builtin codegen @@ -288,11 +330,15 @@ def SScalar: Signed<Scalar>; def SVector: VecOf<SScalar>; // DblVector expands to a vector of scalars of size twice the size of Scalar. +// DblPredicate expands to a predicate corresponding to DblVector // HalfVector, similarly, expands to a vector of half-sized scalars. And // UHalfVector is a vector of half-sized _unsigned integers_. def DblVector: VecOf<DoubleSize<Scalar>>; -def HalfVector: VecOf<HalfSize<Scalar>>; -def UHalfVector: VecOf<Unsigned<HalfSize<Scalar>>>; +def DblPredicate: PredOf<DoubleSize<Scalar>>; +def HalfScalar: HalfSize<Scalar>; +def HalfVector: VecOf<HalfScalar>; +def UHalfScalar: Unsigned<HalfSize<Scalar>>; +def UHalfVector: VecOf<UHalfScalar>; // Expands to the 32-bit integer of the same signedness as Scalar. def Scalar32: CopyKind<u32, Scalar>; @@ -319,6 +365,7 @@ class IB_EltBit<int base_, Type type_ = Scalar> : ImmediateBounds { int base = base_; Type type = type_; } +def IB_ExtraArg_LaneSize; // ----------------------------------------------------------------------------- // End-user definitions for immediate arguments. @@ -327,11 +374,13 @@ class IB_EltBit<int base_, Type type_ = Scalar> : ImmediateBounds { // intrinsics like vmvnq or vorrq. imm_simd_restrictive has to be an 8-bit // value shifted left by a whole number of bytes; imm_simd_vmvn can also be of // the form 0xXXFF for some byte value XX. -def imm_simd_restrictive : Immediate<u32, IB_UEltValue> { +def imm_simd_restrictive : Immediate<Scalar, IB_UEltValue> { let extra = "ShiftedByte"; + let extraarg = "!lanesize"; } -def imm_simd_vmvn : Immediate<u32, IB_UEltValue> { +def imm_simd_vmvn : Immediate<Scalar, IB_UEltValue> { let extra = "ShiftedByteOrXXFF"; + let extraarg = "!lanesize"; } // imm_1toN can take any value from 1 to N inclusive, where N is the number of @@ -356,7 +405,7 @@ def imm_lane : Immediate<sint, IB_LaneIndex>; def imm_1to32 : Immediate<sint, IB_ConstRange<1, 32>>; // imm_1248 can be 1, 2, 4 or 8. (e.g. vidupq) -def imm_1248 : Immediate<u32, IB_ConstRange<1, 8>> { +def imm_1248 : Immediate<sint, IB_ConstRange<1, 8>> { let extra = "Power2"; } @@ -439,9 +488,16 @@ class Intrinsic<Type ret_, dag args_, dag codegen_> { // True if the builtin has to avoid evaluating its arguments. bit nonEvaluating = 0; + // True if the intrinsic needs only the C header part (no codegen, semantic + // checks, etc). Used for redeclaring MVE intrinsics in the arm_cde.h header. + bit headerOnly = 0; + // Use to override the suffix letter to make e.g.vfooq_p16 // with an override suffix letter of "p". string overrideKindLetter = ""; + + // Name of the architecture extension, used in the Clang builtin name + string builtinExtension = "mve"; } // Sometimes you have to use two separate Intrinsic declarations to @@ -457,37 +513,66 @@ class NameOverride<string basename_> { // A wrapper to define both _m and _x versions of a predicated // intrinsic. +// +// We provide optional parameters to override the polymorphic name +// types separately for the _m and _x variants, because sometimes they +// polymorph differently (typically because the type of the inactive +// parameter can be used as a disambiguator if it's present). multiclass IntrinsicMX<Type rettype, dag arguments, dag cg, int wantXVariant = 1, string nameSuffix = "", + PolymorphicNameType pnt_m = PNT_Type, PolymorphicNameType pnt_x = PNT_Type> { // The _m variant takes an initial parameter called $inactive, which // provides the input value of the output register, i.e. all the // inactive lanes in the predicated operation take their values from // this. - def "_m" # nameSuffix: - Intrinsic<rettype, !con((args rettype:$inactive), arguments), cg>; + def : Intrinsic<rettype, !con((args rettype:$inactive), arguments), cg>, + NameOverride<NAME # "_m" # nameSuffix> { + let pnt = pnt_m; + } foreach unusedVar = !if(!eq(wantXVariant, 1), [1], []<int>) in { // The _x variant leaves off that parameter, and simply uses an // undef value of the same type. + + def : Intrinsic<rettype, arguments, (seq (undef rettype):$inactive, cg)>, + NameOverride<NAME # "_x" # nameSuffix> { + let pnt = pnt_x; + } + } +} + +// Same as above, but with an additional parameter 'basename' which overrides +// the C intrinsic base name +multiclass IntrinsicMXNameOverride<Type rettype, dag arguments, dag cg, + string basename, int wantXVariant = 1, + string nameSuffix = "", + PolymorphicNameType pnt_m = PNT_Type, + PolymorphicNameType pnt_x = PNT_Type> { + def "_m" # nameSuffix: + Intrinsic<rettype, !con((args rettype:$inactive), arguments), cg>, + NameOverride<basename # "_m" # nameSuffix> { + let pnt = pnt_m; + } + + foreach unusedVar = !if(!eq(wantXVariant, 1), [1], []<int>) in { def "_x" # nameSuffix: - Intrinsic<rettype, arguments, (seq (undef rettype):$inactive, cg)> { - // Allow overriding of the polymorphic name type, because - // sometimes the _m and _x variants polymorph differently - // (typically because the type of the inactive parameter can be - // used as a disambiguator if it's present). + Intrinsic<rettype, arguments, (seq (undef rettype):$inactive, cg)>, + NameOverride<basename # "_x" # nameSuffix> { let pnt = pnt_x; } } } + // ----------------------------------------------------------------------------- // Convenience lists of parameter types. 'T' is just a container record, so you // can define a typical intrinsic with 'let Params = T.Usual', or similar, // instead of having to repeat a long list every time. def T { + list<Type> None = [Void]; list<Type> Signed = [s8, s16, s32]; list<Type> Unsigned = [u8, u16, u32]; list<Type> Int = Signed # Unsigned; |