This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]