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.tkac...@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.tkac...@arm.com> * gcc.target/aarch64/ands_3.c: New test.
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" } } */