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.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. >
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" } } */ >