[ARM][MVE] Factor out an IntrinsicMX multiclass.

Summary:
The ACLE intrinsics for MVE contain a lot of pairs of functions with
`_m` and `_x` in the name, wrapping a predicated MVE instruction which
only partially overwrites its output register. They have the common
pattern that the `_m` variant takes an initial argument called
'inactive', of the same type as the return value, supplying the input
value of the output register, so that lanes disabled by the
predication will be taken from that parameter; the `_x` variant omits
that initial argument, and simply sets it to undef.

That common pattern is simple enough to wrap into a multiclass, which
should save a lot of effort in setting up all the rest of the `_x`
variants. In this commit I introduce `multiclass IntrinsicMX` in
`arm_mve_defs.td`, and convert existing generation of m/x pairs to use
it.

This allows me to remove the `PredicatedImmediateVectorShift`
multiclass (from D71065) completely, because the new multiclass makes
it so much simpler that it's not worth bothering to define it at all.

Reviewers: MarkMurrayARM, miyuki

Reviewed By: MarkMurrayARM, miyuki

Subscribers: kristof.beyls, dmgreen, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D71335
This commit is contained in:
Simon Tatham 2019-12-11 12:07:16 +00:00
parent 9a5c849991
commit d290424731
2 changed files with 34 additions and 27 deletions

View File

@ -609,30 +609,21 @@ defm vstrhq: scatter_offset_both<!listconcat(T.All16, T.Int32), u16, 1>;
defm vstrwq: scatter_offset_both<T.All32, u32, 2>; defm vstrwq: scatter_offset_both<T.All32, u32, 2>;
defm vstrdq: scatter_offset_both<T.Int64, u64, 3>; defm vstrdq: scatter_offset_both<T.Int64, u64, 3>;
multiclass PredicatedImmediateVectorShift<
Immediate immtype, string predIntrName, list<dag> unsignedFlag = []> {
foreach predIntr = [IRInt<predIntrName, [Vector, Predicate]>] in {
def _m_n: Intrinsic<Vector, (args Vector:$inactive, Vector:$v,
immtype:$sh, Predicate:$pred),
!con((predIntr $v, $sh), !dag(predIntr, unsignedFlag, ?),
(predIntr $pred, $inactive))>;
def _x_n: Intrinsic<Vector, (args Vector:$v, immtype:$sh,
Predicate:$pred),
!con((predIntr $v, $sh), !dag(predIntr, unsignedFlag, ?),
(predIntr $pred, (undef Vector)))>;
}
}
let params = T.Int in { let params = T.Int in {
def vshlq_n: Intrinsic<Vector, (args Vector:$v, imm_0toNm1:$sh), def vshlq_n: Intrinsic<Vector, (args Vector:$v, imm_0toNm1:$sh),
(shl $v, (splat (Scalar $sh)))>; (shl $v, (splat (Scalar $sh)))>;
defm vshlq: PredicatedImmediateVectorShift<imm_0toNm1, "shl_imm_predicated">; defm vshlq: IntrinsicMX<Vector, (args Vector:$v, imm_0toNm1:$sh,
Predicate:$pred),
(IRInt<"shl_imm_predicated", [Vector, Predicate]>
$v, $sh, $pred, $inactive), "_n">;
let pnt = PNT_NType in { let pnt = PNT_NType in {
def vshrq_n: Intrinsic<Vector, (args Vector:$v, imm_1toN:$sh), def vshrq_n: Intrinsic<Vector, (args Vector:$v, imm_1toN:$sh),
(immshr $v, $sh, (unsignedflag Scalar))>; (immshr $v, $sh, (unsignedflag Scalar))>;
defm vshrq: PredicatedImmediateVectorShift<imm_1toN, "shr_imm_predicated", defm vshrq: IntrinsicMX<Vector, (args Vector:$v, imm_1toN:$sh,
[(unsignedflag Scalar)]>; Predicate:$pred),
(IRInt<"shr_imm_predicated", [Vector, Predicate]>
$v, $sh, (unsignedflag Scalar), $pred, $inactive), "_n">;
} }
} }
@ -713,25 +704,17 @@ def vadciq_m: Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b,
multiclass VectorComplexAddPred<dag not_halving, dag angle> { multiclass VectorComplexAddPred<dag not_halving, dag angle> {
def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b), def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b),
(IRInt<"vcaddq", [Vector]> not_halving, angle, $a, $b)>; (IRInt<"vcaddq", [Vector]> not_halving, angle, $a, $b)>;
def _m : Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b, defm "" : IntrinsicMX<Vector, (args Vector:$a, Vector:$b, Predicate:$pred),
Predicate:$pred),
(IRInt<"vcaddq_predicated", [Vector, Predicate]> (IRInt<"vcaddq_predicated", [Vector, Predicate]>
not_halving, angle, $inactive, $a, $b, $pred)>; not_halving, angle, $inactive, $a, $b, $pred)>;
def _x : Intrinsic<Vector, (args Vector:$a, Vector:$b, Predicate:$pred),
(IRInt<"vcaddq_predicated", [Vector, Predicate]>
not_halving, angle, (undef Vector), $a, $b, $pred)>;
} }
multiclass VectorComplexMulPred<dag angle> { multiclass VectorComplexMulPred<dag angle> {
def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b), def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b),
(IRInt<"vcmulq", [Vector]> angle, $a, $b)>; (IRInt<"vcmulq", [Vector]> angle, $a, $b)>;
def _m : Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b, defm "" : IntrinsicMX<Vector, (args Vector:$a, Vector:$b, Predicate:$pred),
Predicate:$pred),
(IRInt<"vcmulq_predicated", [Vector, Predicate]> angle, $inactive, $a, $b, (IRInt<"vcmulq_predicated", [Vector, Predicate]> angle, $inactive, $a, $b,
$pred)>; $pred)>;
def _x : Intrinsic<Vector, (args Vector:$a, Vector:$b, Predicate:$pred),
(IRInt<"vcmulq_predicated", [Vector, Predicate]> angle, (undef Vector), $a,
$b, $pred)>;
} }
multiclass VectorComplexMLAPred<dag angle> { multiclass VectorComplexMLAPred<dag angle> {

View File

@ -432,6 +432,30 @@ class NameOverride<string basename_> {
string basename = basename_; string basename = basename_;
} }
// A wrapper to define both _m and _x versions of a predicated
// intrinsic.
multiclass IntrinsicMX<Type rettype, dag arguments, dag cg,
string nameSuffix = "",
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>;
// The _x variant leaves off that parameter, and simply uses an
// undef value of the same type.
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).
let pnt = pnt_x;
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Convenience lists of parameter types. 'T' is just a container record, so you // 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, // can define a typical intrinsic with 'let Params = T.Usual', or similar,