[PATCH][AArch64] Vector shift by 64 fix
authorAlex Velenko <Alex.Velenko@arm.com>
Thu, 23 Jan 2014 16:24:13 +0000 (16:24 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Thu, 23 Jan 2014 16:24:13 +0000 (16:24 +0000)
gcc/

* config/aarch64/aarch64-simd-builtins.def (ashr): DI mode removed.
(ashr_simd): New builtin handling DI mode.
* config/aarch64/aarch64-simd.md (aarch64_ashr_simddi): New pattern.
(aarch64_sshr_simddi): New match pattern.
* config/aarch64/arm_neon.h (vshr_n_s32): Builtin call modified.
(vshrd_n_s64): Likewise.
* config/aarch64/predicates.md (aarch64_shift_imm64_di): New predicate.

gcc/testsuite/

* gcc.target/aarch64/sshr64_1.c: New testcase.

From-SVN: r206978

gcc/ChangeLog
gcc/config/aarch64/aarch64-simd-builtins.def
gcc/config/aarch64/aarch64-simd.md
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/arm_neon.h
gcc/config/aarch64/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/sshr64_1.c [new file with mode: 0644]

index 68bda3b0855cb80682381b3dbb89950309c3906b..dde3673b830c54b1f516473dc8de4dfc18d10dd2 100644 (file)
@@ -1,3 +1,13 @@
+2014-01-23  Alex Velenko  <Alex.Velenko@arm.com>
+
+       * config/aarch64/aarch64-simd-builtins.def (ashr): DI mode removed.
+       (ashr_simd): New builtin handling DI mode.
+       * config/aarch64/aarch64-simd.md (aarch64_ashr_simddi): New pattern.
+       (aarch64_sshr_simddi): New match pattern.
+       * config/aarch64/arm_neon.h (vshr_n_s32): Builtin call modified.
+       (vshrd_n_s64): Likewise.
+       * config/aarch64/predicates.md (aarch64_shift_imm64_di): New predicate.
+
 2014-01-23  Nick Clifton  <nickc@redhat.com>
 
        * config/msp430/msp430.h (ASM_SPEC): Pass the -mcpu as -mcpu.
index 185281ae5e95d54f6854483550629a57f8f9be48..e5f71b479ccfd1a9cbf84aed0f96b49762053f59 100644 (file)
   BUILTIN_VSDQ_I_DI (BINOP, srshl, 0)
   BUILTIN_VSDQ_I_DI (BINOP, urshl, 0)
 
-  BUILTIN_VSDQ_I_DI (SHIFTIMM, ashr, 3)
+  BUILTIN_VDQ_I (SHIFTIMM, ashr, 3)
+  VAR1 (SHIFTIMM, ashr_simd, 0, di)
   BUILTIN_VSDQ_I_DI (SHIFTIMM, lshr, 3)
   /* Implemented by aarch64_<sur>shr_n<mode>.  */
   BUILTIN_VSDQ_I_DI (SHIFTIMM, srshr_n, 0)
index 680b943414016d41dd0b01e6996c4d586244630e..7378da9122d550f869c3e830e3e5a7681e7581f6 100644 (file)
   DONE;
 })
 
