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] Improve chrec_convert PR/21861 and PR/18403


Hello,

Here is a patch that solve some of the type conversion problems that
lead to unhandled expressions in the vectorizer, in loop-linear as
Daniel has pointed out, or more generally in all the users of the scev
analyzer, i.e. VRP.

Before this patch you'd get ugly expressions with lots of casts that
didn't fold like that:
ib_16 + (aint *) ((long unsigned int) {off_11, +, 1}_1 * 4)

After the patch you get simpler expressions that can be handled by the
optimizers like: {base, +, step}_loop
{ib_16 + (aint *) ((long unsigned int) off_11 * 4), +, 4B}_1

The patch fixes two TODOs left in the source: the first is in the
chrec_convert function, where we provide now more precise information
to convert_step, the second fixed todo is in VRP.

Bootstrapped and tested on i686-pc-linux-gnu and
x86_64-unknown-linux-gnu.  Ok for mainline?

Sebastian 

PS: I'm not happy with the following change, because this could be
done more transparently on demand, without systematically analyzing
all the loops for estimating their niter:

	(execute_vrp): Call estimate_numbers_of_iterations for refining the 
	information provided by scev analyzer.

I will send a patch to fix it once this one is in.

	Fixes PR 18403 and meta PR 21861.
	* Makefile.in (tree-chrec.o): Depend on CFGLOOP_H and TREE_FLOW_H.
	* tree-chrec.c: Include cfgloop.h and tree-flow.h.
	(evolution_function_is_invariant_rec_p,
	evolution_function_is_invariant_p): New.
	(chrec_convert): Use an extra parameter AT_STMT for refining the
	information that is passed down to convert_step.  Integrate the 
	code that was in count_ev_in_wider_type.
	* tree-chrec.h (count_ev_in_wider_type): Removed.
	(chrec_convert): Modify its declaration.
	(evolution_function_is_invariant_p): Declared.
	(evolution_function_is_affine_p): Use evolution_function_is_invariant_p.
	* tree-flow.h (can_count_iv_in_wider_type): Renamed convert_step.
	(scev_probably_wraps_p): Declared.
	* tree-scalar-evolution.c (count_ev_in_wider_type): Removed.
	(follow_ssa_edge_in_rhs, interpret_rhs_modify_expr):
	Use an extra parameter AT_STMT for refining the information that is
	passed down to convert_step.
	(follow_ssa_edge_inner_loop_phi, follow_ssa_edge,
	analyze_scalar_evolution_1): Initialize AT_STMT with the current
	analyzed statement.
	(instantiate_parameters_1): Don't know yet how to initialize AT_STMT.
	* tree-ssa-loop-ivopts.c (idx_find_step): Update the use of 
	can_count_iv_in_wider_type to use convert_step.
	* tree-ssa-loop-niter.c (can_count_iv_in_wider_type_bound): Move 
	code that is independent of the loop over the known iteration
	bounds to convert_step_widening, the rest is moved to
	proved_non_wrapping_p.
	(scev_probably_wraps_p): New.
	(can_count_iv_in_wider_type): Renamed convert_step.
	* tree-vrp.c (adjust_range_with_scev): Take an extra AT_STMT parameter.
	Use scev_probably_wraps_p for computing init_is_max.
	(vrp_visit_assignment): Pass the current analyzed statement to 
	adjust_range_with_scev.
	(execute_vrp): Call estimate_numbers_of_iterations for refining the 
	information provided by scev analyzer.

testsuite:

	* testsuite/gcc.dg/vect/vect-77.c: Remove xfail from lp64.
	* testsuite/gcc.dg/vect/vect-78.c: Same.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1497
diff -c -3 -p -r1.1497 Makefile.in
*** Makefile.in	6 Jun 2005 14:08:35 -0000	1.1497
--- Makefile.in	7 Jun 2005 12:20:29 -0000
*************** tree-browser.o : tree-browser.c tree-bro
*** 1862,1868 ****
     $(TM_H) coretypes.h
  tree-chrec.o: tree-chrec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(GGC_H) $(TREE_H) tree-chrec.h tree-pass.h $(PARAMS_H) \
!    $(DIAGNOSTIC_H) $(VARRAY_H)
  tree-scalar-evolution.o: tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) \
     $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \
--- 1862,1868 ----
     $(TM_H) coretypes.h
  tree-chrec.o: tree-chrec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(GGC_H) $(TREE_H) tree-chrec.h tree-pass.h $(PARAMS_H) \
!    $(DIAGNOSTIC_H) $(VARRAY_H) $(CFGLOOP_H) $(TREE_FLOW_H)
  tree-scalar-evolution.o: tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) \
     $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \
Index: tree-chrec.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.c,v
retrieving revision 2.18
diff -c -3 -p -r2.18 tree-chrec.c
*** tree-chrec.c	2 Jun 2005 21:55:49 -0000	2.18
--- tree-chrec.c	7 Jun 2005 12:20:29 -0000
*************** Software Foundation, 59 Temple Place - S
*** 32,37 ****
--- 32,39 ----
  #include "tree.h"
  #include "diagnostic.h"
  #include "varray.h"
+ #include "cfgloop.h"
+ #include "tree-flow.h"
  #include "tree-chrec.h"
  #include "tree-pass.h"
  #include "params.h"
*************** tree_contains_chrecs (tree expr, int *si
*** 905,910 ****
--- 907,963 ----
      }
  }
  
+ /* Recursive helper function.  */
+ 
+ static bool
+ evolution_function_is_invariant_rec_p (tree chrec, int loopnum)
+ {
+   if (evolution_function_is_constant_p (chrec))
+     return true;
+ 
+   if (TREE_CODE (chrec) == SSA_NAME 
+       && expr_invariant_in_loop_p (current_loops->parray[loopnum],
+ 				   chrec))
+     return true;
+ 
+   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
+       && CHREC_VARIABLE (chrec) == (unsigned) loopnum)
+     return false;
+ 
+   switch (TREE_CODE_LENGTH (TREE_CODE (chrec)))
+     {
+     case 2:
+       if (!evolution_function_is_invariant_rec_p (TREE_OPERAND (chrec, 1),
+ 						  loopnum))
+ 	return false;
+       
+     case 1:
+       if (!evolution_function_is_invariant_rec_p (TREE_OPERAND (chrec, 0),
+ 						  loopnum))
+ 	return false;
+       return true;
+ 
+     default:
+       return false;
+     }
+ 
+   return false;
+ }
+ 
+ /* Return true if CHREC is invariant in loop LOOPNUM, false otherwise. */
+ 
+ bool
+ evolution_function_is_invariant_p (tree chrec, int loopnum)
+ {
+   if (evolution_function_is_constant_p (chrec))
+     return true;
+   
+   if (current_loops != NULL)
+     return evolution_function_is_invariant_rec_p (chrec, loopnum);
+ 
+   return false;
+ }
+ 
  /* Determine whether the given tree is an affine multivariate
     evolution.  */
  
