On 19/11/14 18:22, Sandra Loosemore wrote: > On 11/13/2014 10:47 AM, Andrew Pinski wrote: >> On Thu, Nov 13, 2014 at 9:42 AM, Sandra Loosemore >> <san...@codesourcery.com> wrote: >>> On 11/13/2014 10:27 AM, Richard Earnshaw wrote: >>>> >>>> On 13/11/14 17:05, Ramana Radhakrishnan wrote: >>>>> >>>>> On Thu, Nov 13, 2014 at 4:55 PM, Sandra Loosemore >>>>> <san...@codesourcery.com> wrote: >>>>>> >>>>>> This patch to the AArch64 back end adds a couple of additional bics >>>>>> patterns >>>>>> to match code of the form >>>>>> >>>>>> if ((x & y) == x) ...; >>>>>> >>>>>> This is testing whether the bits set in x are a subset of the bits set >>>>>> in y; >>>>>> or, that no bits in x are set that are not set in y. So, it is >>>>>> equivalent >>>>>> to >>>>>> >>>>>> if ((x & ~y) == 0) ...; >>>>>> >>>>>> Presently this generates code like >>>>>> and x21, x21, x20 >>>>>> cmp x21, x20 >>>>>> b.eq c0 <main+0xc0> >>>>>> >>>>>> and this patch allows it to be written more concisely as: >>>>>> bics x21, x20, x21 >>>>>> b.eq c0 <main+0xc0> >>>>>> >>>>>> Since the bics instruction sets the condition codes itself, no explicit >>>>>> comparison is required and the result of the bics computation can be >>>>>> discarded. >>>>>> >>>>>> Regression-tested on aarch64-linux-gnu. OK to commit? >>>>> >>>>> >>>>> Is this not a duplicate of >>>>> https://gcc.gnu.org/ml/gcc-patches/2014-11/msg00943.html ? >>>>> >>>>> >>>> I don't think so. However, I think it is something that should be >>>> caught in generic simplification code >>>> >>>> ie map ((a & b) == b) ==> ((~a & b) == 0), etc >>>> >>>> Bit-clear operations are not that uncommon. Furthermore, A may be a >>>> constant. >>> >>> >>> Alex posted his patch when I already had Chris's in my regression test >>> queue, but I've just confirmed that it does not fix the test case I >>> included. >>> >>> I already thought a little about making this a generic simplification, but >>> it seemed to me like it was only useful on targets that have a bit-clear >>> instruction that happens to set condition codes, and that it would pessimize >>> code on targets that don't have a bit-clear instruction at all (by inserting >>> the extra complement operation). So to me it seemed reasonable to do it in >>> the back end. >> >> But can't you do this in simplify-rtx.c and allow for the cost model >> to do the correct thing? > > OK, here is a revised patch to apply the identity there. This version > depends on Alex's aarch64 BICS patch for the included test case to pass, > though. > > In addition to the aarch64 testing, I bootstrapped and regression-tested > the target-inspecific part of the patch on x86_64-linux-gnu. Is this > OK? Should I hold off on committing it until Alex's patch is in? > > -Sandra > > > 2014-11-19 Sandra Loosemore <san...@codesourcery.com> > > gcc/ > * simplify-rtx.c (simplify_relational_operation_1): Handle > simplification identities for BICS patterns. > > gcc/testsuite/ > * gcc.target/aarch64/bics_4.c: New. >
Looks sensible to me. Eric, are you happy? R. > > bics2.patch > > > Index: gcc/simplify-rtx.c > =================================================================== > --- gcc/simplify-rtx.c (revision 217322) > +++ gcc/simplify-rtx.c (working copy) > @@ -4551,6 +4551,32 @@ simplify_relational_operation_1 (enum rt > simplify_gen_binary (XOR, cmp_mode, > XEXP (op0, 1), op1)); > > + /* (eq/ne (and x y) x) simplifies to (eq/ne (and (not y) x) 0), which > + can be implemented with a BICS instruction on some targets, or > + constant-folded if y is a constant. */ > + if ((code == EQ || code == NE) > + && op0code == AND > + && rtx_equal_p (XEXP (op0, 0), op1) > + && !side_effects_p (op1)) > + { > + rtx not_y = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 1), > cmp_mode); > + rtx lhs = simplify_gen_binary (AND, cmp_mode, not_y, XEXP (op0, 0)); > + > + return simplify_gen_relational (code, mode, cmp_mode, lhs, const0_rtx); > + } > + > + /* Likewise for (eq/ne (and x y) y). */ > + if ((code == EQ || code == NE) > + && op0code == AND > + && rtx_equal_p (XEXP (op0, 1), op1) > + && !side_effects_p (op1)) > + { > + rtx not_x = simplify_gen_unary (NOT, cmp_mode, XEXP (op0, 0), > cmp_mode); > + rtx lhs = simplify_gen_binary (AND, cmp_mode, not_x, XEXP (op0, 1)); > + > + return simplify_gen_relational (code, mode, cmp_mode, lhs, const0_rtx); > + } > + > /* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped. */ > if ((code == EQ || code == NE) > && GET_CODE (op0) == BSWAP > Index: gcc/testsuite/gcc.target/aarch64/bics_4.c > =================================================================== > --- gcc/testsuite/gcc.target/aarch64/bics_4.c (revision 0) > +++ gcc/testsuite/gcc.target/aarch64/bics_4.c (revision 0) > @@ -0,0 +1,87 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2 --save-temps -fno-inline" } */ > + > +extern void abort (void); > + > +int > +bics_si_test1 (int a, int b, int c) > +{ > + if ((a & b) == a) > + return a; > + else > + return c; > +} > + > +int > +bics_si_test2 (int a, int b, int c) > +{ > + if ((a & b) == b) > + return b; > + else > + return c; > +} > + > +typedef long long s64; > + > +s64 > +bics_di_test1 (s64 a, s64 b, s64 c) > +{ > + if ((a & b) == a) > + return a; > + else > + return c; > +} > + > +s64 > +bics_di_test2 (s64 a, s64 b, s64 c) > +{ > + if ((a & b) == b) > + return b; > + else > + return c; > +} > + > +int > +main () > +{ > + int x; > + s64 y; > + > + x = bics_si_test1 (0xf00d, 0xf11f, 0); > + if (x != 0xf00d) > + abort (); > + > + x = bics_si_test1 (0xf11f, 0xf00d, 0); > + if (x != 0) > + abort (); > + > + x = bics_si_test2 (0xf00d, 0xf11f, 0); > + if (x != 0) > + abort (); > + > + x = bics_si_test2 (0xf11f, 0xf00d, 0); > + if (x != 0xf00d) > + abort (); > + > + y = bics_di_test1 (0x10001000f00dll, 0x12341000f00dll, 0ll); > + if (y != 0x10001000f00dll) > + abort (); > + > + y = bics_di_test1 (0x12341000f00dll, 0x10001000f00dll, 0ll); > + if (y != 0) > + abort (); > + > + y = bics_di_test2 (0x10001000f00dll, 0x12341000f00dll, 0ll); > + if (y != 0) > + abort (); > + > + y = bics_di_test2 (0x12341000f00dll, 0x10001000f00dll, 0ll); > + if (y != 0x10001000f00dll) > + abort (); > + > + return 0; > +} > + > +/* { dg-final { scan-assembler-times "bics\twzr, w\[0-9\]+, w\[0-9\]+" 2 } } > */ > +/* { dg-final { scan-assembler-times "bics\txzr, x\[0-9\]+, x\[0-9\]+" 2 } } > */ > +/* { dg-final { cleanup-saved-temps } } */ >