Simplify vec_merge of vec_duplicate with const_vector
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Wed, 8 Nov 2017 18:23:35 +0000 (18:23 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Wed, 8 Nov 2017 18:23:35 +0000 (18:23 +0000)
I'm trying to improve some of the RTL-level handling of vector lane operations on aarch64 and that
involves dealing with a lot of vec_merge operations. One simplification that I noticed missing
from simplify-rtx are combinations of vec_merge with vec_duplicate.
In this particular case:
(vec_merge (vec_duplicate (X)) (const_vector [A, B]) (const_int N))

which can be replaced with

(vec_concat (X) (B)) if N == 1 (0b01) or
(vec_concat (A) (X)) if N == 2 (0b10).

For the aarch64 testcase in this patch this simplifications allows us to try to combine:
(set (reg:V2DI 77 [ x ])
    (vec_concat:V2DI (mem:DI (reg:DI 0 x0 [ y ]) [1 *y_3(D)+0 S8 A64])
        (const_int 0 [0])))

instead of the more complex:
(set (reg:V2DI 77 [ x ])
    (vec_merge:V2DI (vec_duplicate:V2DI (mem:DI (reg:DI 0 x0 [ y ]) [1 *y_3(D)+0 S8 A64]))
        (const_vector:V2DI [
                (const_int 0 [0])
                (const_int 0 [0])
            ])
        (const_int 1 [0x1])))

For the simplified form above we already have an aarch64 pattern: *aarch64_combinez<mode> which
is missing a DI/DFmode version due to an oversight, so this patch extends that pattern as well to
use the VDC mode iterator that includes DI and DFmode (as well as V2HF which VD_BHSI was missing).
The aarch64 hunk is needed to see the benefit of the simplify-rtx.c hunk, so I didn't split them
into separate patches.

Before this for the testcase we'd generate:
construct_lanedi:
        movi    v0.4s, 0
        ldr     x0, [x0]
        ins     v0.d[0], x0
        ret

construct_lanedf:
        movi    v0.2d, 0
        ldr     d1, [x0]
        ins     v0.d[0], v1.d[0]
        ret

but now we can generate:
construct_lanedi:
        ldr     d0, [x0]
        ret

construct_lanedf:
        ldr     d0, [x0]
        ret

Bootstrapped and tested on aarch64-none-linux-gnu.

* simplify-rtx.c (simplify_ternary_operation, VEC_MERGE):
Simplify vec_merge of vec_duplicate and const_vector.
* config/aarch64/predicates.md (aarch64_simd_or_scalar_imm_zero):
New predicate.
* config/aarch64/aarch64-simd.md (*aarch64_combinez<mode>): Use VDC
mode iterator.  Update predicate on operand 1 to
handle non-const_vec constants.  Delete constraints.
(*aarch64_combinez_be<mode>): Likewise for operand 2.

* gcc.target/aarch64/construct_lane_zero_1.c: New test.

From-SVN: r254548

gcc/ChangeLog
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/predicates.md
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/construct_lane_zero_1.c [new file with mode: 0644]

index 7b13408ddfffb5eb817d707d72e31a28a6b8cb4c..d1225c3a94d88781f8aec592e18bbf7729fe139e 100644 (file)
@@ -1,3 +1,14 @@
+2017-11-08  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * simplify-rtx.c (simplify_ternary_operation, VEC_MERGE):
+       Simplify vec_merge of vec_duplicate and const_vector.
+       * config/aarch64/predicates.md (aarch64_simd_or_scalar_imm_zero):
+       New predicate.
+       * config/aarch64/aarch64-simd.md (*aarch64_combinez<mode>): Use VDC
+       mode iterator.  Update predicate on operand 1 to
+       handle non-const_vec constants.  Delete constraints.
+       (*aarch64_combinez_be<mode>): Likewise for operand 2.
+
 2017-11-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/78821
index 9aeeffd27b02901c6bbca7917de592a35b4a2cd5..34233f68cbae1fe75eb744ef0072aad7ca641883 100644 (file)
 
 (define_insn "*aarch64_combinez<mode>"
   [(set (match_operand:<VDBL> 0 "register_operand" "=w,w,w")
-        (vec_concat:<VDBL>
-          (match_operand:VD_BHSI 1 "general_operand" "w,?r,m")
-          (match_operand:VD_BHSI 2 "aarch64_simd_imm_zero" "Dz,Dz,Dz")))]
+       (vec_concat:<VDBL>
+         (match_operand:VDC 1 "general_operand" "w,?r,m")
+         (match_operand:VDC 2 "aarch64_simd_or_scalar_imm_zero")))]
   "TARGET_SIMD && !BYTES_BIG_ENDIAN"
   "@
    mov\\t%0.8b, %1.8b
 (define_insn "*aarch64_combinez_be<mode>"
   [(set (match_operand:<VDBL> 0 "register_operand" "=w,w,w")
         (vec_concat:<VDBL>
-          (match_operand:VD_BHSI 2 "aarch64_simd_imm_zero" "Dz,Dz,Dz")
-          (match_operand:VD_BHSI 1 "general_operand" "w,?r,m")))]
+         (match_operand:VDC 2 "aarch64_simd_or_scalar_imm_zero")
+         (match_operand:VDC 1 "general_operand" "w,?r,m")))]
   "TARGET_SIMD && BYTES_BIG_ENDIAN"
   "@
    mov\\t%0.8b, %1.8b
