This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][AArch64] PR rtl-optimization/68796: Add patterns for QImode and HImode comparison with zero
- From: Kyrill Tkachov <kyrylo dot tkachov at foss dot arm dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Marcus Shawcroft <marcus dot shawcroft at arm dot com>, Richard Earnshaw <Richard dot Earnshaw at arm dot com>, James Greenhalgh <james dot greenhalgh at arm dot com>
- Date: Thu, 07 Jan 2016 15:39:42 +0000
- Subject: [PATCH][AArch64] PR rtl-optimization/68796: Add patterns for QImode and HImode comparison with zero
- Authentication-results: sourceware.org; auth=none
Hi all,
This is an aarch64-specific approach to fixing the issue I raised in the thread at:
https://gcc.gnu.org/ml/gcc-patches/2015-12/msg01779.html
The guidance there was to define aarch64 patterns for comparing QImode and HImode registers
against zero. This is a simple pattern to write and it maps down to a TST instruction
with the mode mask immediate for each of the short modes.
On aarch64 it has the exact same codegen effect as the combine patch I proposed in the
thread above. For example:
With this patch for the testcases:
int
f255 (int x)
{
if (x & 255)
return 1;
return x;
}
int
foo (long x)
{
return ((short) x != 0) ? x : 1;
}
we now generate for aarch64 at -O2:
f255:
tst x0, 255
csinc w0, w0, wzr, eq
ret
and
foo:
tst x0, 65535
csinc x0, x0, xzr, ne
ret
instead of the previous:
f255:
and w1, w0, 255
cmp w1, wzr
csinc w0, w0, wzr, eq
ret
foo:
sxth w1, w0
cmp w1, wzr
csinc x0, x0, xzr, ne
ret
Bootstrapped and tested on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill
2016-01-07 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR rtl-optimization/68796
* config/aarch64/aarch64.md (*and<mode>_compare0): New pattern.
* config/aarch64/aarch64.c (aarch64_select_cc_mode): Handle HImode
and QImode comparisons against zero with CC_NZmode.
* config/aarch64/iterators.md (short_mask): New mode_attr.
2016-01-07 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR rtl-optimization/68796
* gcc.target/aarch64/tst_5.c: New test.
* gcc.target/aarch64/tst_6.c: Likewise.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 0284406334e1a6ea4c0474873bea4eb69283b572..914af423569bcabd5e32160f872e33057408e2d4 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -4143,6 +4143,13 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
}
}
+ /* Equality comparisons of short modes against zero can be performed
+ using the TST instruction with the appropriate bitmask. */
+ if (y == const0_rtx && REG_P (x)
+ && (code == EQ || code == NE)
+ && (GET_MODE (x) == HImode || GET_MODE (x) == QImode))
+ return CC_NZmode;
+
if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode)
&& y == const0_rtx
&& (code == EQ || code == NE || code == LT || code == GE)
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index a91ed9be082ab0f321a4880845560f72386f0ec3..9471091408ff2146ad57ccf4ddc983424318a5a5 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3687,6 +3687,16 @@ (define_expand "ctz<mode>2"
}
)
+(define_insn "*and<mode>_compare0"
+ [(set (reg:CC_NZ CC_REGNUM)
+ (compare:CC_NZ
+ (match_operand:SHORT 0 "register_operand" "r")
+ (const_int 0)))]
+ ""
+ "tst\\t%<w>0, <short_mask>"
+ [(set_attr "type" "alus_imm")]
+)
+
(define_insn "*and<mode>3nr_compare0"
[(set (reg:CC_NZ CC_REGNUM)
(compare:CC_NZ
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 549d47a7a5d88c142343cdc5c952972069af1c0c..49598a2cd9356d2ff9920544c16f48bbb30022fb 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -345,6 +345,8 @@ (define_mode_attr w [(QI "w") (HI "w") (SI "w") (DI "x") (SF "s") (DF "d")])
(define_mode_attr w1 [(SF "w") (DF "x")])
(define_mode_attr w2 [(SF "x") (DF "w")])
+(define_mode_attr short_mask [(HI "65535") (QI "255")])
+
;; For constraints used in scalar immediate vector moves
(define_mode_attr hq [(HI "h") (QI "q")])
diff --git a/gcc/testsuite/gcc.target/aarch64/tst_5.c b/gcc/testsuite/gcc.target/aarch64/tst_5.c
new file mode 100644
index 0000000000000000000000000000000000000000..0de40a6c47a7d63c1b7a81aeba438a096c0041b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tst_5.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+f255 (int x)
+{
+ if (x & 255)
+ return 1;
+ return x;
+}
+
+int
+f65535 (int x)
+{
+ if (x & 65535)
+ return 1;
+ return x;
+}
+
+/* { dg-final { scan-assembler "tst\t(x|w)\[0-9\]+,\[ \t\]*255" } } */
+/* { dg-final { scan-assembler "tst\t(x|w)\[0-9\]+,\[ \t\]*65535" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/tst_6.c b/gcc/testsuite/gcc.target/aarch64/tst_6.c
new file mode 100644
index 0000000000000000000000000000000000000000..f15ec114c391fed79cc43b7740fde83fb3d4ea53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/tst_6.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+foo (long x)
+{
+ return ((short) x != 0) ? x : 1;
+}
+
+/* { dg-final { scan-assembler "tst\t(x|w)\[0-9\]+,\[ \t\]*65535" } } */