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