[AARCH64][PATCH 1/3] Implementing the variants of the vmulx_ NEON intrinsic
authorBilyan Borisov <bilyan.borisov@arm.com>
Tue, 3 Nov 2015 10:58:27 +0000 (10:58 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Tue, 3 Nov 2015 10:58:27 +0000 (10:58 +0000)
gcc/

* config/aarch64/aarch64-simd-builtins.def (fmulx): New.
* config/aarch64/aarch64-simd.md (aarch64_fmulx<mode>): New.
* config/aarch64/arm_neon.h (vmulx_f32): Rewrite to call fmulx
builtin.
(vmulxq_f32): Likewise.
(vmulx_f64): New.
(vmulxq_f64): Rewrite to call fmulx builtin.
(vmulxs_f32): Likewise.
(vmulxd_f64): Likewise.
(vmulx_lane_f32): Remove.
* config/aarch64/iterators.md (UNSPEC): Add fmulx.

gcc/testsuite/

* gcc/testsuite/gcc.target/aarch64/simd/vmulx_f32_1.c: New.
* gcc/testsuite/gcc.target/aarch64/simd/vmulx_f64_1.c: New.
* gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f32_1.c: New.
* gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f64_1.c: New.
* gcc/testsuite/gcc.target/aarch64/simd/vmulxs_f32_1.c: New.
* gcc/testsuite/gcc.target/aarch64/simd/vmulxd_f64_1.c: New.

From-SVN: r229702

12 files changed:
gcc/ChangeLog
gcc/config/aarch64/aarch64-simd-builtins.def
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/arm_neon.h
gcc/config/aarch64/iterators.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/simd/vmulx_f32_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/simd/vmulx_f64_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/simd/vmulxd_f64_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f32_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f64_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/simd/vmulxs_f32_1.c [new file with mode: 0644]

index 204716ecb0a85d73d4e1c0c315fcdbc563746286..5459551b1f7604a0715974a82e5afa8754525829 100644 (file)
@@ -1,3 +1,17 @@
+2015-11-03  Bilyan Borisov  <bilyan.borisov@arm.com>
+
+       * config/aarch64/aarch64-simd-builtins.def (fmulx): New.
+       * config/aarch64/aarch64-simd.md (aarch64_fmulx<mode>): New.
+       * config/aarch64/arm_neon.h (vmulx_f32): Rewrite to call fmulx
+       builtin.
+       (vmulxq_f32): Likewise.
+       (vmulx_f64): New.
+       (vmulxq_f64): Rewrite to call fmulx builtin.
+       (vmulxs_f32): Likewise.
+       (vmulxd_f64): Likewise.
+       (vmulx_lane_f32): Remove.
+       * config/aarch64/iterators.md (UNSPEC): Add fmulx.
+
 2015-11-03  Alan Lawrence  <alan.lawrence@arm.com>
 
        * config/aarch64/aarch64.md (*movhf_aarch64): Use
index 654e963fa537e3dbc1b950cb30f4156c8cc049aa..04dac6f84db2393ef5057b7ddb04b7ed026c8a72 100644 (file)
@@ -41,6 +41,7 @@
 
   BUILTIN_VDC (COMBINE, combine, 0)
   BUILTIN_VB (BINOP, pmul, 0)
+  BUILTIN_VALLF (BINOP, fmulx, 0)
   BUILTIN_VDQF_DF (UNOP, sqrt, 2)
   BUILTIN_VD_BHSI (BINOP, addp, 0)
   VAR1 (UNOP, addp, 0, di)
index 65a2b6fad64f9210e10c45da7089dfca24e69e71..269e00237bb1153ebf42505906ec5b760b04aafe 100644 (file)
   [(set_attr "type" "neon_mul_<Vetype><q>")]
 )
 
+;; fmulx.
+
+(define_insn "aarch64_fmulx<mode>"
+  [(set (match_operand:VALLF 0 "register_operand" "=w")
+       (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w")
+                      (match_operand:VALLF 2 "register_operand" "w")]
+                     UNSPEC_FMULX))]
+ "TARGET_SIMD"
+ "fmulx\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
+ [(set_attr "type" "neon_fp_mul_<Vetype>")]
+)
+
 ;; <su>q<addsub>
 
 (define_insn "aarch64_<su_optab><optab><mode>"
index e1863488b73ed6d55bc2739ab2c19a907dc85fee..265c26679089f5a1b30a41360687fb1e3c2a8e50 100644 (file)
@@ -8509,63 +8509,6 @@ vmulq_n_u32 (uint32x4_t a, uint32_t b)
   return result;
 }
 
