[AArch64] Implement TARGET_GIMPLE_FOLD_BUILTIN for aarch64 backend.
authorJames Greenhalgh <james.greenhalgh@arm.com>
Thu, 25 Apr 2013 12:44:25 +0000 (12:44 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Thu, 25 Apr 2013 12:44:25 +0000 (12:44 +0000)
gcc/
* config/aarch64/aarch64-builtins.c
(aarch64_gimple_fold_builtin): New.
* config/aarch64/aarch64-protos.h (aarch64_gimple_fold_builtin): New.
* config/aarch64/aarch64-simd-builtins.def (addv): New.
* config/aarch64/aarch64-simd.md (addpv4sf): New.
(addvv4sf): Update.
* config/aarch64/aarch64.c (TARGET_GIMPLE_FOLD_BUILTIN): Define.

gcc/testsuite/
* gcc.target/aarch64/vaddv-intrinsic.c: New.
* gcc.target/aarch64/vaddv-intrinsic-compile.c: Likewise.
* gcc.target/aarch64/vaddv-intrinsic.x: Likewise.

Co-Authored-By: Tejas Belagod <tejas.belagod@arm.com>
From-SVN: r198304

gcc/ChangeLog
gcc/config/aarch64/aarch64-builtins.c
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64-simd-builtins.def
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/arm_neon.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic-compile.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic.x [new file with mode: 0644]

index 085124cea61c55852349f7404dc6d1af84de0099..f42a2afaccce8961d1fff134863610dba6980968 100644 (file)
@@ -1,3 +1,14 @@
+2013-04-25  James Greenhalgh  <james.greenhalgh@arm.com>
+           Tejas Belagod  <tejas.belagod@arm.com>
+
+       * config/aarch64/aarch64-builtins.c
+       (aarch64_gimple_fold_builtin): New.
+       * config/aarch64/aarch64-protos.h (aarch64_gimple_fold_builtin): New.
+       * config/aarch64/aarch64-simd-builtins.def (addv): New.
+       * config/aarch64/aarch64-simd.md (addpv4sf): New.
+       (addvv4sf): Update.
+       * config/aarch64/aarch64.c (TARGET_GIMPLE_FOLD_BUILTIN): Define.
+
 2013-04-25  Naveen H.S  <Naveen.Hurugalawadi@caviumnetworks.com>
 
        * config/aarch64/aarch64.md 
index 35475ba12bbe7808fea24c1ac13a58e4eb2ce15d..a786945f3c8751761063e7d3adcaa01dcfbaee67 100644 (file)
@@ -30,6 +30,7 @@
 #include "langhooks.h"
 #include "diagnostic-core.h"
 #include "optabs.h"
+#include "gimple.h"
 
 enum aarch64_simd_builtin_type_mode
 {
@@ -1254,6 +1255,54 @@ aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
 
   return NULL_TREE;
 }
+
+#undef VAR1
+#define VAR1(T, N, MAP, A) \
+  case AARCH64_SIMD_BUILTIN_##N##A:
+
+bool
+aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
+{
+  bool changed = false;
+  gimple stmt = gsi_stmt (*gsi);
+  tree call = gimple_call_fn (stmt);
+  tree fndecl;
+  gimple new_stmt = NULL;
+  if (call)
+    {
+      fndecl = gimple_call_fndecl (stmt);
+      if (fndecl)
+       {
+         int fcode = DECL_FUNCTION_CODE (fndecl);
+         int nargs = gimple_call_num_args (stmt);
+         tree *args = (nargs > 0
+                       ? gimple_call_arg_ptr (stmt, 0)
+                       : &error_mark_node);
+
+         switch (fcode)
+           {
+             BUILTIN_VDQF (UNOP, addv, 0)
+               new_stmt = gimple_build_assign_with_ops (
+                                               REDUC_PLUS_EXPR,
+                                               gimple_call_lhs (stmt),
+                                               args[0],
+                                               NULL_TREE);
+               break;
+           default:
+             break;
+           }
+       }
+    }
+
+  if (new_stmt)
+    {
+      gsi_replace (gsi, new_stmt, true);
+      changed = true;
+    }
+
+  return changed;
+}
+
 #undef AARCH64_CHECK_BUILTIN_MODE
 #undef AARCH64_FIND_FRINT_VARIANT
 #undef BUILTIN_DX
index 7ebbf51a201b21a263aa44600d148a81d81e2d79..bf02b99b1a2b528d6b07f344ae1a07dd606ac11b 100644 (file)
@@ -140,6 +140,7 @@ bool aarch64_constant_address_p (rtx);
 bool aarch64_float_const_zero_rtx_p (rtx);
 bool aarch64_function_arg_regno_p (unsigned);
 bool aarch64_gen_movmemqi (rtx *);
+bool aarch64_gimple_fold_builtin (gimple_stmt_iterator *);
 bool aarch64_is_extend_from_extract (enum machine_mode, rtx, rtx);
 bool aarch64_is_long_call_p (rtx);
 bool aarch64_label_mentioned_p (rtx);
index 43b5b931d77b8164698012a263ead8fb36e67eb8..41dd82fa4612f19d23a01d628b70a0bd17953e90 100644 (file)
   BUILTIN_VDQF (BINOP, fmax, 0)
   BUILTIN_VDQF (BINOP, fmin, 0)
 
+  /* Implemented by aarch64_addv<mode>.  */
+  BUILTIN_VDQF (UNOP, addv, 0)
+
   /* Implemented by <maxmin><mode>3.  */
   BUILTIN_VDQ_BHSI (BINOP, smax, 3)
   BUILTIN_VDQ_BHSI (BINOP, smin, 3)
index 9b42365b50b5f0e06d429614b2a3218bb634a3c6..e5506fce8a456777f64f26028a940568c15f9191 100644 (file)
 
 ;; FP 'across lanes' add.
 
-(define_insn "aarch64_addvv4sf"
+(define_insn "aarch64_addpv4sf"
  [(set (match_operand:V4SF 0 "register_operand" "=w")
        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "w")]
                    UNSPEC_FADDV))]
  "TARGET_SIMD"
 {
   rtx tmp = gen_reg_rtx (V4SFmode);
-  emit_insn (gen_aarch64_addvv4sf (tmp, operands[1]));
-  emit_insn (gen_aarch64_addvv4sf (operands[0], tmp));
+  emit_insn (gen_aarch64_addpv4sf (tmp, operands[1]));
+  emit_insn (gen_aarch64_addpv4sf (operands[0], tmp));
   DONE;
 })
 
  "TARGET_SIMD"
 {
   rtx tmp = gen_reg_rtx (V4SFmode);
-  emit_insn (gen_aarch64_addvv4sf (tmp, operands[1]));
-  emit_insn (gen_aarch64_addvv4sf (operands[0], tmp));
+  emit_insn (gen_aarch64_addpv4sf (tmp, operands[1]));
+  emit_insn (gen_aarch64_addpv4sf (operands[0], tmp));
+  DONE;
+})
+
+(define_expand "aarch64_addvv4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=w")
+       (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "w")]
+                    UNSPEC_FADDV))]
+ "TARGET_SIMD"
+{
+  emit_insn (gen_reduc_splus_v4sf (operands[0], operands[1]));
   DONE;
 })
 
