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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2019-10-17
                 CC|                            |ebotcazou at gcc dot gnu.org,
                   |                            |rguenth at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #6)
> The reason the intersection gives [-INF, -8] is that compare_values (
> -7, e.7_8 + 9223372036854775806 ) returns -1 rather than -2.  And that is
> because it thinks exactly 9223372036854775806 is added to e.7_8, at which
> point it would be even for e.7_8 equal to LONG_MIN -2 and for any larger
> value larger.

Yes, that's how it is supposed to work.

> Though, when we created that e.7_8 + 9223372036854775806, we didn't mean
> that, we meant that the maximum value it can have is e.7_8 +
> 9223372036854775806 if e.7_8 is negative or 1, if it is > 1, the maximum
> value is LONG_MAX, i.e. we meant
> MIN (9223372036854775807, (__int128_t) e.7_8 + 9223372036854775806).
> So, I'm afraid we need to define exactly what we mean by symbolic + constant
> first and depending on that tweak compare_values, or intersect_ranges, or
> extract_range_from_plus_minus_expr.

We rely on overflow being undefined here and usually create symbolic ranges
from conditions like if (a > b - 10).

But yes, the intersection result looks suspicious (but translating the
range intersection example to one involving smaller numbers and singed char
type might make things easier to grok ;)).  The intersection is basically

Intersecting
  long int ~[-7, -1]  EQUIVALENCES: { ao_23 } (1 elements)
and
  long int [-INF, e.7_8 + (+INF -1)]  EQUIVALENCES: { } (0 elements)
to
  long int [-INF, -8]  EQUIVALENCES: { ao_23 } (1 elements)

IIRC compare_values doesn't look at symbolic SSA names value-range but it
should do the same as fold would do for -7 < e.7_8 + (+INF - 1) which
IIRC doesn't fold this because combining the two constants results in an
overflow.  So that's likely a bug in compare_values to say -1 here:

     /* Compute the difference between the constants.  If it overflows or
         underflows, this means that we can trivially compare the NAME with
         it and, consequently, the two values with each other.  */
      wide_int diff = wi::to_wide (cst) - wi::to_wide (inv);
      if (wi::cmp (0, wi::to_wide (inv), sgn)
          != wi::cmp (diff, wi::to_wide (cst), sgn))
        {
          const int res = wi::cmp (wi::to_wide (cst), wi::to_wide (inv), sgn);
          return cst1 ? res : -res;
        }

either that or when we created the symbolic range we "introduced"
undefined overflow.  IIRC there are some issues with adding/subtracting
one at least.

Reply via email to