-__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
-vmulx_f32 (float32x2_t a, float32x2_t b)
-{
-  float32x2_t result;
-  __asm__ ("fmulx %0.2s,%1.2s,%2.2s"
-           : "=w"(result)
-           : "w"(a), "w"(b)
-           : /* No clobbers */);
-  return result;
-}
-
-#define vmulx_lane_f32(a, b, c)                                         \
-  __extension__                                                         \
-    ({                                                                  \
-       float32x4_t b_ = (b);                                            \
-       float32x2_t a_ = (a);                                            \
-       float32x2_t result;                                              \
-       __asm__ ("fmulx %0.2s,%1.2s,%2.s[%3]"                            \
-                : "=w"(result)                                          \
-                : "w"(a_), "w"(b_), "i"(c)                              \
-                : /* No clobbers */);                                   \
-       result;                                                          \
-     })
-
-__extension__ static __inline float64_t __attribute__ ((__always_inline__))
-vmulxd_f64 (float64_t a, float64_t b)
-{
-  float64_t result;
-  __asm__ ("fmulx %d0, %d1, %d2"
-           : "=w"(result)
-           : "w"(a), "w"(b)
-           : /* No clobbers */);
-  return result;
-}
-
-__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
-vmulxq_f32 (float32x4_t a, float32x4_t b)
-{
-  float32x4_t result;
-  __asm__ ("fmulx %0.4s,%1.4s,%2.4s"
-           : "=w"(result)
-           : "w"(a), "w"(b)
-           : /* No clobbers */);
-  return result;
-}
-
-__extension__ static __inline float64x2_t __attribute__ ((__always_inline__))
-vmulxq_f64 (float64x2_t a, float64x2_t b)
-{
-  float64x2_t result;
-  __asm__ ("fmulx %0.2d,%1.2d,%2.2d"
-           : "=w"(result)
-           : "w"(a), "w"(b)
-           : /* No clobbers */);
-  return result;
-}
-
 #define vmulxq_lane_f32(a, b, c)                                        \
   __extension__                                                         \
     ({                                                                  \
@@ -8592,17 +8535,6 @@ vmulxq_f64 (float64x2_t a, float64x2_t b)
        result;                                                          \
      })
 
-__extension__ static __inline float32_t __attribute__ ((__always_inline__))
-vmulxs_f32 (float32_t a, float32_t b)
-{
-  float32_t result;
-  __asm__ ("fmulx %s0, %s1, %s2"
-           : "=w"(result)
-           : "w"(a), "w"(b)
-           : /* No clobbers */);
-  return result;
-}
-
 __extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
 vmvn_p8 (poly8x8_t a)
 {
@@ -17739,6 +17671,43 @@ vmaxq_u32 (uint32x4_t __a, uint32x4_t __b)
   return (uint32x4_t) __builtin_aarch64_umaxv4si ((int32x4_t) __a,
                                                  (int32x4_t) __b);
 }
+/* vmulx */
+
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vmulx_f32 (float32x2_t __a, float32x2_t __b)
+{
+  return __builtin_aarch64_fmulxv2sf (__a, __b);
+}
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vmulxq_f32 (float32x4_t __a, float32x4_t __b)
+{
+  return __builtin_aarch64_fmulxv4sf (__a, __b);
+}
+
+__extension__ static __inline float64x1_t __attribute__ ((__always_inline__))
+vmulx_f64 (float64x1_t __a, float64x1_t __b)
+{
+  return (float64x1_t) {__builtin_aarch64_fmulxdf (__a[0], __b[0])};
+}
+
+__extension__ static __inline float64x2_t __attribute__ ((__always_inline__))
+vmulxq_f64 (float64x2_t __a, float64x2_t __b)
+{
+  return __builtin_aarch64_fmulxv2df (__a, __b);
+}
+
+__extension__ static __inline float32_t __attribute__ ((__always_inline__))
+vmulxs_f32 (float32_t __a, float32_t __b)
+{
+  return __builtin_aarch64_fmulxsf (__a, __b);
+}
+
+__extension__ static __inline float64_t __attribute__ ((__always_inline__))
+vmulxd_f64 (float64_t __a, float64_t __b)
+{
+  return __builtin_aarch64_fmulxdf (__a, __b);
+}
 
 /* vpmax  */
 
