> Oleg Endo wrote:
> On 04 Sep 2015, at 01:54, Segher Boessenkool <[email protected]>
> 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