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

            Bug ID: 96146
           Summary: VRP turns a terminating loop into an infinite loop
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rsandifo at gcc dot gnu.org
  Target Milestone: ---
            Target: aarch64*-*-*

Compiling the following testcase with -O3 -march=armv8.2-a+sve
turns the loop into an infinite loop:

-------------------------------------------------------
#include <arm_sve.h>

int
f (volatile int *x)
{
  for (int i = 0; i < svcntd (); ++i)
    *x = i;
}
-------------------------------------------------------

Before vrp2 we have:

-------------------------------------------------------
  # i_11 = PHI <0(5), i_7(6)>
  *x_5(D) ={v} i_11;
  i_7 = i_11 + 1;
  if (i_7 != POLY_INT_CST [2, 2])
    goto <bb 6>; [89.00%]
  else
    goto <bb 4>; [11.00%]

  <bb 6> [local count: 850510901]:
  goto <bb 3>; [100.00%]
-------------------------------------------------------

but vrp changes the phi to:

  # i_11 = PHI <0(2), 1(3)>

The ASSERT_EXPR form is:

-------------------------------------------------------
  <bb 3> [local count: 955630225]:
  # i_11 = PHI <0(5), i_1(6)>
  *x_5(D) ={v} i_11;
  i_7 = i_11 + 1;
  if (i_7 != POLY_INT_CST [2, 2])
    goto <bb 6>; [89.00%]
  else
    goto <bb 4>; [11.00%]

  <bb 6> [local count: 850510901]:
  i_1 = ASSERT_EXPR <i_7, i_7 != POLY_INT_CST [2, 2]>;
  goto <bb 3>; [100.00%]
-------------------------------------------------------

During the first round we have:

---------------------------------------------------------------------
Found new range for i_11: int [0, 0]
…
Found new range for i_7: int [1, 1]
…
extract_range_from_stmt visiting:
if (i_7 != POLY_INT_CST [2, 2])

Visiting conditional with predicate: if (i_7 != POLY_INT_CST [2, 2])

With known ranges
        i_7: int [1, 1]

Predicate evaluates to: 1
…
extract_range_from_stmt visiting:
i_1 = ASSERT_EXPR <i_7, i_7 != POLY_INT_CST [2, 2]>;
Intersecting
  int [-INF, 1]  EQUIVALENCES: { i_7 } (1 elements)
and
  int [1, 1]
to
  int [1, 1]  EQUIVALENCES: { i_7 } (1 elements)
Intersecting
  int [1, 1]  EQUIVALENCES: { i_7 } (1 elements)
and
  int [1, +INF]
to
  int [1, 1]  EQUIVALENCES: { i_7 } (1 elements)
Found new range for i_1: int [1, 1]  EQUIVALENCES: { } (0 elements)
---------------------------------------------------------------------

and the second time round:

---------------------------------------------------------------------
Found new range for i_11: int [0, 1]
…
Found new range for i_7: int [1, 2]
…
extract_range_from_stmt visiting:
if (i_7 != POLY_INT_CST [2, 2])

Visiting conditional with predicate: if (i_7 != POLY_INT_CST [2, 2])

With known ranges
        i_7: int [1, 2]

Predicate evaluates to: DON'T KNOW
…

------extract_range_from_stmt visiting:
i_1 = ASSERT_EXPR <i_7, i_7 != POLY_INT_CST [2, 2]>;
Intersecting
  int [-INF, 1]  EQUIVALENCES: { i_7 } (1 elements)
and
  int [1, 2]
to
  int [1, 1]  EQUIVALENCES: { i_7 } (1 elements)
Intersecting
  int [1, 1]  EQUIVALENCES: { i_7 } (1 elements)
and
  int [1, +INF]
to
  int [1, 1]  EQUIVALENCES: { i_7 } (1 elements)
---------------------------------------------------------------

which re-establishes the [1, 1] range, and so the simulation
stops there.

The bug doesn't occur for s/int/unsigned int/, or for svcntw()
instead of svcntd().

Reply via email to