diff mbox

[AArch64] Add ANDS pattern for CMP+ZERO_EXTEND

Message ID 57C7EBE3.5070301@foss.arm.com
State New
Headers show

Commit Message

Kyrill Tkachov Sept. 1, 2016, 8:50 a.m. UTC
Hi all,

For the testcase in this patch combine tries to match:
(parallel [
         (set (reg:CC 66 cc)
             (compare:CC (zero_extend:SI (reg:QI 0 x0 [ x ]))
                 (const_int 0 [0])))
         (set (reg/v:SI 77 [ x ])
             (zero_extend:SI (reg:QI 0 x0 [ x ])))
     ])

which we should be matching down to an ANDS instruction. We already have a pattern for matching
the AND-immediate form of this. Teaching combine to jump between the two representations has in the past
been deemed undesirable (extending change_zero_ext in combine.c would increase the work it has to do by too much)
so I think it's much simpler to just add this pattern.

With this patch for the testcase in the patch we now generate:
f9:
         ands    w0, w0, 255
         mov     w2, 10
         ccmp    w1, 1, 4, eq
         csel    w0, w0, w2, le
         ret


instead of:
f9:
         uxtb    w0, w0
         mov     w2, 10
         cmp     w0, 0
         ccmp    w1, 1, 4, eq
         csel    w0, w0, w2, le
         ret

Bootstrapped and tested on aarch64-none-linux-gnu.
Ok for trunk?

Thanks,
Kyrill

2016-09-01  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * config/aarch64/aarch64.md (*ands<mode>_compare0): New pattern.
     * config/aarch64/aarch64.c (aarch64_select_cc_mode): Return CC_NZmode
     for comparisons of integer ZERO_EXTEND against zero.

2016-09-01  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * gcc.target/aarch64/ands_3.c: New test.

Comments

Richard Earnshaw (lists) Sept. 1, 2016, 8:56 a.m. UTC | #1
On 01/09/16 09:50, Kyrill Tkachov wrote:
> Hi all,
> 
> For the testcase in this patch combine tries to match:
> (parallel [
>         (set (reg:CC 66 cc)
>             (compare:CC (zero_extend:SI (reg:QI 0 x0 [ x ]))
>                 (const_int 0 [0])))
>         (set (reg/v:SI 77 [ x ])
>             (zero_extend:SI (reg:QI 0 x0 [ x ])))
>     ])
> 
> which we should be matching down to an ANDS instruction. We already have
> a pattern for matching
> the AND-immediate form of this. Teaching combine to jump between the two
> representations has in the past
> been deemed undesirable (extending change_zero_ext in combine.c would
> increase the work it has to do by too much)
> so I think it's much simpler to just add this pattern.
> 
> With this patch for the testcase in the patch we now generate:
> f9:
>         ands    w0, w0, 255
>         mov     w2, 10
>         ccmp    w1, 1, 4, eq
>         csel    w0, w0, w2, le
>         ret
> 
> 
> instead of:
> f9:
>         uxtb    w0, w0
>         mov     w2, 10
>         cmp     w0, 0
>         ccmp    w1, 1, 4, eq
>         csel    w0, w0, w2, le
>         ret
> 
> Bootstrapped and tested on aarch64-none-linux-gnu.
> Ok for trunk?
> 
> Thanks,
> Kyrill
> 
> 2016-09-01  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>     * config/aarch64/aarch64.md (*ands<mode>_compare0): New pattern.
>     * config/aarch64/aarch64.c (aarch64_select_cc_mode): Return CC_NZmode
>     for comparisons of integer ZERO_EXTEND against zero.
> 
> 2016-09-01  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>     * gcc.target/aarch64/ands_3.c: New test.
> 

OK.

R.

