On Thu, 1 Dec 2016, Paolo Bonzini wrote: > In code like the following from KVM: > > /* it is a read fault? */ > error_code = (exit_qualification << 2) & PFERR_FETCH_MASK; > > it would be nicer to write > > /* it is a read fault? */ > error_code = (exit_qualification & VMX_EPT_READ_FAULT_MASK) ? > PFERR_FETCH_MASK : 0; > > instead of having to know the difference between the positions of the > source and destination bits. LLVM catches the latter just fine (which > is why I am sending this in stage 3...), but GCC does not, so this > patch adds two patterns to catch it. > > The combine.c hunk of v1 has been committed already. > > Bootstrapped/regtested x86_64-pc-linux-gnu, ok?
Ok. Thanks, Richard. > Paolo > > 2016-11-26 Paolo Bonzini <bonz...@gnu.org> > > * match.pd: Simplify X ? C : 0 where C is a power of 2 and > X tests a single bit. > > 2016-11-26 Paolo Bonzini <bonz...@gnu.org> > > * gcc.dg/fold-and-lshift.c, gcc.dg/fold-and-rshift-1.c, > gcc.dg/fold-and-rshift-2.c: New testcases. > > Index: match.pd > =================================================================== > --- match.pd (revision 242916) > +++ match.pd (working copy) > @@ -2630,6 +2630,21 @@ > (cmp (bit_and@2 @0 integer_pow2p@1) @1) > (icmp @2 { build_zero_cst (TREE_TYPE (@0)); }))) > > +/* If we have (A & C) != 0 ? D : 0 where C and D are powers of 2, > + convert this into a shift followed by ANDing with D. */ > +(simplify > + (cond > + (ne (bit_and @0 integer_pow2p@1) integer_zerop) > + integer_pow2p@2 integer_zerop) > + (with { > + int shift = wi::exact_log2 (@2) - wi::exact_log2 (@1); > + } > + (if (shift > 0) > + (bit_and > + (lshift (convert @0) { build_int_cst (integer_type_node, shift); }) @2) > + (bit_and > + (convert (rshift @0 { build_int_cst (integer_type_node, -shift); })) > @2)))) > + > /* If we have (A & C) != 0 where C is the sign bit of A, convert > this into A < 0. Similarly for (A & C) == 0 into A >= 0. */ > (for cmp (eq ne) > @@ -2644,6 +2659,19 @@ > (with { tree stype = signed_type_for (TREE_TYPE (@0)); } > (ncmp (convert:stype @0) { build_zero_cst (stype); }))))) > > +/* If we have A < 0 ? C : 0 where C is a power of 2, convert > + this into a right shift followed by ANDing with C. */ > +(simplify > + (cond > + (lt @0 integer_zerop) > + integer_pow2p@1 integer_zerop) > + (with { > + int shift = element_precision (@0) - wi::exact_log2 (@1) - 1; > + } > + (bit_and > + (convert (rshift @0 { build_int_cst (integer_type_node, shift); })) > + @1))) > + > /* When the addresses are not directly of decls compare base and offset. > This implements some remaining parts of fold_comparison address > comparisons but still no complete part of it. Still it is good > Index: testsuite/gcc.dg/fold-and-lshift.c > =================================================================== > --- testsuite/gcc.dg/fold-and-lshift.c (revision 0) > +++ testsuite/gcc.dg/fold-and-lshift.c (working copy) > @@ -0,0 +1,35 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O -fdump-tree-original" } */ > + > +int f(int x) > +{ > + return (x << 2) & 128; > +} > + > +int g(int x) > +{ > + return !!(x & 32) << 7; > +} > + > +int h(int x) > +{ > + return ((x >> 5) & 1) << 7; > +} > + > +int i(int x) > +{ > + return (x & 32) >> 5 << 7; > +} > + > +int j(int x) > +{ > + return ((x >> 5) & 1) ? 128 : 0; > +} > + > +int k(int x) > +{ > + return (x & 32) ? 128 : 0; > +} > + > +/* { dg-final { scan-tree-dump-not " \\? " "original" } } */ > +/* { dg-final { scan-assembler-not "sarl" { target i?86-*-* x86_64-*-* } } > }" */ > Index: testsuite/gcc.dg/fold-and-rshift-1.c > =================================================================== > --- testsuite/gcc.dg/fold-and-rshift-1.c (revision 0) > +++ testsuite/gcc.dg/fold-and-rshift-1.c (working copy) > @@ -0,0 +1,35 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O -fdump-tree-original" } */ > + > +int f(int x) > +{ > + return (x >> 2) & 128; > +} > + > +int g(int x) > +{ > + return !!(x & 512) << 7; > +} > + > +int h(int x) > +{ > + return ((x >> 9) & 1) << 7; > +} > + > +int i(int x) > +{ > + return (x & 512) >> 9 << 7; > +} > + > +int j(int x) > +{ > + return ((x >> 9) & 1) ? 128 : 0; > +} > + > +int k(int x) > +{ > + return (x & 512) ? 128 : 0; > +} > + > +/* { dg-final { scan-tree-dump-not " \\? " "original" } } */ > +/* { dg-final { scan-assembler-not "sall" { target i?86-*-* x86_64-*-* } } > }" */ > Index: testsuite/gcc.dg/fold-and-rshift-2.c > =================================================================== > --- testsuite/gcc.dg/fold-and-rshift-2.c (revision 0) > +++ testsuite/gcc.dg/fold-and-rshift-2.c (working copy) > @@ -0,0 +1,25 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O -fdump-tree-original" } */ > + > +unsigned f(unsigned x) > +{ > + return (x >> 29) & 32; > +} > + > +unsigned g(unsigned x) > +{ > + return !!(x & 0x80000000) << 5; > +} > + > +unsigned j(unsigned x) > +{ > + return ((x >> 31) & 1) ? 32 : 0; > +} > + > +unsigned k(unsigned x) > +{ > + return (x & 0x80000000) ? 32 : 0; > +} > + > +/* { dg-final { scan-tree-dump-not " \\? " "original" } } */ > +/* { dg-final { scan-assembler-not "sall" { target i?86-*-* x86_64-*-* } } > }" */ > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)