http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58417
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> --- So we want the evolution of sum_11 in the following loop (for a use on the exit edge): # i_18 = PHI <i_13(4), 1(2)> # sum_19 = PHI <sum_11(4), 0(2)> # prevsum_21 = PHI <prevsum_12(4), 0(2)> foo (sum_19); _7 = i_18 + -1; _8 = (long long int) _7; _9 = arr[i_18]; _10 = _8 * _9; sum_11 = _10 - prevsum_21; prevsum_12 = prevsum_21 + _9; i_13 = i_18 + 1; if (i_13 <= 5) goto <bb 4>; else goto <bb 5>; <bb 4>: goto <bb 3>; and we compute _10 = {0, +, _9}_1 _prevsum_21 = {0, +, _9}_1 but that is really meaningless as _9 is not a loop invariant which means that this two very CHRECs are not "valid" as far as I understand, not valid to operate on at least. Thus the following asserts should IMHO hold (and trigger on the testcase and many others) Index: gcc/tree-chrec.c =================================================================== --- gcc/tree-chrec.c (revision 202644) +++ gcc/tree-chrec.c (working copy) @@ -268,9 +268,14 @@ chrec_fold_plus_1 (enum tree_code code, switch (TREE_CODE (op0)) { case POLYNOMIAL_CHREC: + gcc_checking_assert + (!chrec_contains_symbols_defined_in_loop (op0, CHREC_VARIABLE (op0))); switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: + gcc_checking_assert + (!chrec_contains_symbols_defined_in_loop (op1, + CHREC_VARIABLE (op1))); return chrec_fold_plus_poly_poly (code, type, op0, op1); CASE_CONVERT: @@ -298,6 +303,9 @@ chrec_fold_plus_1 (enum tree_code code, switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: + gcc_checking_assert + (!chrec_contains_symbols_defined_in_loop (op1, + CHREC_VARIABLE (op1))); if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR) return build_polynomial_chrec (CHREC_VARIABLE (op1), @@ -396,9 +404,14 @@ chrec_fold_multiply (tree type, switch (TREE_CODE (op0)) { case POLYNOMIAL_CHREC: + gcc_checking_assert + (!chrec_contains_symbols_defined_in_loop (op0, CHREC_VARIABLE (op0))); switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: + gcc_checking_assert + (!chrec_contains_symbols_defined_in_loop (op1, + CHREC_VARIABLE (op1))); return chrec_fold_multiply_poly_poly (type, op0, op1); CASE_CONVERT: @@ -431,6 +444,9 @@ chrec_fold_multiply (tree type, switch (TREE_CODE (op1)) { case POLYNOMIAL_CHREC: + gcc_checking_assert + (!chrec_contains_symbols_defined_in_loop (op1, + CHREC_VARIABLE (op1))); return build_polynomial_chrec (CHREC_VARIABLE (op1), chrec_fold_multiply (type, CHREC_LEFT (op1), op0), as of the recursion we can fix that by making the cache used to guard against the recursion global (and maybe use instantiate_parameters instead of resolve_mixers).