+;; DI vector shift
+(define_expand "aarch64_ashr_simddi"
+  [(match_operand:DI 0 "register_operand" "=w")
+   (match_operand:DI 1 "register_operand" "w")
+   (match_operand:QI 2 "aarch64_shift_imm64_di" "")]
+  "TARGET_SIMD"
+  {
+    if (INTVAL (operands[2]) == 64)
+      emit_insn (gen_aarch64_sshr_simddi (operands[0], operands[1]));
+    else
+      emit_insn (gen_ashrdi3 (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+;; SIMD shift by 64.  This pattern is a special case as standard pattern does
+;; not handle NEON shifts by 64.
+(define_insn "aarch64_sshr_simddi"
+  [(set (match_operand:DI 0 "register_operand" "=w")
+        (unspec:DI
+          [(match_operand:DI 1 "register_operand" "w")] UNSPEC_SSHR64))]
+  "TARGET_SIMD"
+  "sshr\t%d0, %d1, 64"
+  [(set_attr "type" "neon_shift_imm")]
+)
+
 (define_expand "vlshr<mode>3"
  [(match_operand:VQ_S 0 "register_operand" "")
   (match_operand:VQ_S 1 "register_operand" "")
index 8657b168582248530392afdbf5e1925e9b556932..99a6ac8fcbdcd24a0ea18cc037bef9cf72070281 100644 (file)
@@ -93,6 +93,7 @@
     UNSPEC_SISD_SSHL
     UNSPEC_SISD_USHL
     UNSPEC_SSHL_2S
+    UNSPEC_SSHR64
     UNSPEC_ST1
     UNSPEC_ST2
     UNSPEC_ST3
index b6aee7a7426f8fe427701770b0e9f26189e08d06..6af99361b8e265f66026dc506cfc23f044d153b4 100644 (file)
@@ -23340,7 +23340,7 @@ vshr_n_s32 (int32x2_t __a, const int __b)
 __extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
 vshr_n_s64 (int64x1_t __a, const int __b)
 {
-  return (int64x1_t) __builtin_aarch64_ashrdi (__a, __b);
+  return (int64x1_t) __builtin_aarch64_ashr_simddi (__a, __b);
 }
 
 __extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
@@ -23418,7 +23418,7 @@ vshrq_n_u64 (uint64x2_t __a, const int __b)
 __extension__ static __inline int64x1_t __attribute__ ((__always_inline__))
 vshrd_n_s64 (int64x1_t __a, const int __b)
 {
-  return (int64x1_t) __builtin_aarch64_ashrdi (__a, __b);
+  return (int64x1_t) __builtin_aarch64_ashr_simddi (__a, __b);
 }
 
 __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__))
index 45fcdc97176fcedf034bf1f7cad39956f9cded44..c8e27d8715df96819fc98efb970cd403f6adefd5 100644 (file)
   (and (match_code "const_int")
        (match_test "(unsigned HOST_WIDE_INT) INTVAL (op) < 64")))
 
+(define_predicate "aarch64_shift_imm64_di"
+  (and (match_code "const_int")
+       (match_test "(unsigned HOST_WIDE_INT) INTVAL (op) <= 64")))
+
 (define_predicate "aarch64_reg_or_shift_imm_si"
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "aarch64_shift_imm_si")))
index f10db4772758d25d618d2335671254b1ad6d594e..43979c3603bebc0e76168c95294ce64765165328 100644 (file)
@@ -1,3 +1,7 @@
+2014-01-23  Alex Velenko  <Alex.Velenko@arm.com>
+
+       * gcc.target/aarch64/sshr64_1.c: New testcase.
+
 2014-01-23  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
        * g++.dg/cilk-plus/cilk-plus.exp: Called the C/C++ common tests for
diff --git a/gcc/testsuite/gcc.target/aarch64/sshr64_1.c b/gcc/testsuite/gcc.target/aarch64/sshr64_1.c
new file mode 100644 (file)
index 0000000..89c6096
--- /dev/null
@@ -0,0 +1,115 @@
+/* Test SIMD shift works correctly.  */
+/* { dg-do run } */
+/* { dg-options "-O3 --save-temps" } */
+
+#include "arm_neon.h"
+
+extern void abort (void);
+
+int __attribute__ ((noinline))
+test_sshr64 ()
+{
+  int64x1_t arg;
+  int64x1_t result;
+  int64_t got;
+  int64_t exp;
+  arg = vcreate_s64 (0x0000000080000000);
+  result = vshr_n_s64 (arg, 64);
+  got = vget_lane_s64 (result, 0);
+  exp = 0;
+  /* Expect: "result" = 0000000000000000.  */
+  if (exp != got)
+    return 1;
+  return 0;
+}
+
+int __attribute__ ((noinline))
+test_sshr64_neg ()
+{
+  int64x1_t arg;
+  int64x1_t result;
+  int64_t got;
+  int64_t exp;
+  arg = vcreate_s64 (0xffffffff80000000);
+  result = vshr_n_s64 (arg, 64);
+  got = vget_lane_s64 (result, 0);
+  exp = 0xffffffffffffffff;
+  /* Expect: "result" = -1.  */
+  if (exp != got)
+    return 1;
+  return 0;
+}
+
+int
+__attribute__ ((noinline))
+test_other ()
+{
+  int64x1_t arg;
+  int64x1_t result;
+  int64_t got;
+  int64_t exp;
+  arg = vcreate_s64 (0x0000000080000000);
+  result = vshr_n_s64 (arg, 4);
+  got = vget_lane_s64 (result, 0);
+  exp = 0x0000000008000000;
+  /* Expect: "result" = 0x0000000008000000.  */
+  if (exp != got)
+    return 1;
+  return 0;
+}
+
+int __attribute__ ((noinline))
+test_other_neg ()
+{
+  int64x1_t arg;
+  int64x1_t result;
+  int64_t got;
+  int64_t exp;
+  arg = vcreate_s64 (0xffffffff80000000);
+  result = vshr_n_s64 (arg, 4);
+  got = vget_lane_s64 (result, 0);
+  exp = 0xfffffffff8000000;
+  /* Expect: "result" = 0xfffffffff8000000.  */
+  if (exp != got)
+    return 1;
+  return 0;
+}
+
+int __attribute__ ((noinline))
+test_no_sshr0 ()
+{
+  int64x1_t arg;
+  int64x1_t result;
+  int64_t got;
+  int64_t exp;
+  arg = vcreate_s64 (0x0000000080000000);
+  result = vshr_n_s64 (arg, 0);
+  got = vget_lane_s64 (result, 0);
+  exp = 0x0000000080000000;
+  /* Expect: "result" = 0x0000000080000000.  */
+  if (exp != got)
+    return 1;
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not "sshr\\td\[0-9\]+, d\[0-9\]+, 0" } } */
+int
+main ()
+{
+  if (test_sshr64 ())
+    abort ();
+  if (test_other ())
+    abort ();
+
+  if (test_sshr64_neg ())
+    abort ();
+  if (test_other_neg ())
+    abort ();
+
+  if (test_no_sshr0 ())
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { cleanup-saved-temps } } */