*************** nb_vars_in_chrec (tree chrec)
*** 1015,1025 ****
  
  
  
! /* Convert CHREC to TYPE.  The following is rule is always true:
!    TREE_TYPE (chrec) == TREE_TYPE (CHREC_LEFT (chrec)) == TREE_TYPE
!    (CHREC_RIGHT (chrec)).  An example of what could happen when adding
!    two chrecs and the type of the CHREC_RIGHT is different than
!    CHREC_LEFT is:
     
     {(uint) 0, +, (uchar) 10} +
     {(uint) 0, +, (uchar) 250}
--- 1068,1086 ----
  
  
  
! /* Convert CHREC to TYPE.  When the analyzer knows the context in
!    which the CHREC is built,
! 
!    - it sets AT_STMT to the statement that contains the definition of
!    the analyzed variable, otherwise the conversion is less accurate:
!    the information is used for determining a more accurate estimation
!    of the number of iterations.  By default AT_STMT could be safely
!    set to NULL_TREE.
! 
!    The following is rule is always true: TREE_TYPE (chrec) ==
!    TREE_TYPE (CHREC_LEFT (chrec)) == TREE_TYPE (CHREC_RIGHT (chrec)).
!    An example of what could happen when adding two chrecs and the type
!    of the CHREC_RIGHT is different than CHREC_LEFT is:
     
     {(uint) 0, +, (uchar) 10} +
     {(uint) 0, +, (uchar) 250}
*************** nb_vars_in_chrec (tree chrec)
*** 1034,1044 ****
  */
  
  tree 
! chrec_convert (tree type, 
! 	       tree chrec)
  {
!   tree ct;
!   
    if (automatically_generated_chrec_p (chrec))
      return chrec;
    
--- 1095,1104 ----
  */
  
  tree 
! chrec_convert (tree type, tree chrec, tree at_stmt)
  {
!   tree ct, res;
! 
    if (automatically_generated_chrec_p (chrec))
      return chrec;
    
*************** chrec_convert (tree type, 
*** 1046,1088 ****
    if (ct == type)
      return chrec;
  
!   if (TYPE_PRECISION (ct) < TYPE_PRECISION (type))
!     return count_ev_in_wider_type (type, chrec);
! 
!   switch (TREE_CODE (chrec))
      {
!     case POLYNOMIAL_CHREC:
!       return build_polynomial_chrec (CHREC_VARIABLE (chrec),
! 				     chrec_convert (type,
! 						    CHREC_LEFT (chrec)),
! 				     chrec_convert (type,
! 						    CHREC_RIGHT (chrec)));
  
!     default:
!       {
! 	tree res = fold_convert (type, chrec);
  
! 	/* Don't propagate overflows.  */
! 	if (CONSTANT_CLASS_P (res))
! 	  {
! 	    TREE_CONSTANT_OVERFLOW (res) = 0;
! 	    TREE_OVERFLOW (res) = 0;
! 	  }
  
! 	/* But reject constants that don't fit in their type after conversion.
! 	   This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the
! 	   natural values associated with TYPE_PRECISION and TYPE_UNSIGNED,
! 	   and can cause problems later when computing niters of loops.  Note
! 	   that we don't do the check before converting because we don't want
! 	   to reject conversions of negative chrecs to unsigned types.  */
! 	if (TREE_CODE (res) == INTEGER_CST
! 	    && TREE_CODE (type) == INTEGER_TYPE
! 	    && !int_fits_type_p (res, type))
! 	  res = chrec_dont_know;
  
! 	return res;
!       }
      }
  }
  
  /* Returns the type of the chrec.  */
--- 1106,1149 ----
    if (ct == type)
      return chrec;
  
!   if (evolution_function_is_affine_p (chrec))
      {
!       tree step = convert_step (current_loops->parray[CHREC_VARIABLE (chrec)],
!  				type, CHREC_LEFT (chrec), CHREC_RIGHT (chrec),
!  				at_stmt);
!       if (!step)
!  	return fold_convert (type, chrec);
  
!       return build_polynomial_chrec (CHREC_VARIABLE (chrec),
!  				     chrec_convert (type, CHREC_LEFT (chrec),
!  						    at_stmt),
!  				     step);
!     }
  
!   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
!     return chrec_dont_know;
  
!   res = fold_convert (type, chrec);
  
!   /* Don't propagate overflows.  */
!   if (CONSTANT_CLASS_P (res))
!     {
!       TREE_CONSTANT_OVERFLOW (res) = 0;
!       TREE_OVERFLOW (res) = 0;
      }
+ 
+   /* But reject constants that don't fit in their type after conversion.
+      This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the
+      natural values associated with TYPE_PRECISION and TYPE_UNSIGNED,
+      and can cause problems later when computing niters of loops.  Note
+      that we don't do the check before converting because we don't want
+      to reject conversions of negative chrecs to unsigned types.  */
+   if (TREE_CODE (res) == INTEGER_CST
+       && TREE_CODE (type) == INTEGER_TYPE
+       && !int_fits_type_p (res, type))
+     res = chrec_dont_know;
+ 
+   return res;
  }
  
  /* Returns the type of the chrec.  */
Index: tree-chrec.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.h,v
retrieving revision 2.8
diff -c -3 -p -r2.8 tree-chrec.h
*** tree-chrec.h	28 Apr 2005 05:38:34 -0000	2.8
--- tree-chrec.h	7 Jun 2005 12:20:29 -0000
*************** tree_is_chrec (tree expr)
*** 67,74 ****
  extern tree chrec_fold_plus (tree, tree, tree);
  extern tree chrec_fold_minus (tree, tree, tree);
  extern tree chrec_fold_multiply (tree, tree, tree);
! extern tree chrec_convert (tree, tree);
! extern tree count_ev_in_wider_type (tree, tree);
  extern tree chrec_type (tree);
  
  /* Operations.  */
--- 67,73 ----
  extern tree chrec_fold_plus (tree, tree, tree);
  extern tree chrec_fold_minus (tree, tree, tree);
  extern tree chrec_fold_multiply (tree, tree, tree);
! extern tree chrec_convert (tree, tree, tree);
  extern tree chrec_type (tree);
  
  /* Operations.  */
*************** evolution_function_is_constant_p (tree c
*** 146,151 ****
--- 145,151 ----
      }
  }
  
