Predictive commoning thinks that { a, +, a + 1 } and { 2 * a, +, a + 1 } are just 1 iteration apart because when verifying if the difference between a and 2*a is a multiple of a + 1 it falls into the trap of double_int_constant_multiple_p returning true (but not initializing a multiplier) for the question whether 0 is a multiple of 1 (the opposite question, whether 1 is a multiple of 0 is false of course). But it fails to set mult to zero in this case and the caller doesn't check for that.
Fixed by changing the semantics of double_int_constant_multiple_p to also record a zero as multiplier if VAL == 0. Bootstrap and regtest running on x86_64-unknown-linux-gnu. Zdenek, does this look ok? double_int_constant_multiple_p seems to be only used from aff_combination_constant_multiple_p. Thanks, Richard. 2013-05-24 Richard Biener <rguent...@suse.de> PR tree-optimization/57396 * tree-affine.c (double_int_constant_multiple_p): Properly return false for val == 0 and div != 0. * gfortran.fortran-torture/execute/pr57396.f90: New testcase. Index: gcc/tree-affine.c =================================================================== *** gcc/tree-affine.c (revision 199284) --- gcc/tree-affine.c (working copy) *************** free_affine_expand_cache (struct pointer *** 736,746 **** } /* If VAL != CST * DIV for any constant CST, returns false. ! Otherwise, if VAL != 0 (and hence CST != 0), and *MULT_SET is true, ! additionally compares CST and MULT, and if they are different, ! returns false. Finally, if neither of these two cases occur, ! true is returned, and if CST != 0, CST is stored to MULT and ! MULT_SET is set to true. */ static bool double_int_constant_multiple_p (double_int val, double_int div, --- 736,745 ---- } /* If VAL != CST * DIV for any constant CST, returns false. ! Otherwise, if *MULT_SET is true, additionally compares CST and MULT, ! and if they are different, returns false. Finally, if neither of these ! two cases occur, true is returned, and CST is stored to MULT and MULT_SET ! is set to true. */ static bool double_int_constant_multiple_p (double_int val, double_int div, *************** double_int_constant_multiple_p (double_i *** 749,755 **** double_int rem, cst; if (val.is_zero ()) ! return true; if (div.is_zero ()) return false; --- 748,760 ---- double_int rem, cst; if (val.is_zero ()) ! { ! if (*mult_set && !mult->is_zero ()) ! return false; ! *mult_set = true; ! *mult = double_int_zero; ! return true; ! } if (div.is_zero ()) return false; Index: gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90 =================================================================== *** gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90 (revision 0) --- gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90 (working copy) *************** *** 0 **** --- 1,33 ---- + module testmod + implicit none + + contains + + subroutine foo(n) + integer, intent(in) :: n + real :: r(0:n,-n:n), a(0:n,-n:n), dj + integer :: k, j + + ! initialize with some dummy values + do j = -n, n + a(:, j) = j + r(:,j) = j + 1 + end do + + ! here be dragons + do k = 0, n + dj = r(k, k - 2) * a(k, k - 2) + r(k,k) = a(k, k - 1) * dj + enddo + + if (r(0,0) .ne. -2.) call abort + + end subroutine + + end module + + program test + use testmod + implicit none + call foo(5) + end program