[ARM][MVE] Factor out an IntrinsicMX multiclass.
authorSimon Tatham <simon.tatham@arm.com>
Wed, 11 Dec 2019 12:07:16 +0000 (12:07 +0000)
committerSimon Tatham <simon.tatham@arm.com>
Wed, 11 Dec 2019 12:07:26 +0000 (12:07 +0000)
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

clang/include/clang/Basic/arm_mve.td
clang/include/clang/Basic/arm_mve_defs.td

index 9b6053e..7ed3c04 100644 (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 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 {
   def vshlq_n: Intrinsic<Vector, (args Vector:$v, imm_0toNm1:$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 {
     def vshrq_n: Intrinsic<Vector, (args Vector:$v, imm_1toN:$sh),
                             (immshr $v, $sh, (unsignedflag Scalar))>;
-    defm vshrq: PredicatedImmediateVectorShift<imm_1toN, "shr_imm_predicated",
-                                     [(unsignedflag Scalar)]>;
+    defm vshrq: IntrinsicMX<Vector, (args Vector:$v, imm_1toN:$sh,
+                                          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> {
   def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b),
      (IRInt<"vcaddq", [Vector]> not_halving, angle, $a, $b)>;
-  def _m : Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b,
-                              Predicate:$pred),
+  defm "" : IntrinsicMX<Vector, (args Vector:$a, Vector:$b, Predicate:$pred),
      (IRInt<"vcaddq_predicated", [Vector, Predicate]>
        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> {
   def "" : Intrinsic<Vector, (args Vector:$a, Vector:$b),
     (IRInt<"vcmulq", [Vector]> angle, $a, $b)>;
-  def _m : Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b,
-                              Predicate:$pred),
+  defm "" : IntrinsicMX<Vector, (args Vector:$a, Vector:$b, Predicate:$pred),
     (IRInt<"vcmulq_predicated", [Vector, Predicate]> angle, $inactive, $a, $b,
       $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> {
index 6bc9b35..3e22e44 100644 (file)
@@ -432,6 +432,30 @@ class NameOverride<string 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
 // can define a typical intrinsic with 'let Params = T.Usual', or similar,