public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/redhat/heads/gcc-8-branch)] [AArch64] Implement new intrinsics vabsd_s64 and vnegd_s64.
@ 2020-09-28 9:15 Jakub Jelinek
0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2020-09-28 9:15 UTC (permalink / raw)
To: gcc-cvs
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;
+}
+
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-09-28 9:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-28 9:15 [gcc(refs/vendors/redhat/heads/gcc-8-branch)] [AArch64] Implement new intrinsics vabsd_s64 and vnegd_s64 Jakub Jelinek
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).