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().