From f9a4c9a61396acaea09951aa26b57375a14ac632 Mon Sep 17 00:00:00 2001 From: Alex Velenko Date: Thu, 23 Jan 2014 16:24:13 +0000 Subject: [PATCH] [PATCH][AArch64] Vector shift by 64 fix 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 | 10 ++ gcc/config/aarch64/aarch64-simd-builtins.def | 3 +- gcc/config/aarch64/aarch64-simd.md | 26 +++++ gcc/config/aarch64/aarch64.md | 1 + gcc/config/aarch64/arm_neon.h | 4 +- gcc/config/aarch64/predicates.md | 4 + gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.target/aarch64/sshr64_1.c | 115 +++++++++++++++++++ 8 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/sshr64_1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 68bda3b0855..dde3673b830 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2014-01-23 Alex Velenko + + * 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 * config/msp430/msp430.h (ASM_SPEC): Pass the -mcpu as -mcpu. diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def index 185281ae5e9..e5f71b479cc 100644 --- a/gcc/config/aarch64/aarch64-simd-builtins.def +++ b/gcc/config/aarch64/aarch64-simd-builtins.def @@ -190,7 +190,8 @@ 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_shr_n. */ BUILTIN_VSDQ_I_DI (SHIFTIMM, srshr_n, 0) diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 680b9434140..7378da9122d 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -685,6 +685,32 @@ 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 "vlshr3" [(match_operand:VQ_S 0 "register_operand" "") (match_operand:VQ_S 1 "register_operand" "") diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 8657b168582..99a6ac8fcbd 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -93,6 +93,7 @@ UNSPEC_SISD_SSHL UNSPEC_SISD_USHL UNSPEC_SSHL_2S + UNSPEC_SSHR64 UNSPEC_ST1 UNSPEC_ST2 UNSPEC_ST3 diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index b6aee7a7426..6af99361b8e 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -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__)) diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 45fcdc97176..c8e27d8715d 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -86,6 +86,10 @@ (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"))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f10db477275..43979c3603b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-01-23 Alex Velenko + + * gcc.target/aarch64/sshr64_1.c: New testcase. + 2014-01-23 Balaji V. Iyer * 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 index 00000000000..89c6096ad39 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sshr64_1.c @@ -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 } } */ -- 2.30.2