index 964f8f1af68cfb8b02919a616e1feb6fad466fdc..6f35036b0132a615ecc7318a5498f7d61db7950b 100644 (file)
     UNSPEC_SQDMULH     ; Used in aarch64-simd.md.
     UNSPEC_SQRDMULH    ; Used in aarch64-simd.md.
     UNSPEC_PMUL                ; Used in aarch64-simd.md.
+    UNSPEC_FMULX       ; Used in aarch64-simd.md.
     UNSPEC_USQADD      ; Used in aarch64-simd.md.
     UNSPEC_SUQADD      ; Used in aarch64-simd.md.
     UNSPEC_SQXTUN      ; Used in aarch64-simd.md.
index 48185b38131fc8ab28a98dcfd3a298de1ce87e63..1de0ea186a89a5a6b65fe491732e79f16425df54 100644 (file)
@@ -1,3 +1,12 @@
+2015-11-03  Bilyan Borisov  <bilyan.borisov@arm.com>
+
+       * gcc/testsuite/gcc.target/aarch64/simd/vmulx_f32_1.c: New.
+       * gcc/testsuite/gcc.target/aarch64/simd/vmulx_f64_1.c: New.
+       * gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f32_1.c: New.
+       * gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f64_1.c: New.
+       * gcc/testsuite/gcc.target/aarch64/simd/vmulxs_f32_1.c: New.
+       * gcc/testsuite/gcc.target/aarch64/simd/vmulxd_f64_1.c: New.
+
 2015-11-03  Alan Lawrence  <alan.lawrence@arm.com>
 
        * gcc.target/aarch64/fp16/set_zero_1.c: New.
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulx_f32_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmulx_f32_1.c
new file mode 100644 (file)
index 0000000..d0d26c5
--- /dev/null
@@ -0,0 +1,52 @@
+/* Test the vmulx_f32 AArch64 SIMD intrinsic.  */
+
+/* { dg-do run } */
+/* { dg-options "-save-temps -O3" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+void __attribute__ ((noinline))
+test_case (float32_t v1[2], float32_t v2[2], float32_t e[2])
+{
+  int i;
+  float32x2_t vec1_1 = vld1_f32 (v1);
+  float32x2_t vec1_2 = vld1_f32 (v2);
+
+  float32x2_t actual1 = vmulx_f32 (vec1_1, vec1_2);
+  float32_t actual[2];
+  vst1_f32 (actual, actual1);
+
+  for (i = 0; i < 2; ++i)
+    if (actual[i] != e[i])
+      abort ();
+}
+
+int
+main (void)
+{
+  float32_t v1 = 3.14159265359;
+  float32_t v2 = 1.383894;
+  float32_t v3 = -2.71828;
+  float32_t v4 = -3.4891931;
+
+  float32_t v1_1[] = {v1, v2};
+  float32_t v1_2[] = {v3, v4};
+  float32_t e1[] = {v1 * v3, v2 * v4};
+  test_case (v1_1, v1_2, e1);
+
+  float32_t v2_1[] = {0, -0.0};
+  float32_t v2_2[] = {__builtin_huge_valf (), __builtin_huge_valf ()};
+  float32_t e2[] = {2.0, -2.0};
+  test_case (v2_1, v2_2, e2);
+
+  float32_t v3_1[] = {0, -0.0};
+  float32_t v3_2[] = {-__builtin_huge_valf (), -__builtin_huge_valf ()};
+  float32_t e3[] = {-2.0, 2.0};
+  test_case (v3_1, v3_2, e3);
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "fmulx\[ \t\]+\[vV\]\[0-9\]+\.2s, ?\[vV\]\[0-9\]+\.2s, ?\[vV\]\[0-9\]+\.2s\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulx_f64_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmulx_f64_1.c
new file mode 100644 (file)
index 0000000..5791d8a
--- /dev/null
@@ -0,0 +1,57 @@
+/* Test the vmulx_f64 AArch64 SIMD intrinsic.  */
+
+/* { dg-do run } */
+/* { dg-options "-save-temps -O3" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+void  __attribute__ ((noinline))
+test_case (float64_t v1[1], float64_t v2[1], float64_t e1[1])
+{
+  float64x1_t vec1_1 = vld1_f64 (v1);
+  float64x1_t vec1_2 = vld1_f64 (v2);
+
+  float64x1_t actual1 = vmulx_f64 (vec1_1, vec1_2);
+  float64_t actual[1];
+  vst1_f64 (actual, actual1);
+  if (actual[0] != e1[0])
+    abort ();
+}
+
+int
+main (void)
+{
+  float64_t v1 = 3.14159265359;
+  float64_t v2 = -2.71828;
+
+  float64_t v1_1[] = {v1};
+  float64_t v1_2[] = {v2};
+  float64_t e1[] = {v1 * v2};
+  test_case (v1_1, v1_2, e1);
+
+  float64_t v2_1[] = {0};
+  float64_t v2_2[] = {__builtin_huge_val ()};
+  float64_t e2[] = {2.0};
+  test_case (v2_1, v2_2, e2);
+
+  float64_t v3_1[] = {0};
+  float64_t v3_2[] = {-__builtin_huge_val ()};
+  float64_t e3[] = {-2.0};
+  test_case (v3_1, v3_2, e3);
+
+  float64_t v4_1[] = {-0.0};
+  float64_t v4_2[] = {__builtin_huge_val ()};
+  float64_t e4[] = {-2.0};
+  test_case (v4_1, v4_2, e4);
+
+  float64_t v5_1[] = {-0.0};
+  float64_t v5_2[] = {-__builtin_huge_val ()};
+  float64_t e5[] = {2.0};
+  test_case (v5_1, v5_2, e5);
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "fmulx\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulxd_f64_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmulxd_f64_1.c
new file mode 100644 (file)
index 0000000..d36e742
--- /dev/null
@@ -0,0 +1,36 @@
+/* Test the vmulxd_f64 AArch64 SIMD intrinsic.  */
+
+/* { dg-do run } */
+/* { dg-options "-save-temps -O3" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+void __attribute__ ((noinline))
+test_case (float64_t v1, float64_t v2, float64_t e1)
+{
+  float64_t actual1 = vmulxd_f64 (v1, v2);
+  if (actual1 != e1)
+    abort ();
+}
+
+int
+main (void)
+{
+  int i;
+  float64_t v1 = 3.14159265359;
+  float64_t v2 = 1.383894;
+  float64_t v3 = -2.71828;
+  float64_t v4 = -3.4891931;
+
+  test_case (v1, v2, v1 * v2);
+  test_case (0.0, __builtin_huge_val (), 2.0);
+  test_case (0.0, -__builtin_huge_val (), -2.0);
+  test_case (-0.0, __builtin_huge_val (), -2.0);
+  test_case (-0.0, -__builtin_huge_val (), 2.0);
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "fmulx\[ \t\]+\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f32_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f32_1.c
new file mode 100644 (file)
index 0000000..7f8dbd9
--- /dev/null
@@ -0,0 +1,48 @@
+/* Test the vmulxq_f32 AArch64 SIMD intrinsic.  */
+
+/* { dg-do run } */
+/* { dg-options "-save-temps -O3" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+void __attribute__ ((noinline))
+test_case (float32_t v1[4], float32_t v2[4], float32_t e[4])
+{
+  int i;
+  float32x4_t vec1_1 = vld1q_f32 (v1);
+  float32x4_t vec1_2 = vld1q_f32 (v2);
+
+  float32x4_t actual1 = vmulxq_f32 (vec1_1, vec1_2);
+  float32_t actual[4];
+  vst1q_f32 (actual, actual1);
+
+  for (i = 0; i < 4; ++i)
+    if (actual[i] != e[i])
+      abort ();
+}
+
+int
+main (void)
+{
+  float32_t v1 = 3.14159265359;
+  float32_t v2 = 1.383894;
+  float32_t v3 = -2.71828;
+  float32_t v4 = -3.4891931;
+
+  float32_t v1_1[] = {v1, v2, v3, v4};
+  float32_t v1_2[] = {v3, v4, v1, v2};
+  float32_t e1[] = {v1 * v3, v2 * v4, v3 * v1, v4 * v2};
+  test_case (v1_1, v1_2, e1);
+
+  float32_t v2_1[] = {0, -0.0, 0, -0.0};
+  float32_t v2_2[] = {-__builtin_huge_valf (), -__builtin_huge_valf (),
+                     __builtin_huge_valf (), __builtin_huge_valf () };
+  float32_t e2[] = {-2.0, 2.0, 2.0, -2.0};
+  test_case (v2_1, v2_2, e2);
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "fmulx\[ \t\]+\[vV\]\[0-9\]+\.4s, ?\[vV\]\[0-9\]+\.4s, ?\[vV\]\[0-9\]+\.4s\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f64_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmulxq_f64_1.c
new file mode 100644 (file)
index 0000000..f306bd0
--- /dev/null
@@ -0,0 +1,51 @@
+/* Test the vmulxq_f64 AArch64 SIMD intrinsic.  */
+
+/* { dg-do run } */
+/* { dg-options "-save-temps -O3" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+void  __attribute__ ((noinline))
+test_case (float64_t v1[2], float64_t v2[2], float64_t e1[2])
+{
+  int i;
+  float64x2_t vec1_1 = vld1q_f64 (v1);
+  float64x2_t vec1_2 = vld1q_f64 (v2);
+
+  float64x2_t actual1 = vmulxq_f64 (vec1_1, vec1_2);
+  float64_t actual[2];
+  vst1q_f64 (actual, actual1);
+
+  for (i = 0; i < 2; ++i)
+    if (actual[i] != e1[i])
+      abort ();
+}
+
+int
+main (void)
+{
+  int i;
+  float64_t v1 = 3.14159265359;
+  float64_t v2 = -2.71828;
+
+  float64_t v1_1[] = {v1, v2};
+  float64_t v1_2[] = {v2, v1};
+  float64_t e1[] = {v1 * v2, v2* v1};
+  test_case (v1_1, v1_2, e1);
+
+  float64_t v2_1[] = {0, 0};
+  float64_t v2_2[] = {__builtin_huge_val (), -__builtin_huge_val ()};
+  float64_t e2[] = {2.0, -2.0};
+  test_case (v2_1, v2_2, e2);
+
+  float64_t v3_1[] = {-0.0, -0.0};
+  float64_t v3_2[] = {__builtin_huge_val (), -__builtin_huge_val ()};
+  float64_t e3[] = {-2.0, 2.0};
+  test_case (v3_1, v3_2, e3);
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times "fmulx\[ \t\]+\[vV\]\[0-9\]+\.2\[dD\], ?\[vV\]\[0-9\]+\.2\[dD\], ?\[vV\]\[0-9\]+\.2\[dD\]\n" 1} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulxs_f32_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmulxs_f32_1.c
new file mode 100644 (file)
index 0000000..fc08e14
--- /dev/null
@@ -0,0 +1,34 @@
+/* Test the vmulxs_f32 AArch64 SIMD intrinsic.  */
+
+/* { dg-do run } */
+/* { dg-options "-save-temps -O3" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+void __attribute__ ((noinline))
+test_case (float32_t v1, float32_t v2, float32_t e)
+{
+  float32_t actual = vmulxs_f32 (v1, v2);
+  if (actual != e)
+    abort ();
+}
+
+int
+main (void)
+{
+  float32_t v1 = 3.14159265359;
+  float32_t v2 = 1.383894;
+  float32_t v3 = -2.71828;
+  float32_t v4 = -3.4891931;
+
+  test_case (v1, v2, v1 * v2);
+  test_case (0.0, __builtin_huge_valf (), 2.0);
+  test_case (0.0, -__builtin_huge_valf (), -2.0);
+  test_case (-0.0, __builtin_huge_valf (), -2.0);
+  test_case (-0.0, -__builtin_huge_valf (), 2.0);
+
+  return 0;
+}
+/* { dg-final { scan-assembler-times "fmulx\[ \t\]+\[sS\]\[0-9\]+, ?\[sS\]\[0-9\]+, ?\[sS\]\[0-9\]+\n" 1 } } */