index 16034d21aa6bdc53afeb4ce8a2548979204d0d1a..8c2c5765e04d8837b0fb0c7c46dfc8ff627bdbbe 100644 (file)
@@ -7895,6 +7895,9 @@ aarch64_vectorize_vec_perm_const_ok (enum machine_mode vmode,
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED aarch64_frame_pointer_required
 
+#undef TARGET_GIMPLE_FOLD_BUILTIN
+#define TARGET_GIMPLE_FOLD_BUILTIN aarch64_gimple_fold_builtin
+
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR aarch64_gimplify_va_arg_expr
 
index 58343a7a7419c0e3944f0f32d09849fab94b66f8..e7ba000a24aa4c01b88362ca7666e6631bfb89bb 100644 (file)
@@ -19731,6 +19731,27 @@ vaddd_u64 (uint64x1_t __a, uint64x1_t __b)
   return __a + __b;
 }
 
+__extension__ static __inline float32_t __attribute__ ((__always_inline__))
+vaddv_f32 (float32x2_t __a)
+{
+  float32x2_t t = __builtin_aarch64_addvv2sf (__a);
+  return vget_lane_f32 (t, 0);
+}
+
+__extension__ static __inline float32_t __attribute__ ((__always_inline__))
+vaddvq_f32 (float32x4_t __a)
+{
+  float32x4_t t = __builtin_aarch64_addvv4sf (__a);
+  return vgetq_lane_f32 (t, 0);
+}
+
+__extension__ static __inline float64_t __attribute__ ((__always_inline__))
+vaddvq_f64 (float64x2_t __a)
+{
+  float64x2_t t = __builtin_aarch64_addvv2df (__a);
+  return vgetq_lane_f64 (t, 0);
+}
+
 /* vceq */
 
 __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
