aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/include/clang/Basic/arm_mve_defs.td
diff options
context:
space:
mode:
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.td109
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;