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

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Seems it hangs when doing range_of_stmt on if (_17 >= -1) in
<bb 7> [local count: 227695545]:
l:
_13 = _11 * 1958960196;
b.9_14 = b;
_15 = _13 + b.9_14;
_16 = _15 + -1016458303;
e = _16;
_17 = _16 * 20;
if (_17 >= -1)
  goto <bb 8>; [5.50%]
else
  goto <bb 4>; [94.50%]

$5 = <basic_block 0x7fffea31d900 (7)>

The code added in r14-5109 seems to change the
[irange] int [-INF, 2147483626] MASK 0xfffffffc VALUE 0x1
range into
[irange] int [-INF, -1][1, 1][4, 2147483626] MASK 0xfffffffc VALUE 0x1
That is because it attempted to intersect it with
[irange] int [-INF, -1][1, 1][4, +INF]
derived from the mask & value.
For GCC 16, guess one question is if it can't do better, like
[irange] int [-INF, -3][1, 1][5, +INF] in this case, i.e. not only specify that
m_value is the only possibility on the [0, 3] range but at least grow it in
both directions from that value.  So instead of
      range = int_range<5> (type, wi::zero (prec), ub);
      // Then remove the specific value these bits contain from the range.
      wide_int value = m_value & ub;
      range.intersect (int_range<2> (type, value, value, VR_ANTI_RANGE));
do
      // Then remove the specific value these bits contain from the range.
      wide_int value = m_value & ub;
      range = int_range<5> (type, value - ub + 1, value + ub - 1);
      range.intersect (int_range<2> (type, value, value, VR_ANTI_RANGE));
(but carefully handle signed vs. unsigned types or too large UB for the
precision,
the above would work for signed types if ub is small enough only I guess).
Obviously for z == 1 the current code is already ok.

But why this change hangs the algorithm, no idea.

Reply via email to