https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97567

--- Comment #2 from Andrew Macleod <amacleod at redhat dot com> ---
Created attachment 49441
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49441&action=edit
combine OR operands with union, not intersect

Fundamentally, this boils down to a bug in logical-combine.

calculating the range for f_21 on edge 11->17  


  <bb 11> :
  # iftmp.4_28 = PHI <1(9), 0(10), 1(8)>
  _10 = (long int) f_21;
  j_40 = g_25 - _10;
  _11 = _10 != g_25;
  _13 = _8 | _11;
  if (_13 != 0)
    goto <bb 12>; [INV]
  else
    goto <bb 17>; [INV]


this is the FALSE edge, so we want to deal with _13 = [0,0]

Unseen in this block is the definition of _8, which comes from a elsewhere
  _8 = f_21 != 0;

Notice f_21 can be calculated on both sides of the OR.

logical_combine figures out the ranges on each side and combines them.  it
correctly identifies that in order to take the false side, we need to only look
at  the values for f_21 where
 _8  [0,0] = f_21 != 0      in which case f_21 is [0,0]
and on the _11 side we cant really figure anything out, so we get VARYING when
_11 is [0,0]

logical combine then combines these values, and as this is an OR operation, it
can be any value from either op1 or op2... so it can be [0,0] or VARYING
which should be varying.

The code had a carry over from the AND, and was intersecting these values.. and
producing [0,0], which was then triggering new folds in substitute and fold
because it resolved to a constant.   incorrectly. 

As you can see in the patch, the comments were a little conflicting, but the
conclusion was the UNION of 2 values...   but then the code did an
intersection.

currently testing

Reply via email to