[PATCH] Fix PR57343

Richard Biener rguenther@suse.de
Mon May 27 11:02:00 GMT 2013


The following fixes PR57343 - niter analysis uses multiple_of_p to
check whether a value is a multiple of another, but multiple_of_p
does not refrain from returning true for a * 10 and 10 even when
the multiplication may overflow (and changing that would pessimize
some callers at least while possibly fixing a latent bug in
extract_mul_div).  So the following guards the use of
multiple_of_p in niter analysis properly and implements the
important special-cases for wrapping types.

Bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk?

Thanks,
Richard.

2013-05-27  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/57343
	* tree-ssa-loop-niter.c (number_of_iterations_ne_max): Do not
	use multiple_of_p if not TYPE_OVERFLOW_UNDEFINED.
	(number_of_iterations_cond): Do not build the folded tree.

	* gcc.dg/torture/pr57343.c: New testcase.

Index: gcc/tree-ssa-loop-niter.c
===================================================================
*** gcc/tree-ssa-loop-niter.c	(revision 199350)
--- gcc/tree-ssa-loop-niter.c	(working copy)
*************** number_of_iterations_ne_max (mpz_t bnd,
*** 552,561 ****
  {
    double_int max;
    mpz_t d;
    bool bnds_u_valid = ((no_overflow && exit_must_be_taken)
  		       || mpz_sgn (bnds->below) >= 0);
  
!   if (multiple_of_p (TREE_TYPE (c), c, s))
      {
        /* If C is an exact multiple of S, then its value will be reached before
  	 the induction variable overflows (unless the loop is exited in some
--- 552,569 ----
  {
    double_int max;
    mpz_t d;
+   tree type = TREE_TYPE (c);
    bool bnds_u_valid = ((no_overflow && exit_must_be_taken)
  		       || mpz_sgn (bnds->below) >= 0);
  
!   if (integer_onep (s)
!       || (TREE_CODE (c) == INTEGER_CST
! 	  && TREE_CODE (s) == INTEGER_CST
! 	  && tree_to_double_int (c).mod (tree_to_double_int (s),
! 					 TYPE_UNSIGNED (type),
! 					 EXACT_DIV_EXPR).is_zero ())
!       || (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (c))
! 	  && multiple_of_p (type, c, s)))
      {
        /* If C is an exact multiple of S, then its value will be reached before
  	 the induction variable overflows (unless the loop is exited in some
*************** number_of_iterations_ne_max (mpz_t bnd,
*** 572,587 ****
       the whole # of iterations analysis will fail).  */
    if (!no_overflow)
      {
!       max = double_int::mask (TYPE_PRECISION (TREE_TYPE (c))
! 			     - tree_low_cst (num_ending_zeros (s), 1));
        mpz_set_double_int (bnd, max, true);
        return;
      }
  
    /* Now we know that the induction variable does not overflow, so the loop
       iterates at most (range of type / S) times.  */
!   mpz_set_double_int (bnd, double_int::mask (TYPE_PRECISION (TREE_TYPE (c))),
! 		      true);
  
    /* If the induction variable is guaranteed to reach the value of C before
       overflow, ... */
--- 580,594 ----
       the whole # of iterations analysis will fail).  */
    if (!no_overflow)
      {
!       max = double_int::mask (TYPE_PRECISION (type)
! 			      - tree_low_cst (num_ending_zeros (s), 1));
        mpz_set_double_int (bnd, max, true);
        return;
      }
  
    /* Now we know that the induction variable does not overflow, so the loop
       iterates at most (range of type / S) times.  */
!   mpz_set_double_int (bnd, double_int::mask (TYPE_PRECISION (type)), true);
  
    /* If the induction variable is guaranteed to reach the value of C before
       overflow, ... */
*************** number_of_iterations_cond (struct loop *
*** 1311,1317 ****
      }
  
    /* If the loop exits immediately, there is nothing to do.  */
!   if (integer_zerop (fold_build2 (code, boolean_type_node, iv0->base, iv1->base)))
      {
        niter->niter = build_int_cst (unsigned_type_for (type), 0);
        niter->max = double_int_zero;
--- 1318,1325 ----
      }
  
    /* If the loop exits immediately, there is nothing to do.  */
!   tree tem = fold_binary (code, boolean_type_node, iv0->base, iv1->base);
!   if (tem && integer_zerop (tem))
      {
        niter->niter = build_int_cst (unsigned_type_for (type), 0);
        niter->max = double_int_zero;
Index: gcc/testsuite/gcc.dg/torture/pr57343.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr57343.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr57343.c	(working copy)
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do run } */
+ 
+ int c = 0;
+ 
+ int
+ main ()
+ {
+   int i, f = 1;
+   for (i = 0; i < 5; i++)
+     {
+       --c;
+       unsigned char h = c * 100;
+       if (h == 0)
+ 	{
+ 	  f = 0;
+ 	  break;
+ 	}
+     }
+   if (f != 1)
+     __builtin_abort ();
+   return 0;
+ }



More information about the Gcc-patches mailing list