From: Kyrylo Tkachov <[email protected]>
aarch64_cm<optab>di has a general register alternative, but its second
operand only accepts a register there, while the predicate also allows a
constant zero. A comparison against zero therefore has no general
register alternative and the value is moved through a vector register.
Accept the zero in that alternative. The split already builds the
comparison with aarch64_gen_compare_reg, which handles a zero operand.
long f (long x) { return -(long) (x == 0); }
aarch64 -O2:
before after
fmov d31, x0 cmp x0, 0
cmeq d31, d31, #0 csetm x0, eq
fmov x0, d31
The two moves cross the general and vector register files, which is the
expensive part. The vector alternatives are unchanged, so a comparison
whose operands are already in vector registers still uses cmeq.
Constant time selection code in OpenSSL, Botan and libgcrypt builds masks
this way.
Bootstrapped and tested on aarch64-none-linux-gnu.
gcc/ChangeLog:
* config/aarch64/aarch64-simd.md (aarch64_cm<optab>di): Accept a
zero second operand in the general register alternative.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/cmpdi-neg-1.c: New test.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/config/aarch64/aarch64-simd.md | 2 +-
.../gcc.target/aarch64/cmpdi-neg-1.c | 58 +++++++++++++++++++
2 files changed, 59 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/aarch64/cmpdi-neg-1.c
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index aa6c1fa0735..12861333b22 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -7945,7 +7945,7 @@
(neg:DI
(COMPARISONS:DI
(match_operand:DI 1 "register_operand" "w,w,r")
- (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz,r")
+ (match_operand:DI 2 "aarch64_simd_reg_or_zero" "w,ZDz,rZ")
)))
(clobber (reg:CC CC_REGNUM))]
"TARGET_SIMD"
diff --git a/gcc/testsuite/gcc.target/aarch64/cmpdi-neg-1.c b/gcc/testsuite/gcc.target/aarch64/cmpdi-neg-1.c
new file mode 100644
index 00000000000..cfe0eb0ac0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/cmpdi-neg-1.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+/* A 64-bit comparison against zero whose result is negated has to stay in
+ the general registers. Before, only the vector alternative accepted the
+ zero, so the value was moved to and from a vector register. */
+
+/*
+** f1:
+** cmp x0, 0
+** csetm x0, eq
+** ret
+*/
+long
+f1 (long x)
+{
+ return -(long) (x == 0);
+}
+
+/*
+** f2:
+** cmp x0, 0
+** csetm x0, ne
+** ret
+*/
+long
+f2 (long x)
+{
+ return -(long) (x != 0);
+}
+
+/*
+** f3:
+** cmp x0, 0
+** csetm x0, le
+** ret
+*/
+long
+f3 (long x)
+{
+ return -(long) (x <= 0);
+}
+
+/*
+** f4:
+** cmp x0, x1
+** csetm x0, eq
+** ret
+*/
+long
+f4 (long x, long y)
+{
+ return -(long) (x == y);
+}
+
+/* { dg-final { scan-assembler-not "\\tfmov\\t" } } */
+/* { dg-final { scan-assembler-not "\\tcmeq\\t" } } */
--
2.50.1 (Apple Git-155)
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.