+ extern bool evolution_function_is_invariant_p (tree, int);
  /* Determine whether the given tree is an affine evolution function or not.  */
  
  static inline bool 
*************** evolution_function_is_affine_p (tree chr
*** 157,164 ****
    switch (TREE_CODE (chrec))
      {
      case POLYNOMIAL_CHREC:
!       if (evolution_function_is_constant_p (CHREC_LEFT (chrec))
! 	  && evolution_function_is_constant_p (CHREC_RIGHT (chrec)))
  	return true;
        else
  	return false;
--- 157,166 ----
    switch (TREE_CODE (chrec))
      {
      case POLYNOMIAL_CHREC:
!       if (evolution_function_is_invariant_p (CHREC_LEFT (chrec), 
! 					     CHREC_VARIABLE (chrec))
! 	  && evolution_function_is_invariant_p (CHREC_RIGHT (chrec),
! 						CHREC_VARIABLE (chrec)))
  	return true;
        else
  	return false;
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.117
diff -c -3 -p -r2.117 tree-flow.h
*** tree-flow.h	5 Jun 2005 18:07:42 -0000	2.117
--- tree-flow.h	7 Jun 2005 12:20:29 -0000
*************** tree find_loop_niter (struct loop *, edg
*** 658,664 ****
  tree loop_niter_by_eval (struct loop *, edge);
  tree find_loop_niter_by_eval (struct loop *, edge *);
  void estimate_numbers_of_iterations (struct loops *);
! tree can_count_iv_in_wider_type (struct loop *, tree, tree, tree, tree);
  void free_numbers_of_iterations_estimates (struct loops *);
  void rewrite_into_loop_closed_ssa (bitmap, unsigned);
  void verify_loop_closed_ssa (void);
--- 658,665 ----
  tree loop_niter_by_eval (struct loop *, edge);
  tree find_loop_niter_by_eval (struct loop *, edge *);
  void estimate_numbers_of_iterations (struct loops *);
! bool scev_probably_wraps_p (tree, tree, tree, tree, struct loop *, bool *);
! tree convert_step (struct loop *, tree, tree, tree, tree);
  void free_numbers_of_iterations_estimates (struct loops *);
  void rewrite_into_loop_closed_ssa (bitmap, unsigned);
  void verify_loop_closed_ssa (void);
Index: tree-scalar-evolution.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-scalar-evolution.c,v
retrieving revision 2.27
diff -c -3 -p -r2.27 tree-scalar-evolution.c
*** tree-scalar-evolution.c	5 Jun 2005 18:07:43 -0000	2.27
--- tree-scalar-evolution.c	7 Jun 2005 12:20:29 -0000
*************** find_var_scev_info (tree var)
*** 349,381 ****
    return &res->chrec;
  }
  
- /* Tries to express CHREC in wider type TYPE.  */
- 
- tree
- count_ev_in_wider_type (tree type, tree chrec)
- {
-   tree base, step;
-   struct loop *loop;
- 
-   if (!evolution_function_is_affine_p (chrec))
-     return fold_convert (type, chrec);
- 
-   base = CHREC_LEFT (chrec);
-   step = CHREC_RIGHT (chrec);
-   loop = current_loops->parray[CHREC_VARIABLE (chrec)];
- 
-   /* TODO -- if we knew the statement at that the conversion occurs,
-      we could pass it to can_count_iv_in_wider_type and get a better
-      result.  */
-   step = can_count_iv_in_wider_type (loop, type, base, step, NULL_TREE);
-   if (!step)
-     return fold_convert (type, chrec);
-   base = chrec_convert (type, base);
- 
-   return build_polynomial_chrec (CHREC_VARIABLE (chrec),
- 				 base, step);
- }
- 
  /* Return true when CHREC contains symbolic names defined in
     LOOP_NB.  */
  
--- 349,354 ----
*************** static bool follow_ssa_edge (struct loop
*** 1052,1057 ****
--- 1025,1031 ----
  
  static bool
  follow_ssa_edge_in_rhs (struct loop *loop,
+ 			tree at_stmt,
  			tree rhs, 
  			tree halting_phi, 
  			tree *evolution_of_loop)
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1071,1079 ****
      {
      case NOP_EXPR:
        /* This assignment is under the form "a_1 = (cast) rhs.  */
!       res = follow_ssa_edge_in_rhs (loop, TREE_OPERAND (rhs, 0), halting_phi, 
! 				    evolution_of_loop);
!       *evolution_of_loop = chrec_convert (TREE_TYPE (rhs), *evolution_of_loop);
        break;
  
      case INTEGER_CST:
--- 1045,1054 ----
      {
      case NOP_EXPR:
        /* This assignment is under the form "a_1 = (cast) rhs.  */
!       res = follow_ssa_edge_in_rhs (loop, at_stmt, TREE_OPERAND (rhs, 0),
! 				    halting_phi, evolution_of_loop);
!       *evolution_of_loop = chrec_convert (TREE_TYPE (rhs),
! 					  *evolution_of_loop, at_stmt);
        break;
  
      case INTEGER_CST:
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1107,1113 ****
  	      if (res)
  		*evolution_of_loop = add_to_evolution 
  		  (loop->num, 
! 		   chrec_convert (type_rhs, *evolution_of_loop), 
  		   PLUS_EXPR, rhs1);
  	      
  	      else
--- 1082,1088 ----
  	      if (res)
  		*evolution_of_loop = add_to_evolution 
  		  (loop->num, 
! 		   chrec_convert (type_rhs, *evolution_of_loop, at_stmt), 
  		   PLUS_EXPR, rhs1);
  	      
  	      else
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1119,1125 ****
  		  if (res)
  		    *evolution_of_loop = add_to_evolution 
  		      (loop->num, 
! 		       chrec_convert (type_rhs, *evolution_of_loop), 
  		       PLUS_EXPR, rhs0);
  		}
  	    }
--- 1094,1100 ----
  		  if (res)
  		    *evolution_of_loop = add_to_evolution 
  		      (loop->num, 
! 		       chrec_convert (type_rhs, *evolution_of_loop, at_stmt), 
  		       PLUS_EXPR, rhs0);
  		}
  	    }
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1133,1139 ****
  		 evolution_of_loop);
  	      if (res)
  		*evolution_of_loop = add_to_evolution 
! 		  (loop->num, chrec_convert (type_rhs, *evolution_of_loop), 
  		   PLUS_EXPR, rhs1);
  	    }
  	}
