[backport gcc-4.9/trunk r199350 ] gcc/ 2013-05-27 Richard Biener PR tree-optimization/57396 * tree-affine.c (double_int_constant_multiple_p): Properly return false for val == 0 and div != 0. gcc/testsuite/ 2013-05-27 Richard Biener PR tree-optimization/57396 * gfortran.fortran-torture/execute/pr57396.f90: New testcase. --- gcc-4.8.1/gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.8.1/gcc/testsuite/gfortran.fortran-torture/execute/pr57396.f90 2013-06-01 10:39:02.882165017 +0200 @@ -0,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 --- gcc-4.8.1/gcc/tree-affine.c.~1~ 2013-01-10 21:38:27.000000000 +0100 +++ gcc-4.8.1/gcc/tree-affine.c 2013-06-01 10:39:02.882165017 +0200 @@ -736,11 +736,10 @@ free_affine_expand_cache (struct pointer } /* 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. */ + 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, @@ -749,7 +748,13 @@ double_int_constant_multiple_p (double_i double_int rem, cst; if (val.is_zero ()) - return true; + { + if (*mult_set && !mult->is_zero ()) + return false; + *mult_set = true; + *mult = double_int_zero; + return true; + } if (div.is_zero ()) return false;