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

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
So for VARYING | 1 we go using the may_be_nonzero stuff in



      else if (code == BIT_IOR_EXPR)
        {
          max = wide_int_to_tree (expr_type,
                                  may_be_nonzero0 | may_be_nonzero1);
          wide_int wmin = must_be_nonzero0 | must_be_nonzero1;
          /* If the input ranges contain only positive values we can
             truncate the minimum of the result range to the maximum
             of the input range minima.  */
          if (int_cst_range0 && int_cst_range1
              && tree_int_cst_sgn (vr0.min) >= 0
              && tree_int_cst_sgn (vr1.min) >= 0)
            {
              wmin = wi::max (wmin, wi::to_wide (vr0.min),
                              TYPE_SIGN (expr_type));
              wmin = wi::max (wmin, wi::to_wide (vr1.min),
                              TYPE_SIGN (expr_type));
            }
          /* If either input range contains only negative values
             we can truncate the minimum of the result range to the
             respective minimum range.  */
          if (int_cst_range0 && tree_int_cst_sgn (vr0.max) < 0)
            wmin = wi::max (wmin, wi::to_wide (vr0.min),
                            TYPE_SIGN (expr_type));
          if (int_cst_range1 && tree_int_cst_sgn (vr1.max) < 0)
            wmin = wi::max (wmin, wi::to_wide (vr1.min),
                            TYPE_SIGN (expr_type));
          min = wide_int_to_tree (expr_type, wmin);

but for [MIN, MAX] we go

          /* For op & or | attempt to optimize:
             [x, y] op z into [x op z, y op z]
             if z is a constant which (for op | its bitwise not) has n
             consecutive least significant bits cleared followed by m 1
             consecutive bits set immediately above it and either
             m + n == precision, or (x >> (m + n)) == (y >> (m + n)).
             The least significant n bits of all the values in the range are
             cleared or set, the m bits above it are preserved and any bits
             above these are required to be the same for all values in the
             range.  */
          if (vr0p && range_int_cst_p (vr0p))
            {
              wide_int w = wi::to_wide (vr1p->min);
              int m = 0, n = 0;
              if (code == BIT_IOR_EXPR)
                w = ~w;
              if (wi::eq_p (w, 0))
 ...

and both cases produce a different outcome (as we see).

I don't see how we can do better.  Well, we can choose to handle
| CST with least significant bit set as ~[0, 0] consistently. Or
we can add a predicate effectively_varying_p () and guard the 2nd case
above with it.

The "proper" result for [MIN,MAX] | 1 is of course a set of every odd number...

Reply via email to