--- 1108,1115 ----
  		 evolution_of_loop);
  	      if (res)
  		*evolution_of_loop = add_to_evolution 
! 		  (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
! 					     at_stmt),
  		   PLUS_EXPR, rhs1);
  	    }
  	}
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1147,1153 ****
  	     evolution_of_loop);
  	  if (res)
  	    *evolution_of_loop = add_to_evolution 
! 	      (loop->num, chrec_convert (type_rhs, *evolution_of_loop), 
  	       PLUS_EXPR, rhs0);
  	}
  
--- 1123,1130 ----
  	     evolution_of_loop);
  	  if (res)
  	    *evolution_of_loop = add_to_evolution 
! 	      (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
! 					 at_stmt),
  	       PLUS_EXPR, rhs0);
  	}
  
*************** follow_ssa_edge_in_rhs (struct loop *loo
*** 1174,1180 ****
  				 evolution_of_loop);
  	  if (res)
  	    *evolution_of_loop = add_to_evolution 
! 		    (loop->num, chrec_convert (type_rhs, *evolution_of_loop), 
  		     MINUS_EXPR, rhs1);
  	}
        else
--- 1151,1158 ----
  				 evolution_of_loop);
  	  if (res)
  	    *evolution_of_loop = add_to_evolution 
! 		    (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
! 					       at_stmt),
  		     MINUS_EXPR, rhs1);
  	}
        else
*************** follow_ssa_edge_inner_loop_phi (struct l
*** 1391,1397 ****
  	  /* Follow the edges that exit the inner loop.  */
  	  bb = PHI_ARG_EDGE (loop_phi_node, i)->src;
  	  if (!flow_bb_inside_loop_p (loop, bb))
! 	    res = res || follow_ssa_edge_in_rhs (outer_loop, arg, halting_phi,
  						 evolution_of_loop);
  	}
  
--- 1369,1376 ----
  	  /* Follow the edges that exit the inner loop.  */
  	  bb = PHI_ARG_EDGE (loop_phi_node, i)->src;
  	  if (!flow_bb_inside_loop_p (loop, bb))
! 	    res = res || follow_ssa_edge_in_rhs (outer_loop, loop_phi_node,
! 						 arg, halting_phi,
  						 evolution_of_loop);
  	}
  
*************** follow_ssa_edge_inner_loop_phi (struct l
*** 1404,1410 ****
  
    /* Otherwise, compute the overall effect of the inner loop.  */
    ev = compute_overall_effect_of_inner_loop (loop, ev);
!   return follow_ssa_edge_in_rhs (outer_loop, ev, halting_phi,
  				 evolution_of_loop);
  }
  
--- 1383,1389 ----
  
    /* Otherwise, compute the overall effect of the inner loop.  */
    ev = compute_overall_effect_of_inner_loop (loop, ev);
!   return follow_ssa_edge_in_rhs (outer_loop, loop_phi_node, ev, halting_phi,
  				 evolution_of_loop);
  }
  