index 3de1dff99fded6fae3ade70973603556bbed1c5f..32d986aa797fa265a8265287d5c89c1d9222e03d 100644 (file)
@@ -1,3 +1,10 @@
+2013-04-25  James Greenhalgh  <james.greenhalgh@arm.com>
+           Tejas Belagod  <tejas.belagod@arm.com>
+
+       * gcc.target/aarch64/vaddv-intrinsic.c: New.
+       * gcc.target/aarch64/vaddv-intrinsic-compile.c: Likewise.
+       * gcc.target/aarch64/vaddv-intrinsic.x: Likewise.
+
 2013-04-25  Naveen H.S  <Naveen.Hurugalawadi@caviumnetworks.com>
 
        * gcc.target/aarch64/cmp.c: New.
diff --git a/gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic-compile.c b/gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic-compile.c
new file mode 100644 (file)
index 0000000..11fa984
--- /dev/null
@@ -0,0 +1,11 @@
+
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+#include "arm_neon.h"
+
+#include "vaddv-intrinsic.x"
+
+/* { dg-final { scan-assembler "faddp\\ts\[0-9\]+"} } */
+/* { dg-final { scan-assembler-times "faddp\\tv\[0-9\]+\.4s" 2} } */
+/* { dg-final { scan-assembler "faddp\\td\[0-9\]+"} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic.c b/gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic.c
new file mode 100644 (file)
index 0000000..f6e0829
--- /dev/null
@@ -0,0 +1,28 @@
+
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+#include "vaddv-intrinsic.x"
+
+int
+main (void)
+{
+  const float32_t pool_v2sf[] = {4.0f, 9.0f};
+  const float32_t pool_v4sf[] = {4.0f, 9.0f, 16.0f, 25.0f};
+  const float64_t pool_v2df[] = {4.0, 9.0};
+
+  if (test_vaddv_v2sf (pool_v2sf) != 13.0f)
+    abort ();
+
+  if (test_vaddv_v4sf (pool_v4sf) != 54.0f)
+    abort ();
+
+  if (test_vaddv_v2df (pool_v2df) != 13.0)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic.x b/gcc/testsuite/gcc.target/aarch64/vaddv-intrinsic.x
new file mode 100644 (file)
index 0000000..7bf38ca
--- /dev/null
@@ -0,0 +1,27 @@
+
+float32_t
+test_vaddv_v2sf (const float32_t *pool)
+{
+  float32x2_t val;
+
+  val = vld1_f32 (pool);
+  return vaddv_f32 (val);
+}
+
+float32_t
+test_vaddv_v4sf (const float32_t *pool)
+{
+  float32x4_t val;
+
+  val = vld1q_f32 (pool);
+  return vaddvq_f32 (val);
+}
+
+float64_t
+test_vaddv_v2df (const float64_t *pool)
+{
+  float64x2_t val;
+
+  val = vld1q_f64 (pool);
+  return vaddvq_f64 (val);
+}