+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.
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)
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" "")
UNSPEC_SISD_SSHL
UNSPEC_SISD_USHL
UNSPEC_SSHL_2S
+ UNSPEC_SSHR64
UNSPEC_ST1
UNSPEC_ST2
UNSPEC_ST3
__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__))
__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__))
(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")))
+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
--- /dev/null
+/* 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 } } */