> Oleg Endo wrote: > On 04 Sep 2015, at 01:54, Segher Boessenkool <seg...@kernel.crashing.org> > wrote: > > > On Thu, Sep 03, 2015 at 05:25:43PM +0100, Kyrill Tkachov wrote: > >>> void g(void); > >>> void f(int *x) { if (*x & 2) g(); } > > > >> A testcase I was looking at is: > >> int > >> foo (int a) > >> { > >> return (a & 7) != 0; > >> } > >> > >> For me this generates: > >> and w0, w0, 7 > >> cmp w0, wzr > >> cset w0, ne > >> ret > >> > >> when it could be: > >> tst w0, 7 > >> cset w0, ne > >> ret > > > > Interesting, thanks. > > > > That testcase with 4 (instead of 7) results in a single ubfx (a > > zero_extract) > > (this case is written differently before combine already, however). > > With 6 it does what you want (combine does not handle it as an extract, > > no matter what the docs say); and 7 is as you say (combine tries the > > extract, > > there is no insn like that).
(a & 1) != 0 is optimized earlier to a & 1, (a & 2) != 0 to a real zero_extract (non-zero shift), so these cases don't need a compare. return (a & C) ? 2 : 3 always uses a compare with zero, even for C=1. > I've been through this on SH. As it currently stands, to generate tst insns > basically 4 > different combine patterns are required: > - lsb (e.g. & 1) > - one bit (zero extract, e.g. & 2) > - n contiguous bits (zero extract, e.g. & 7) > - everything else (e.g. 4) Also: (a & 255) and (a & 65535) which are converted into zero_extend by combine. Interestingly a subreg is used depending on whether the operand is a virtual or physical reg - ((a + 1) & 255) == 0 vs (a & 65535) == 0: Failed to match this instruction: (set (reg:CC_ZESWP 66 cc) (compare:CC_ZESWP (reg:HI 0 x0 [ xD.2661 ]) (const_int 0 [0]))) Failed to match this instruction: (set (reg:CC_ZESWP 66 cc) (compare:CC_ZESWP (subreg:QI (reg:SI 80 [ D.2778 ]) 0) (const_int 0 [0]))) So that means another 2 patterns - and all that for one simple instruction... Wilco