On Wed, 11 May 2016, H.J. Lu wrote:
* fold-const.c (fold_binary_loc) [(X ^ Y) & Y]: Remove and merge with...
* match.pd ((X & Y) ^ Y): ... this.
It caused:
FAIL: gcc.dg/tree-ssa/vrp47.c scan-tree-dump-times vrp2 " & 1;" 0
on x86.
Ah, yes, logical_op_short_circuit so I didn't test it. Hmm, doesn't seem
so easy. We want to compute (int)(x==0) in a branch where x is known to be
in [0, 1]. VRP1 gives (int)(_Bool)(x^1). forwprop3 handles the double
conversion, which gives (x^1)&1. Here the new transform applies and gives
(~x)&1. VRP2 comes, and with (x^1)&1 it used to notice that this is just
x^1 (remember that x is in [0, 1] in this branch), while it doesn't know
what to do with (~x)&1. In the end, we get
notl %eax
andl $1, %eax
instead of
xorl $1, %eax
(andn doesn't seem to have a version with an immediate)
The transformation seems right to me, but we are then missing another
transformation like ~X & Y -> X ^ Y when we know that X & ~Y is 0 (the 1
bits of X are included in those of Y). That may not be easy with the
limited bit tracking we have. A version limited to constant Y of the form
2^n-1 (i.e. 0...01...1) where X has a range included in [0, Y] may be
simpler.
We could also simplify (int)(_Bool)x to x using VRP information that x is
in [0, 1], but apparently when VRP replaces x==0 with y=x^1,(_Bool)y, it
does not compute a range for the new variable y, and by the time the next
VRP pass comes, it is too late.
In the mean time, I propose xfailing this test...
--
Marc Glisse