*************** follow_ssa_edge (struct loop *loop, 
*** 1456,1462 ****
        return false;
  
      case MODIFY_EXPR:
!       return follow_ssa_edge_in_rhs (loop,
  				     TREE_OPERAND (def, 1), 
  				     halting_phi, 
  				     evolution_of_loop);
--- 1435,1441 ----
        return false;
  
      case MODIFY_EXPR:
!       return follow_ssa_edge_in_rhs (loop, def,
  				     TREE_OPERAND (def, 1), 
  				     halting_phi, 
  				     evolution_of_loop);
*************** interpret_condition_phi (struct loop *lo
*** 1665,1678 ****
     analyze the effect of an inner loop: see interpret_loop_phi.  */
  
  static tree
! interpret_rhs_modify_expr (struct loop *loop,
  			   tree opnd1, tree type)
  {
    tree res, opnd10, opnd11, chrec10, chrec11;
!   
    if (is_gimple_min_invariant (opnd1))
!     return chrec_convert (type, opnd1);
!   
    switch (TREE_CODE (opnd1))
      {
      case PLUS_EXPR:
--- 1644,1657 ----
     analyze the effect of an inner loop: see interpret_loop_phi.  */
  
  static tree
! interpret_rhs_modify_expr (struct loop *loop, tree at_stmt,
  			   tree opnd1, tree type)
  {
    tree res, opnd10, opnd11, chrec10, chrec11;
! 
    if (is_gimple_min_invariant (opnd1))
!     return chrec_convert (type, opnd1, at_stmt);
! 
    switch (TREE_CODE (opnd1))
      {
      case PLUS_EXPR:
*************** interpret_rhs_modify_expr (struct loop *
*** 1680,1687 ****
        opnd11 = TREE_OPERAND (opnd1, 1);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
        chrec11 = analyze_scalar_evolution (loop, opnd11);
!       chrec10 = chrec_convert (type, chrec10);
!       chrec11 = chrec_convert (type, chrec11);
        res = chrec_fold_plus (type, chrec10, chrec11);
        break;
        
--- 1659,1666 ----
        opnd11 = TREE_OPERAND (opnd1, 1);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
        chrec11 = analyze_scalar_evolution (loop, opnd11);
!       chrec10 = chrec_convert (type, chrec10, at_stmt);
!       chrec11 = chrec_convert (type, chrec11, at_stmt);
        res = chrec_fold_plus (type, chrec10, chrec11);
        break;
        
*************** interpret_rhs_modify_expr (struct loop *
*** 1690,1704 ****
        opnd11 = TREE_OPERAND (opnd1, 1);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
        chrec11 = analyze_scalar_evolution (loop, opnd11);
!       chrec10 = chrec_convert (type, chrec10);
!       chrec11 = chrec_convert (type, chrec11);
        res = chrec_fold_minus (type, chrec10, chrec11);
        break;
  
      case NEGATE_EXPR:
        opnd10 = TREE_OPERAND (opnd1, 0);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
!       chrec10 = chrec_convert (type, chrec10);
        res = chrec_fold_minus (type, build_int_cst (type, 0), chrec10);
        break;
  
--- 1669,1683 ----
        opnd11 = TREE_OPERAND (opnd1, 1);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
        chrec11 = analyze_scalar_evolution (loop, opnd11);
!       chrec10 = chrec_convert (type, chrec10, at_stmt);
!       chrec11 = chrec_convert (type, chrec11, at_stmt);
        res = chrec_fold_minus (type, chrec10, chrec11);
        break;
  
      case NEGATE_EXPR:
        opnd10 = TREE_OPERAND (opnd1, 0);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
!       chrec10 = chrec_convert (type, chrec10, at_stmt);
        res = chrec_fold_minus (type, build_int_cst (type, 0), chrec10);
        break;
  
*************** interpret_rhs_modify_expr (struct loop *
*** 1707,1731 ****
        opnd11 = TREE_OPERAND (opnd1, 1);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
        chrec11 = analyze_scalar_evolution (loop, opnd11);
!       chrec10 = chrec_convert (type, chrec10);
!       chrec11 = chrec_convert (type, chrec11);
        res = chrec_fold_multiply (type, chrec10, chrec11);
        break;
        
      case SSA_NAME:
!       res = chrec_convert (type, analyze_scalar_evolution (loop, opnd1));
        break;
  
      case ASSERT_EXPR:
        opnd10 = ASSERT_EXPR_VAR (opnd1);
!       res = chrec_convert (type, analyze_scalar_evolution (loop, opnd10));
        break;
        
      case NOP_EXPR:
      case CONVERT_EXPR:
        opnd10 = TREE_OPERAND (opnd1, 0);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
!       res = chrec_convert (type, chrec10);
        break;
        
      default:
--- 1686,1712 ----
        opnd11 = TREE_OPERAND (opnd1, 1);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
        chrec11 = analyze_scalar_evolution (loop, opnd11);
!       chrec10 = chrec_convert (type, chrec10, at_stmt);
!       chrec11 = chrec_convert (type, chrec11, at_stmt);
        res = chrec_fold_multiply (type, chrec10, chrec11);
        break;
        
      case SSA_NAME:
!       res = chrec_convert (type, analyze_scalar_evolution (loop, opnd1),
! 			   at_stmt);
        break;
  
      case ASSERT_EXPR:
        opnd10 = ASSERT_EXPR_VAR (opnd1);
!       res = chrec_convert (type, analyze_scalar_evolution (loop, opnd10),
! 			   at_stmt);
        break;
        
      case NOP_EXPR:
      case CONVERT_EXPR:
        opnd10 = TREE_OPERAND (opnd1, 0);
        chrec10 = analyze_scalar_evolution (loop, opnd10);
!       res = chrec_convert (type, chrec10, at_stmt);
        break;
        
      default:
*************** analyze_scalar_evolution_1 (struct loop 
*** 1775,1781 ****
      return chrec_dont_know;
  
    if (TREE_CODE (var) != SSA_NAME)
!     return interpret_rhs_modify_expr (loop, var, type);
  
    def = SSA_NAME_DEF_STMT (var);
    bb = bb_for_stmt (def);
--- 1756,1762 ----
      return chrec_dont_know;
  
    if (TREE_CODE (var) != SSA_NAME)
!     return interpret_rhs_modify_expr (loop, NULL_TREE, var, type);
  
    def = SSA_NAME_DEF_STMT (var);
    bb = bb_for_stmt (def);
*************** analyze_scalar_evolution_1 (struct loop 
*** 1809,1815 ****
    switch (TREE_CODE (def))
      {
      case MODIFY_EXPR:
!       res = interpret_rhs_modify_expr (loop, TREE_OPERAND (def, 1), type);
        break;
  
      case PHI_NODE:
--- 1790,1796 ----
    switch (TREE_CODE (def))
      {
      case MODIFY_EXPR:
!       res = interpret_rhs_modify_expr (loop, def, TREE_OPERAND (def, 1), type);
        break;
  
      case PHI_NODE:
*************** instantiate_parameters_1 (struct loop *l
*** 2093,2099 ****
        if (op0 == TREE_OPERAND (chrec, 0))
  	return chrec;
  
!       return chrec_convert (TREE_TYPE (chrec), op0);
  
      case SCEV_NOT_KNOWN:
        return chrec_dont_know;
--- 2074,2080 ----
        if (op0 == TREE_OPERAND (chrec, 0))
  	return chrec;
  
!       return chrec_convert (TREE_TYPE (chrec), op0, NULL_TREE);
  
      case SCEV_NOT_KNOWN:
        return chrec_dont_know;
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.75
diff -c -3 -p -r2.75 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c	2 Jun 2005 22:05:13 -0000	2.75
--- tree-ssa-loop-ivopts.c	7 Jun 2005 12:20:29 -0000
*************** idx_find_step (tree base, tree *idx, voi
*** 1442,1452 ****
      /* The step for pointer arithmetics already is 1 byte.  */
      step = build_int_cst (sizetype, 1);
  
!   if (TYPE_PRECISION (TREE_TYPE (iv->base)) < TYPE_PRECISION (sizetype))
!     iv_step = can_count_iv_in_wider_type (dta->ivopts_data->current_loop,
! 					  sizetype, iv->base, iv->step, dta->stmt);
!   else
!     iv_step = fold_convert (sizetype, iv->step);
  
    if (!iv_step)
      {
--- 1442,1449 ----
      /* The step for pointer arithmetics already is 1 byte.  */
      step = build_int_cst (sizetype, 1);
  
!   iv_step = convert_step (dta->ivopts_data->current_loop,
! 			  sizetype, iv->base, iv->step, dta->stmt);
  
    if (!iv_step)
      {
Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-niter.c,v
retrieving revision 2.28
diff -c -3 -p -r2.28 tree-ssa-loop-niter.c
*** tree-ssa-loop-niter.c	5 Jun 2005 18:07:43 -0000	2.28
--- tree-ssa-loop-niter.c	7 Jun 2005 12:20:29 -0000
*************** stmt_dominates_stmt_p (tree s1, tree s2)
*** 1445,1457 ****
    return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
  }
  
! /* Checks whether it is correct to count the induction variable BASE + STEP * I
!    at AT_STMT in wider TYPE, using the fact that statement OF is executed at
!    most BOUND times in the loop.  If it is possible, return the value of step
!    of the induction variable in the TYPE, otherwise return NULL_TREE.
     
!    ADDITIONAL is the additional condition recorded for operands of the bound.
!    This is useful in the following case, created by loop header copying:
  
     i = 0;
     if (n > 0)
--- 1445,1462 ----
    return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
  }
  
! /* Return true when it is possible to prove that the induction
!    variable does not wrap: vary outside the type specified bounds.
!    Checks whether BOUND < VALID_NITER that means in the context of iv
!    conversion that all the iterations in the loop are safe: not
!    producing wraps.
! 
!    The statement NITER_BOUND->AT_STMT is executed at most
!    NITER_BOUND->BOUND times in the loop.
     
!    NITER_BOUND->ADDITIONAL is the additional condition recorded for
!    operands of the bound.  This is useful in the following case,
!    created by loop header copying:
  
     i = 0;
     if (n > 0)
*************** stmt_dominates_stmt_p (tree s1, tree s2)
*** 1465,1572 ****
     assumption "n > 0" says us that the value of the number of iterations is at
     most MAX_TYPE - 1 (without this assumption, it might overflow).  */
  
! static tree
! can_count_iv_in_wider_type_bound (tree type, tree base, tree step,
! 				  tree at_stmt,
! 				  tree bound,
! 				  tree additional,
! 				  tree of)
  {
-   tree inner_type = TREE_TYPE (base), b, bplusstep, new_step, new_step_abs;
-   tree valid_niter, extreme, unsigned_type, delta, bound_type;
    tree cond;
  
!   b = fold_convert (type, base);
!   bplusstep = fold_convert (type,
! 			    fold_build2 (PLUS_EXPR, inner_type, base, step));
!   new_step = fold_build2 (MINUS_EXPR, type, bplusstep, b);
!   if (TREE_CODE (new_step) != INTEGER_CST)
      return NULL_TREE;
  
!   switch (compare_trees (bplusstep, b))
      {
      case -1:
!       extreme = upper_bound_in_type (type, inner_type);
!       delta = fold_build2 (MINUS_EXPR, type, extreme, b);
!       new_step_abs = new_step;
!       break;
  
      case 1:
!       extreme = lower_bound_in_type (type, inner_type);
!       new_step_abs = fold_build1 (NEGATE_EXPR, type, new_step);
!       delta = fold_build2 (MINUS_EXPR, type, b, extreme);
!       break;
  
      case 0:
!       return new_step;
  
      default:
        return NULL_TREE;
      }
  
!   unsigned_type = unsigned_type_for (type);
    delta = fold_convert (unsigned_type, delta);
!   new_step_abs = fold_convert (unsigned_type, new_step_abs);
    valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type,
! 			     delta, new_step_abs);
  
!   bound_type = TREE_TYPE (bound);
!   if (TYPE_PRECISION (type) > TYPE_PRECISION (bound_type))
!     bound = fold_convert (unsigned_type, bound);
!   else
!     valid_niter = fold_convert (bound_type, valid_niter);
!     
!   if (at_stmt && stmt_dominates_stmt_p (of, at_stmt))
!     {
!       /* After the statement OF we know that anything is executed at most
! 	 BOUND times.  */
!       cond = fold_build2 (GE_EXPR, boolean_type_node, valid_niter, bound);
!     }
!   else
      {
!       /* Before the statement OF we know that anything is executed at most
! 	 BOUND + 1 times.  */
!       cond = fold_build2 (GT_EXPR, boolean_type_node, valid_niter, bound);
      }
  
!   if (nonzero_p (cond))
!     return new_step;
  
!   /* Try taking additional conditions into account.  */
!   cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
! 		      invert_truthvalue (additional),
! 		      cond);
!   if (nonzero_p (cond))
!     return new_step;
  
!   return NULL_TREE;
  }
  
! /* Checks whether it is correct to count the induction variable BASE + STEP * I
!    at AT_STMT in wider TYPE, using the bounds on numbers of iterations of a
!    LOOP.  If it is possible, return the value of step of the induction variable
!    in the TYPE, otherwise return NULL_TREE.  */
  
  tree
! can_count_iv_in_wider_type (struct loop *loop, tree type, tree base, tree step,
! 			    tree at_stmt)
  {
!   struct nb_iter_bound *bound;
!   tree new_step;
  
!   for (bound = loop->bounds; bound; bound = bound->next)
!     {
!       new_step = can_count_iv_in_wider_type_bound (type, base, step,
! 						   at_stmt,
! 						   bound->bound,
! 						   bound->additional,
! 						   bound->at_stmt);
  
!       if (new_step)
! 	return new_step;
!     }
  
!   return NULL_TREE;
  }
  
  /* Frees the information on upper bounds on numbers of iterations of LOOP.  */
--- 1470,1680 ----
     assumption "n > 0" says us that the value of the number of iterations is at
     most MAX_TYPE - 1 (without this assumption, it might overflow).  */
  
! static bool
! proved_non_wrapping_p (tree at_stmt,
! 		       struct nb_iter_bound *niter_bound, 
! 		       tree new_type,
! 		       tree valid_niter)
  {
    tree cond;
+   tree bound = niter_bound->bound;
+ 
+   if (TYPE_PRECISION (new_type) > TYPE_PRECISION (TREE_TYPE (bound)))
+     bound = fold_convert (unsigned_type_for (new_type), bound);
+   else
+     valid_niter = fold_convert (TREE_TYPE (bound), valid_niter);
+ 
+   /* After the statement niter_bound->at_stmt we know that anything is
+      executed at most BOUND times.  */
+   if (at_stmt && stmt_dominates_stmt_p (niter_bound->at_stmt, at_stmt))
+     cond = fold_build2 (GE_EXPR, boolean_type_node, valid_niter, bound);
+ 
+   /* Before the statement niter_bound->at_stmt we know that anything
+      is executed at most BOUND + 1 times.  */
+   else
+     cond = fold_build2 (GT_EXPR, boolean_type_node, valid_niter, bound);
+ 
+   if (nonzero_p (cond))
+     return true;
+ 
+   /* Try taking additional conditions into account.  */
+   cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
+ 		      invert_truthvalue (niter_bound->additional),
+ 		      cond);
+ 
+   if (nonzero_p (cond))
+     return true;
  
!   return false;
! }
! 
! /* Checks whether it is correct to count the induction variable BASE +
!    STEP * I at AT_STMT in a wider type NEW_TYPE, using the bounds on
!    numbers of iterations of a LOOP.  If it is possible, return the
!    value of step of the induction variable in the NEW_TYPE, otherwise
!    return NULL_TREE.  */
! 
! static tree
! convert_step_widening (struct loop *loop, tree new_type, tree base, tree step,
! 		       tree at_stmt)
! {
!   struct nb_iter_bound *bound;
!   tree base_in_new_type, base_plus_step_in_new_type, step_in_new_type;
!   tree delta, step_abs;
!   tree unsigned_type, valid_niter;
! 
!   /* Compute the new step.  For example, {(uchar) 100, +, (uchar) 240}
!      is converted to {(uint) 100, +, (uint) 0xfffffff0} in order to
!      keep the values of the induction variable unchanged: 100, 84, 68,
!      ...
! 
!      Another example is: (uint) {(uchar)100, +, (uchar)3} is converted
!      to {(uint)100, +, (uint)3}.  
! 
!      Before returning the new step, verify that the number of
!      iterations is less than DELTA / STEP_ABS (i.e. in the previous
!      example (256 - 100) / 3) such that the iv does not wrap (in which
!      case the operations are too difficult to be represented and
!      handled: the values of the iv should be taken modulo 256 in the
!      wider type; this is not implemented).  */
!   base_in_new_type = fold_convert (new_type, base);
!   base_plus_step_in_new_type = 
!     fold_convert (new_type,
! 		  fold_build2 (PLUS_EXPR, TREE_TYPE (base), base, step));
!   step_in_new_type = fold_build2 (MINUS_EXPR, new_type,
! 				  base_plus_step_in_new_type,
! 				  base_in_new_type);
! 
!   if (TREE_CODE (step_in_new_type) != INTEGER_CST)
      return NULL_TREE;
  
!   switch (compare_trees (base_plus_step_in_new_type, base_in_new_type))
      {
      case -1:
!       {
! 	tree extreme = upper_bound_in_type (new_type, TREE_TYPE (base));
! 	delta = fold_build2 (MINUS_EXPR, new_type, extreme,
! 			     base_in_new_type);
! 	step_abs = step_in_new_type;
! 	break;
!       }
  
      case 1:
!       {
! 	tree extreme = lower_bound_in_type (new_type, TREE_TYPE (base));
! 	delta = fold_build2 (MINUS_EXPR, new_type, base_in_new_type,
! 			     extreme);
! 	step_abs = fold_build1 (NEGATE_EXPR, new_type, step_in_new_type);
! 	break;
!       }
  
      case 0:
!       return step_in_new_type;
  
      default:
        return NULL_TREE;
      }
  
!   unsigned_type = unsigned_type_for (new_type);
    delta = fold_convert (unsigned_type, delta);
!   step_abs = fold_convert (unsigned_type, step_abs);
    valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type,
! 			     delta, step_abs);
  
!   for (bound = loop->bounds; bound; bound = bound->next)
!     if (proved_non_wrapping_p (at_stmt, bound, new_type, valid_niter))
!       return step_in_new_type;
! 
!   /* Fail when the loop has no bound estimations, or when no bound can
!      be used for verifying the conversion.  */
!   return NULL_TREE;
! }
! 
! /* Return false only when the induction variable BASE + STEP * I is
!    known to not overflow: i.e. when the number of iterations is small
!    enough with respect to the step and initial condition in order to
!    keep the evolution confined in TYPEs bounds.  Return true when the
!    iv is known to overflow or when the property is not computable.
! 
!    Initialize INIT_IS_MAX to true when the evolution goes from
!    INIT_IS_MAX to LOWER_BOUND_IN_TYPE, false in the contrary case, not
!    defined when the function returns true.  */
! 
! bool
! scev_probably_wraps_p (tree type, tree base, tree step, 
! 		       tree at_stmt, struct loop *loop,
! 		       bool *init_is_max)
! {
!   struct nb_iter_bound *bound;
!   tree delta, step_abs;
!   tree unsigned_type, valid_niter;
!   tree base_plus_step = fold_build2 (PLUS_EXPR, type, base, step);
! 
!   switch (compare_trees (base_plus_step, base))
      {
!     case -1:
!       {
! 	tree extreme = upper_bound_in_type (type, TREE_TYPE (base));
! 	delta = fold_build2 (MINUS_EXPR, type, extreme, base);
! 	step_abs = step;
! 	*init_is_max = false;
! 	break;
!       }
! 
!     case 1:
!       {
! 	tree extreme = lower_bound_in_type (type, TREE_TYPE (base));
! 	delta = fold_build2 (MINUS_EXPR, type, base, extreme);
! 	step_abs = fold_build1 (NEGATE_EXPR, type, step);
! 	*init_is_max = true;
! 	break;
!       }
! 
!     case 0:
!       /* This means step is equal to 0.  This should not happen.  It
! 	 could happen in convert step, but not here.  Safely answer
! 	 don't know as in the default case.  */
! 
!     default:
!       return true;
      }
  
!   /* After having set INIT_IS_MAX, we can return false: when not using
!      wrapping arithmetic, signed types don't wrap.  */
!   if (!flag_wrapv && !TYPE_UNSIGNED (type))
!     return false;
  
!   unsigned_type = unsigned_type_for (type);
!   delta = fold_convert (unsigned_type, delta);
!   step_abs = fold_convert (unsigned_type, step_abs);
!   valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type, delta, step_abs);
  
!   for (bound = loop->bounds; bound; bound = bound->next)
!     if (proved_non_wrapping_p (at_stmt, bound, type, valid_niter))
!       return false;
! 
!   /* At this point we still don't have a proof that the iv does not
!      overflow: give up.  */
!   return true;
  }
  
! /* Return the conversion to NEW_TYPE of the STEP of an induction
!    variable BASE + STEP * I at AT_STMT.  */
  
  tree
! convert_step (struct loop *loop, tree new_type, tree base, tree step,
! 	      tree at_stmt)
  {
!   tree base_type = TREE_TYPE (base);
  
!   /* When not using wrapping arithmetic, signed types don't wrap.  */
!   if (!flag_wrapv && !TYPE_UNSIGNED (base_type))
!     return fold_convert (new_type, step);
  
!   if (TYPE_PRECISION (new_type) > TYPE_PRECISION (base_type))
!     return convert_step_widening (loop, new_type, base, step, at_stmt);
  
!   return fold_convert (new_type, step);
  }
  
  /* Frees the information on upper bounds on numbers of iterations of LOOP.  */
Index: tree-vrp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-vrp.c,v
retrieving revision 2.23
diff -c -3 -p -r2.23 tree-vrp.c
*** tree-vrp.c	3 Jun 2005 21:07:08 -0000	2.23
--- tree-vrp.c	7 Jun 2005 12:20:37 -0000
*************** extract_range_from_expr (value_range_t *
*** 1427,1439 ****
      set_value_range_to_varying (vr);
  }
  
! 
! /* Given a range VR, a loop L and a variable VAR, determine whether it
     would be profitable to adjust VR using scalar evolution information
     for VAR.  If so, update VR with the new limits.  */
  
  static void
! adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var)
  {
    tree init, step, chrec;
    bool init_is_max;
--- 1427,1439 ----
      set_value_range_to_varying (vr);
  }
  
! /* Given a range VR, a LOOP and a variable VAR, determine whether it
     would be profitable to adjust VR using scalar evolution information
     for VAR.  If so, update VR with the new limits.  */
  
  static void
! adjust_range_with_scev (value_range_t *vr, struct loop *loop, tree stmt,
! 			tree var)
  {
    tree init, step, chrec;
    bool init_is_max;
*************** adjust_range_with_scev (value_range_t *v
*** 1443,1449 ****
    if (vr->type == VR_ANTI_RANGE)
      return;
  
!   chrec = analyze_scalar_evolution (l, var);
    if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
      return;
  
--- 1443,1449 ----
    if (vr->type == VR_ANTI_RANGE)
      return;
  
!   chrec = analyze_scalar_evolution (loop, var);
    if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
      return;
  
*************** adjust_range_with_scev (value_range_t *v
*** 1455,1476 ****
    if (!is_gimple_min_invariant (step))
      return;
  
!   /* FIXME.  When dealing with unsigned types,
!      analyze_scalar_evolution sets STEP to very large unsigned values
!      when the evolution goes backwards.  This confuses this analysis
!      because we think that INIT is the smallest value that the range
!      can take, instead of the largest.  Ignore these chrecs for now.  */
!   if (INTEGRAL_TYPE_P (TREE_TYPE (step)) && TYPE_UNSIGNED (TREE_TYPE (step)))
!     return;
! 
!   /* Do not adjust ranges when using wrapping arithmetic.  */
!   if (flag_wrapv)
      return;
  
-   /* If STEP is negative, then INIT is the maximum value the range
-      will take.  Otherwise, INIT is the minimum value.  */
-   init_is_max = (tree_int_cst_sgn (step) < 0);
- 
    if (!POINTER_TYPE_P (TREE_TYPE (init))
        && (vr->type == VR_VARYING || vr->type == VR_UNDEFINED))
      {
--- 1455,1466 ----
    if (!is_gimple_min_invariant (step))
      return;
  
!   /* Do not adjust ranges when chrec may wrap.  */
!   if (scev_probably_wraps_p (chrec_type (chrec), init, step, stmt,
! 			     cfg_loops->parray[CHREC_VARIABLE (chrec)],
! 			     &init_is_max))
      return;
  
    if (!POINTER_TYPE_P (TREE_TYPE (init))
        && (vr->type == VR_VARYING || vr->type == VR_UNDEFINED))
      {
*************** vrp_visit_assignment (tree stmt, tree *o
*** 2772,2778 ****
  	 else about the range of LHS by examining scalar evolution
  	 information.  */
        if (cfg_loops && (l = loop_containing_stmt (stmt)))
! 	adjust_range_with_scev (&new_vr, l, lhs);
  
        if (update_value_range (lhs, &new_vr))
  	{
--- 2762,2768 ----
  	 else about the range of LHS by examining scalar evolution
  	 information.  */
        if (cfg_loops && (l = loop_containing_stmt (stmt)))
! 	adjust_range_with_scev (&new_vr, l, stmt, lhs);
  
        if (update_value_range (lhs, &new_vr))
  	{
*************** execute_vrp (void)
*** 3519,3525 ****
  
    cfg_loops = loop_optimizer_init (NULL);
    if (cfg_loops)
!     scev_initialize (cfg_loops);
  
    vrp_initialize ();
    ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
--- 3509,3518 ----
  
    cfg_loops = loop_optimizer_init (NULL);
    if (cfg_loops)
!     {
!       scev_initialize (cfg_loops);
!       estimate_numbers_of_iterations (cfg_loops);
!     }
  
    vrp_initialize ();
    ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
Index: testsuite/gcc.dg/vect/vect-77.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-77.c,v
retrieving revision 1.10
diff -c -3 -p -r1.10 vect-77.c
*** testsuite/gcc.dg/vect/vect-77.c	31 Mar 2005 18:34:19 -0000	1.10
--- testsuite/gcc.dg/vect/vect-77.c	7 Jun 2005 12:20:44 -0000
*************** int main (void)
*** 39,45 ****
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
! /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
  /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
--- 39,45 ----
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align } } } } */
! /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { vect_no_align } } } } */
  /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
Index: testsuite/gcc.dg/vect/vect-78.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-78.c,v
retrieving revision 1.11
diff -c -3 -p -r1.11 vect-78.c
*** testsuite/gcc.dg/vect/vect-78.c	31 Mar 2005 18:34:19 -0000	1.11
--- testsuite/gcc.dg/vect/vect-78.c	7 Jun 2005 12:20:44 -0000
*************** int main (void)
*** 40,46 ****
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
! /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
  /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */
--- 40,46 ----
    return 0;
  }
  
! /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align } } } } */
! /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { vect_no_align } } } } */
  /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
  /* { dg-final { cleanup-tree-dump "vect" } } */


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