https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66375
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> --- Indeed as we just feed the initial condition to chrec_convert it happily just fold_convert()s the zero to signed char and then back to int ... So res = follow_ssa_edge (loop, SSA_NAME_DEF_STMT (rhs0), halting_phi, evolution_of_loop, limit); if (res == t_true) *evolution_of_loop = add_to_evolution (loop->num, chrec_convert (type, *evolution_of_loop, at_stmt), code, rhs1, at_stmt); doesn't work at all (the follow_ssa_edge call just picking up the initial value converted to the type of the add). static tree analyze_evolution_in_loop (gphi *loop_phi_node, tree init_cond) { ... /* Pass in the initial condition to the follow edge function. */ ev_fn = init_cond; res = follow_ssa_edge (loop, ssa_chain, loop_phi_node, &ev_fn, 0); I suppose a trick would be to always pass a symbolic initial condition but then this would likely pessimize code. With that we get (add_to_evolution (loop_nb = 1) (chrec_before = (int) (signed char) D.1876) (to_add = -11) (res = {(int) (signed char) D.1876, +, -11}_1)) (evolution_function = {(int) (signed char) 0, +, -11}_1)) Hmm, but that isn't correct either. We want (int)(signed char){(int)0, +, -11)_1 Sorter testcase pin-pointing the issue in VRP/SCEV: int a; extern void abort (void); int main () { int c = 0; for (; a < 13; ++a) c = (signed char)c - 11; if (c != 113) abort (); return c; }