public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/redhat/heads/gcc-8-branch)] [AArch64] Implement new intrinsics vabsd_s64 and vnegd_s64. Date: Mon, 28 Sep 2020 09:15:13 +0000 (GMT) [thread overview] Message-ID: <20200928091513.83275386EC0B@sourceware.org> (raw) https://gcc.gnu.org/g:bb9d137611b1099a86fc68aed4d0f66b723ebd95 commit bb9d137611b1099a86fc68aed4d0f66b723ebd95 Author: Vlad Lazar <vlad.lazar@arm.com> Date: Fri Aug 31 15:00:54 2018 +0000 [AArch64] Implement new intrinsics vabsd_s64 and vnegd_s64. gcc/ 2018-08-31 Vlad Lazar <vlad.lazar@arm.com> PR target/71233 * config/aarch64/arm_neon.h (vabsd_s64): New. (vnegd_s64): Likewise. gcc/testsuite/ 2018-08-31 Vlad Lazar <vlad.lazar@arm.com> PR target/71233 * gcc.target/aarch64/scalar_intrinsics.c (test_vnegd_s64): New. * gcc.target/aarch64/vneg_s.c (RUN_TEST_SCALAR): New. (test_vnegd_s64): Likewise. * gcc.target/aarch64/vnegd_s64.c: New. * gcc.target/aarch64/vabsd_s64.c: New. (cherry picked from commit 66da5b53107962a1c115a9686f2220de27f276f7) Diff: --- gcc/config/aarch64/arm_neon.h | 31 +++++++++++++++++ .../gcc.target/aarch64/scalar_intrinsics.c | 8 +++++ .../gcc.target/aarch64/vabs_intrinsic_3.c | 39 ++++++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/vabsd_s64.c | 34 +++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/vneg_s.c | 34 ++++++++++++++++++- gcc/testsuite/gcc.target/aarch64/vnegd_s64.c | 36 ++++++++++++++++++++ 6 files changed, 181 insertions(+), 1 deletion(-) diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index dd53e243b52..7bcd1e1c844 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -11822,6 +11822,18 @@ vabsq_s64 (int64x2_t __a) return __builtin_aarch64_absv2di (__a); } +/* Try to avoid moving between integer and vector registers. + For why the cast to unsigned is needed check the vnegd_s64 intrinsic. + There is a testcase related to this issue: + gcc.target/aarch64/vabsd_s64.c. */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vabsd_s64 (int64_t __a) +{ + return __a < 0 ? - (uint64_t) __a : __a; +} + /* vadd */ __extension__ extern __inline int64_t @@ -23189,6 +23201,25 @@ vneg_s64 (int64x1_t __a) return -__a; } +/* According to the ACLE, the negative of the minimum (signed) + value is itself. This leads to a semantics mismatch, as this is + undefined behaviour in C. The value range predictor is not + aware that the negation of a negative number can still be negative + and it may try to fold the expression. See the test in + gcc.target/aarch64/vnegd_s64.c for an example. + + The cast below tricks the value range predictor to include + INT64_MIN in the range it computes. So for x in the range + [INT64_MIN, y] the range prediction after vnegd_s64 (x) will + be ~[INT64_MIN + 1, y]. */ + +__extension__ extern __inline int64_t +__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) +vnegd_s64 (int64_t __a) +{ + return - (uint64_t) __a; +} + __extension__ extern __inline float32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vnegq_f32 (float32x4_t __a) diff --git a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c index ea29066e369..d943989768d 100644 --- a/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c +++ b/gcc/testsuite/gcc.target/aarch64/scalar_intrinsics.c @@ -627,6 +627,14 @@ test_vqabss_s32 (int32_t a) return vqabss_s32 (a); } +/* { dg-final { scan-assembler-times "\\tneg\\tx\[0-9\]+" 1 } } */ + +int64_t +test_vnegd_s64 (int64_t a) +{ + return vnegd_s64 (a); +} + /* { dg-final { scan-assembler-times "\\tsqneg\\tb\[0-9\]+" 1 } } */ int8_t diff --git a/gcc/testsuite/gcc.target/aarch64/vabs_intrinsic_3.c b/gcc/testsuite/gcc.target/aarch64/vabs_intrinsic_3.c new file mode 100644 index 00000000000..cf4e7ae4679 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vabs_intrinsic_3.c @@ -0,0 +1,39 @@ +/* Test the vabsd_s64 intrinsic. */ + +/* { dg-do run } */ +/* { dg-options "--save-temps -O2" } */ + +#include <arm_neon.h> +#include <limits.h> + +extern void abort (void); + +#define force_simd(V1) asm volatile ("mov %d0, %1.d[0]" \ + : "=w"(V1) \ + : "w"(V1) \ + : /* No clobbers */); + +#define RUN_TEST(test, answ) \ +{ \ + force_simd (test); \ + force_simd (answ); \ + int64_t res = vabsd_s64 (test); \ + force_simd (res); \ + if (res != answ) \ + abort (); \ +} + +int64_t input[] = {INT64_MAX, 10, 0, -10, INT64_MIN + 1, INT64_MIN}; +int64_t expected[] = {INT64_MAX, 10, 0, 10, INT64_MAX, INT64_MIN}; + +int main (void) +{ + RUN_TEST (input[0], expected[0]); + RUN_TEST (input[1], expected[1]); + RUN_TEST (input[2], expected[2]); + RUN_TEST (input[3], expected[3]); + RUN_TEST (input[4], expected[4]); + RUN_TEST (input[5], expected[5]); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/vabsd_s64.c b/gcc/testsuite/gcc.target/aarch64/vabsd_s64.c new file mode 100644 index 00000000000..a0f88ee12c3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vabsd_s64.c @@ -0,0 +1,34 @@ +/* Check that the compiler does not optimise the vabsd_s64 call out. + We need to check for this because there is a mismatch in semantics + between the ACLE, which states that he absolute value of the minimum + (signed) value is itself, and C, where this is undefined behaviour. */ + +/* { dg-do run } */ +/* { dg-options "--save-temps -fno-inline -O2" } */ + +#include <arm_neon.h> +#include <limits.h> + +extern void abort (void); + +int +bar (int64_t x) +{ + if (x < (int64_t) 0) + return vabsd_s64 (x) < (int64_t) 0; + else + return -1; +} + +int +main (void) +{ + int ans = 1; + int res_abs = bar (INT64_MIN); + + if (res_abs != ans) + abort (); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/aarch64/vneg_s.c b/gcc/testsuite/gcc.target/aarch64/vneg_s.c index 911054053ea..e7f20f2831f 100644 --- a/gcc/testsuite/gcc.target/aarch64/vneg_s.c +++ b/gcc/testsuite/gcc.target/aarch64/vneg_s.c @@ -75,6 +75,18 @@ extern void abort (void); } \ } +#define RUN_TEST_SCALAR(test_val, answ_val, a, b) \ + { \ + int64_t res; \ + INHIB_OPTIMIZATION; \ + a = test_val; \ + b = answ_val; \ + force_simd (b); \ + force_simd (a); \ + res = vnegd_s64 (a); \ + force_simd (res); \ + } + int test_vneg_s8 () { @@ -177,7 +189,24 @@ test_vneg_s64 () return 0; } -/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 8 } } */ +int +test_vnegd_s64 () +{ + int64_t a, b; + + RUN_TEST_SCALAR (TEST0, ANSW0, a, b); + RUN_TEST_SCALAR (TEST1, ANSW1, a, b); + RUN_TEST_SCALAR (TEST2, ANSW2, a, b); + RUN_TEST_SCALAR (TEST3, ANSW3, a, b); + RUN_TEST_SCALAR (TEST4, ANSW4, a, b); + RUN_TEST_SCALAR (TEST5, ANSW5, a, b); + RUN_TEST_SCALAR (LLONG_MAX, LLONG_MIN + 1, a, b); + RUN_TEST_SCALAR (LLONG_MIN, LLONG_MIN, a, b); + + return 0; +} + +/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 16 } } */ int test_vnegq_s8 () @@ -283,6 +312,9 @@ main (int argc, char **argv) if (test_vneg_s64 ()) abort (); + if (test_vnegd_s64 ()) + abort (); + if (test_vnegq_s8 ()) abort (); diff --git a/gcc/testsuite/gcc.target/aarch64/vnegd_s64.c b/gcc/testsuite/gcc.target/aarch64/vnegd_s64.c new file mode 100644 index 00000000000..73d478ff49d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vnegd_s64.c @@ -0,0 +1,36 @@ +/* Check that the compiler does not optimise the negation out. + We need to check for this because there is a mismatch in semantics + between the ACLE, which states that he negative of the minimum + (signed) value is itself and C, where this is undefined behaviour. */ + +/* { dg-do run } */ +/* { dg-options "--save-temps -O2" } */ + +#include <arm_neon.h> +#include <limits.h> + +extern void abort (void); + +int +foo (int64_t x) +{ + if (x < (int64_t) 0) + return vnegd_s64 (x) < (int64_t) 0; + else + return -1; +} + +/* { dg-final { scan-assembler-times {neg\tx[0-9]+, x[0-9]+} 1 } } */ + +int +main (void) +{ + int ans = 1; + int res = foo (INT64_MIN); + + if (res != ans) + abort (); + + return 0; +} +
reply other threads:[~2020-09-28 9:15 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200928091513.83275386EC0B@sourceware.org \ --to=jakub@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).