index bf23b88cb596a6374250e2bba08fc58ea420e5c0..84d441a1cf6d3a7a6bf548132195c6105b3bd3a8 100644 (file)
   return aarch64_simd_imm_zero_p (op, mode);
 })
 
+(define_special_predicate "aarch64_simd_or_scalar_imm_zero"
+  (match_test "aarch64_simd_imm_zero_p (op, mode)"))
+
 (define_special_predicate "aarch64_simd_imm_minus_one"
   (match_code "const_vector")
 {
index 5cdea355ecdf299e22720e68b29d0de96ac3e0f2..94302f6d00962251eab7cdeb7018bfe5f139a876 100644 (file)
@@ -5749,6 +5749,22 @@ simplify_ternary_operation (enum rtx_code code, machine_mode mode,
                    return op1;
                }
            }
+         /* Replace (vec_merge (vec_duplicate (X)) (const_vector [A, B])
+            (const_int N))
+            with (vec_concat (X) (B)) if N == 1 or
+            (vec_concat (A) (X)) if N == 2.  */
+         if (GET_CODE (op0) == VEC_DUPLICATE
+             && GET_CODE (op1) == CONST_VECTOR
+             && CONST_VECTOR_NUNITS (op1) == 2
+             && GET_MODE_NUNITS (GET_MODE (op0)) == 2
+             && IN_RANGE (sel, 1, 2))
+           {
+             rtx newop0 = XEXP (op0, 0);
+             rtx newop1 = CONST_VECTOR_ELT (op1, 2 - sel);
+             if (sel == 2)
+               std::swap (newop0, newop1);
+             return simplify_gen_binary (VEC_CONCAT, mode, newop0, newop1);
+           }
        }
 
       if (rtx_equal_p (op0, op1)
index d4a0b0f3c26a96d2bdf4161a4829cdc78d0fa33f..28894ee07a1603b2a91f2be8155a8b7f0119cd0d 100644 (file)
@@ -1,3 +1,7 @@
+2017-11-08  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * gcc.target/aarch64/construct_lane_zero_1.c: New test.
+
 2017-11-08  Ed Schonberg  <schonberg@adacore.com>
 
        * gnat.dg/delta_aggr.adb: New testcase.
diff --git a/gcc/testsuite/gcc.target/aarch64/construct_lane_zero_1.c b/gcc/testsuite/gcc.target/aarch64/construct_lane_zero_1.c
new file mode 100644 (file)
index 0000000..d87f329
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef long long v2di __attribute__ ((vector_size (16)));
+typedef double v2df __attribute__ ((vector_size (16)));
+
+v2di
+construct_lanedi (long long *y)
+{
+  v2di x =
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+  { 0, y[0] }
+#else
+  { y[0], 0 }
+#endif
+  ;
+  return x;
+}
+
+v2df
+construct_lanedf (double *y)
+{
+  v2df x =
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+  { 0.0, y[0] }
+#else
+  { y[0], 0.0 }
+#endif
+  ;
+  return x;
+}
+
+/* Check that creating V2DI and V2DF vectors from a lane with a zero
+   makes use of the D-reg LDR rather than doing explicit lane inserts.  */
+
+/* { dg-final { scan-assembler-times "ldr\td\[0-9\]+" 2 } } */
+/* { dg-final { scan-assembler-not "ins\t" } } */