This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR57396
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Zdenek Dvorak <ook at ucw dot cz>
- Date: Fri, 24 May 2013 14:21:30 +0200 (CEST)
- Subject: [PATCH] Fix PR57396
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 <rguenther@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