> aarch64-cmp-ands.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index ed5910aaf5f183bb068e31c85698a509cb8a10bc..43442a44a559f3191a10d8d3ce6b82cff0a41e1a 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -4264,6 +4264,14 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
>        && (GET_MODE (x) == HImode || GET_MODE (x) == QImode))
>      return CC_NZmode;
>  
> +  /* Similarly, comparisons of zero_extends from shorter modes can
> +     be performed using and ANDS with an immediate mask.  */
> +  if (y == const0_rtx && GET_CODE (x) == ZERO_EXTEND
> +      && (GET_MODE (x) == SImode || GET_MODE (x) == DImode)
> +      && (GET_MODE (XEXP (x, 0)) == HImode || GET_MODE (XEXP (x, 0)) == QImode)
> +      && (code == EQ || code == NE))
> +    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 137aed42c6b10511e7f558c9df65a73144f4bb94..68b715c9a7298f02e47abd1cbe146346ad1c3e30 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -3826,6 +3826,18 @@ (define_insn "*and<mode>_compare0"
>    [(set_attr "type" "alus_imm")]
>  )
>  
> +(define_insn "*ands<mode>_compare0"
> +  [(set (reg:CC_NZ CC_REGNUM)
> +	(compare:CC_NZ
> +	 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
> +	 (const_int 0)))
> +   (set (match_operand:GPI 0 "register_operand" "=r")
> +	(zero_extend:GPI (match_dup 1)))]
> +  ""
> +  "ands\\t%<GPI:w>0, %<GPI:w>1, <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/testsuite/gcc.target/aarch64/ands_3.c b/gcc/testsuite/gcc.target/aarch64/ands_3.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..42cb7f0f0bc86a4aceb09851c31eb2e888d93403
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ands_3.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +int
> +f9 (unsigned char x, int y)
> +{
> +  if (y > 1 && x == 0)
> +    return 10;
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler "ands\t(x|w)\[0-9\]+,\[ \t\]*(x|w)\[0-9\]+,\[ \t\]*255" } } */
>
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index ed5910aaf5f183bb068e31c85698a509cb8a10bc..43442a44a559f3191a10d8d3ce6b82cff0a41e1a 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -4264,6 +4264,14 @@  aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
       && (GET_MODE (x) == HImode || GET_MODE (x) == QImode))
     return CC_NZmode;
 
+  /* Similarly, comparisons of zero_extends from shorter modes can
+     be performed using and ANDS with an immediate mask.  */
+  if (y == const0_rtx && GET_CODE (x) == ZERO_EXTEND
+      && (GET_MODE (x) == SImode || GET_MODE (x) == DImode)
+      && (GET_MODE (XEXP (x, 0)) == HImode || GET_MODE (XEXP (x, 0)) == QImode)
+      && (code == EQ || code == NE))
+    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 137aed42c6b10511e7f558c9df65a73144f4bb94..68b715c9a7298f02e47abd1cbe146346ad1c3e30 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3826,6 +3826,18 @@  (define_insn "*and<mode>_compare0"
   [(set_attr "type" "alus_imm")]
 )
 
+(define_insn "*ands<mode>_compare0"
+  [(set (reg:CC_NZ CC_REGNUM)
+	(compare:CC_NZ
+	 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
+	 (const_int 0)))
+   (set (match_operand:GPI 0 "register_operand" "=r")
+	(zero_extend:GPI (match_dup 1)))]
+  ""
+  "ands\\t%<GPI:w>0, %<GPI:w>1, <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/testsuite/gcc.target/aarch64/ands_3.c b/gcc/testsuite/gcc.target/aarch64/ands_3.c
new file mode 100644
index 0000000000000000000000000000000000000000..42cb7f0f0bc86a4aceb09851c31eb2e888d93403
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ands_3.c
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int
+f9 (unsigned char x, int y)
+{
+  if (y > 1 && x == 0)
+    return 10;
+  return x;
+}
+
+/* { dg-final { scan-assembler "ands\t(x|w)\[0-9\]+,\[ \t\]*(x|w)\[0-9\]+,\[ \t\]*255" } } */