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.