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]

Re: [lno] symbolic number of iterations


Hello,

> > I have replaced the code handling the computation of loop counts with
> > a call to number_of_iterations_cond.
> 
> Sebastian, I'm sorry if it sounded as if it's your patch responsible for
> the recent regression I have seen; this is not what I meant, just trying to
> track down which is the relevant change.
> 
> I believe it's actually the following patch that's causing the change of
> behavior:
> http://gcc.gnu.org/ml/gcc-patches/2004-05/msg01234.html
> 
> With this patch, number_of_iterations_in_loop returns 'chrec_top' for the
> loop bound in tree-ssa-vect-8.c;
> 
> When I disable the patch, I get the original (good!) behavior again - the
> loop bound returned is the following:
> '(<unnamed type>)(n_6 - 1) + 1'

it should work again, with this patch.

Zdenek

Index: ChangeLog.lno
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ChangeLog.lno,v
retrieving revision 1.1.2.170
diff -c -3 -p -r1.1.2.170 ChangeLog.lno
*** ChangeLog.lno	29 May 2004 22:09:02 -0000	1.1.2.170
--- ChangeLog.lno	30 May 2004 09:22:12 -0000
***************
*** 1,3 ****
--- 1,26 ----
+ 2004-05-30  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+ 
+ 	* fold-const.c (fold_widened_comparison,
+ 	fold_sign_changed_comparison): New.
+ 	(fold): Use them.
+ 	* tree-flow.h (struct tree_niter_desc): New field additional_info.
+ 	* tree-ssa-loop-niter.c (simplify_using_outer_evolutions): Do not
+ 	rewrite expressions in-place.
+ 	(tree_simplify_using_condition, simplify_using_initial_conditions):
+ 	New functions.
+ 	(number_of_iterations_exit): Use simplify_using_initial_conditions.
+ 	(struct nb_iter_bound): New field additional.
+ 	(record_estimate, estimate_numbers_of_iterations_loop): Initialize
+ 	field additional.
+ 	(upper_bound_in_type, lower_bound_in_type): Export.  Handle
+ 	unsigned->signed conversion correctly.
+ 	(can_count_iv_in_wider_type): Pass the additional info to
+ 	can_count_iv_in_wider_type_bound.
+ 	(can_count_iv_in_wider_type_bound): Use the additional info.
+ 	* trre.h (lower_bound_in_type, upper_bound_in_type): Declare.
+ 	* config/i386/i386.c (legitimate_constant_p): Do not allow
+ 	integer - symbol.
+ 
  2004-05-29  Sebastian Pop  <pop@cri.ensmp.fr>
  
  	* lambda-code.c: Spell check.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.213.2.65.2.6
diff -c -3 -p -r1.213.2.65.2.6 fold-const.c
*** fold-const.c	27 May 2004 14:32:41 -0000	1.213.2.65.2.6
--- fold-const.c	30 May 2004 09:22:12 -0000
*************** tree_swap_operands_p (tree arg0, tree ar
*** 5431,5436 ****
--- 5431,5557 ----
    return 0;
  }
  
+ /* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where
+    ARG0 is extended to a wider type.  */
+ 
+ static tree
+ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
+ {
+   tree arg0_unw = get_unwidened (arg0, NULL_TREE);
+   tree arg1_unw;
+   tree shorter_type, outer_type;
+   tree min, max;
+   bool above, below;
+ 
+   if (arg0_unw == arg0)
+     return NULL_TREE;
+   shorter_type = TREE_TYPE (arg0_unw);
+   
+   arg1_unw = get_unwidened (arg1, shorter_type);
+   if (!arg1_unw)
+     return NULL_TREE;
+ 
+   /* If possible, express the comparison in the shorter mode.  */
+   if ((code == EQ_EXPR || code == NE_EXPR
+        || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
+       && (TREE_TYPE (arg1_unw) == shorter_type
+ 	  || (TREE_CODE (arg1_unw) == INTEGER_CST
+ 	      && int_fits_type_p (arg1_unw, shorter_type))))
+     return fold (build (code, type, arg0_unw,
+ 			fold_convert (shorter_type, arg1_unw)));
+ 
+   if (TREE_CODE (arg1_unw) != INTEGER_CST)
+     return NULL_TREE;
+ 
+   /* If we are comparing with the integer that does not fit into the range
+      of the shorter type, the result is known.  */
+   outer_type = TREE_TYPE (arg1_unw);
+   min = lower_bound_in_type (outer_type, shorter_type);
+   max = upper_bound_in_type (outer_type, shorter_type);
+ 
+   above = integer_nonzerop (fold_relational_const (LT_EXPR, type,
+ 						   max, arg1_unw));
+   below = integer_nonzerop (fold_relational_const (LT_EXPR, type,
+ 						   arg1_unw, min));
+ 
+   switch (code)
+     {
+     case EQ_EXPR:
+       if (above || below)
+ 	return constant_boolean_node (false, type);
+       break;
+ 
+     case NE_EXPR:
+       if (above || below)
+ 	return constant_boolean_node (true, type);
+       break;
+ 
+     case LT_EXPR:
+     case LE_EXPR:
+       if (above)
+ 	return constant_boolean_node (true, type);
+       else if (below)
+ 	return constant_boolean_node (false, type);;
+ 
+     case GT_EXPR:
+     case GE_EXPR:
+       if (above)
+ 	return constant_boolean_node (false, type);
+       else if (below)
+ 	return constant_boolean_node (true, type);;
+ 
+     default:
+       break;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ /* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where for
+    ARG0 just the signedness is changed.  */
+ 
+ static tree
+ fold_sign_changed_comparison (enum tree_code code, tree type,
+ 			      tree arg0, tree arg1)
+ {
+   tree arg0_inner;
+   tree inner_type, outer_type;
+   int ovflw;
+ 
+   if (TREE_CODE (arg0) != NOP_EXPR)
+     return NULL_TREE;
+ 
+   outer_type = TREE_TYPE (arg0);
+   arg0_inner = TREE_OPERAND (arg0, 0);
+   inner_type = TREE_TYPE (arg0_inner);
+ 
+   if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
+     return NULL_TREE;
+ 
+   if (TREE_CODE (arg1) != INTEGER_CST
+       && !(TREE_CODE (arg1) == NOP_EXPR
+ 	   && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
+     return NULL_TREE;
+ 
+   if (TYPE_UNSIGNED (inner_type) == TYPE_UNSIGNED (outer_type))
+     {
+       /* Not much to do.  */
+       ovflw = TREE_OVERFLOW (arg1);
+       arg1 = fold_convert (inner_type, arg1);
+       TREE_OVERFLOW (arg1) = ovflw;
+       return fold (build (code, type, arg0_inner, arg1));
+     }
+ 
+   /* TODO -- we still might do something if we compare with the constant.  */
+   if (code != NE_EXPR && code != EQ_EXPR)
+     return NULL_TREE;
+ 
+   ovflw = TREE_OVERFLOW (arg1);
+   arg1 = fold_convert (inner_type, arg1);
+   TREE_OVERFLOW (arg1) = ovflw;
+   return fold (build (code, type, arg0_inner, arg1));
+ }
+ 
  /* Perform constant folding and related simplification of EXPR.
     The related simplifications include x*1 => x, x*0 => 0, etc.,
     and application of the associative law.
*************** fold (tree expr)
*** 7618,7638 ****
  	return fold (build2 (code, type,
  			     TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
  
-       /* If we are widening one operand of an integer comparison,
- 	 see if the other operand is similarly being widened.  Perhaps we
- 	 can do the comparison in the narrower type.  */
        else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
! 	       && TREE_CODE (arg0) == NOP_EXPR
! 	       && (tem = get_unwidened (arg0, NULL_TREE)) != arg0
! 	       && (code == EQ_EXPR || code == NE_EXPR
! 		   || TYPE_UNSIGNED (TREE_TYPE (arg0))
! 		      == TYPE_UNSIGNED (TREE_TYPE (tem)))
! 	       && (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
! 	       && (TREE_TYPE (t1) == TREE_TYPE (tem)
! 		   || (TREE_CODE (t1) == INTEGER_CST
! 		       && int_fits_type_p (t1, TREE_TYPE (tem)))))
! 	return fold (build2 (code, type, tem,
! 			     fold_convert (TREE_TYPE (tem), t1)));
  
        /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
  	 constant, we can simplify it.  */
--- 7739,7759 ----
  	return fold (build2 (code, type,
  			     TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
  
        else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
! 	       && TREE_CODE (arg0) == NOP_EXPR)
! 	{
! 	  /* If we are widening one operand of an integer comparison,
! 	     see if the other operand is similarly being widened.  Perhaps we
! 	     can do the comparison in the narrower type.  */
! 	  tem = fold_widened_comparison (code, type, arg0, arg1);
! 	  if (tem)
! 	    return tem;
! 
! 	  /* Or if we are changing signedness.  */
! 	  tem = fold_sign_changed_comparison (code, type, arg0, arg1);
! 	  if (tem)
! 	    return tem;
! 	}
  
        /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
  	 constant, we can simplify it.  */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 1.1.4.177.2.30
diff -c -3 -p -r1.1.4.177.2.30 tree-flow.h
*** tree-flow.h	27 May 2004 14:33:03 -0000	1.1.4.177.2.30
--- tree-flow.h	30 May 2004 09:22:12 -0000
*************** struct tree_niter_desc
*** 647,652 ****
--- 647,654 ----
    tree may_be_zero;	/* Condition under that the loop exits in the first
  			   iteration.  */
    tree niter;		/* Number of iterations.  */
+   tree additional_info;	/* Additional conditions taken into account when
+ 			   deriving the information above.  */
  };
  
  void number_of_iterations_cond (tree, tree, tree, enum tree_code, tree, tree,
Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop-niter.c,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 tree-ssa-loop-niter.c
*** tree-ssa-loop-niter.c	28 May 2004 20:39:58 -0000	1.1.2.3
--- tree-ssa-loop-niter.c	30 May 2004 09:22:12 -0000
*************** simplify_using_outer_evolutions (struct 
*** 435,441 ****
  {
    enum tree_code code = TREE_CODE (expr);
    bool changed;
!   tree e;
  
    if (is_gimple_min_invariant (expr))
      return expr;
--- 435,441 ----
  {
    enum tree_code code = TREE_CODE (expr);
    bool changed;
!   tree e, e0, e1, e2;
  
    if (is_gimple_min_invariant (expr))
      return expr;
*************** simplify_using_outer_evolutions (struct 
*** 446,471 ****
      {
        changed = false;
  
!       e = TREE_OPERAND (expr, 0);
!       TREE_OPERAND (expr, 0) = simplify_using_outer_evolutions (loop, e);
!       if (TREE_OPERAND (expr, 0) != e)
  	changed = true;
  
!       e = TREE_OPERAND (expr, 1);
!       TREE_OPERAND (expr, 1) = simplify_using_outer_evolutions (loop, e);
!       if (TREE_OPERAND (expr, 1) != e)
  	changed = true;
  
        if (code == COND_EXPR)
  	{
! 	  e = TREE_OPERAND (expr, 2);
! 	  TREE_OPERAND (expr, 2) = simplify_using_outer_evolutions (loop, e);
! 	  if (TREE_OPERAND (expr, 2) != e)
  	    changed = true;
  	}
  
        if (changed)
! 	expr = fold (expr);
  
        return expr;
      }
--- 446,476 ----
      {
        changed = false;
  
!       e0 = simplify_using_outer_evolutions (loop, TREE_OPERAND (expr, 0));
!       if (TREE_OPERAND (expr, 0) != e0)
  	changed = true;
  
!       e1 = simplify_using_outer_evolutions (loop, TREE_OPERAND (expr, 1));
!       if (TREE_OPERAND (expr, 1) != e1)
  	changed = true;
  
        if (code == COND_EXPR)
  	{
! 	  e2 = simplify_using_outer_evolutions (loop, TREE_OPERAND (expr, 2));
! 	  if (TREE_OPERAND (expr, 2) != e2)
  	    changed = true;
  	}
+       else
+ 	e2 = NULL_TREE;
  
        if (changed)
! 	{
! 	  if (code == COND_EXPR)
! 	    expr = build (code, boolean_type_node, e0, e1, e2);
! 	  else
! 	    expr = build (code, boolean_type_node, e0, e1);
! 	  expr = fold (expr);
! 	}
  
        return expr;
      }
*************** simplify_using_outer_evolutions (struct 
*** 477,482 ****
--- 482,592 ----
    return expr;
  }
  
+ /* Tries to simplify EXPR using the condition COND.  */
+ 
+ static tree
+ tree_simplify_using_condition (tree cond, tree expr)
+ {
+   bool changed;
+   tree e, e0, e1, e2, notcond;
+   enum tree_code code = TREE_CODE (expr);
+ 
+   if (code == INTEGER_CST)
+     return expr;
+ 
+   if (code == TRUTH_OR_EXPR
+       || code == TRUTH_AND_EXPR
+       || code == COND_EXPR)
+     {
+       changed = false;
+ 
+       e0 = tree_simplify_using_condition (cond, TREE_OPERAND (expr, 0));
+       if (TREE_OPERAND (expr, 0) != e0)
+ 	changed = true;
+ 
+       e1 = tree_simplify_using_condition (cond, TREE_OPERAND (expr, 1));
+       if (TREE_OPERAND (expr, 1) != e1)
+ 	changed = true;
+ 
+       if (code == COND_EXPR)
+ 	{
+ 	  e2 = tree_simplify_using_condition (cond, TREE_OPERAND (expr, 2));
+ 	  if (TREE_OPERAND (expr, 2) != e2)
+ 	    changed = true;
+ 	}
+       else
+ 	e2 = NULL_TREE;
+ 
+       if (changed)
+ 	{
+ 	  if (code == COND_EXPR)
+ 	    expr = build (code, boolean_type_node, e0, e1, e2);
+ 	  else
+ 	    expr = build (code, boolean_type_node, e0, e1);
+ 	  expr = fold (expr);
+ 	}
+ 
+       return expr;
+     }
+ 
+   /* Check whether COND ==> EXPR.  */
+   notcond = invert_truthvalue (cond);
+   e = fold (build (TRUTH_OR_EXPR, boolean_type_node,
+ 		   notcond, expr));
+   if (integer_nonzerop (e))
+     return e;
+ 
+   /* Check whether COND ==> not EXPR.  */
+   e = fold (build (TRUTH_AND_EXPR, boolean_type_node,
+ 		   cond, expr));
+   if (integer_zerop (e))
+     return e;
+ 
+   return expr;
+ }
+ 
+ /* Tries to simplify EXPR using the conditions on entry to LOOP.
+    Record the conditions used to CONDS_USED.  */
+ 
+ static tree
+ simplify_using_initial_conditions (struct loop *loop, tree expr,
+ 				   tree *conds_used)
+ {
+   edge e;
+   basic_block bb;
+   tree exp, cond;
+ 
+   if (TREE_CODE (expr) == INTEGER_CST)
+     return expr;
+ 
+   for (bb = loop->header;
+        bb != ENTRY_BLOCK_PTR;
+        bb = get_immediate_dominator (CDI_DOMINATORS, bb))
+     {
+       e = bb->pred;
+       if (e->pred_next)
+ 	continue;
+ 
+       if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
+ 	continue;
+ 
+       cond = COND_EXPR_COND (last_stmt (e->src));
+       if (e->flags & EDGE_FALSE_VALUE)
+ 	cond = invert_truthvalue (cond);
+       exp = tree_simplify_using_condition (cond, expr);
+ 
+       if (exp != expr)
+ 	*conds_used = fold (build (TRUTH_AND_EXPR,
+ 				   boolean_type_node,
+ 				   *conds_used,
+ 				   cond));
+ 
+       expr = exp;
+     }
+ 
+   return expr;
+ }
+ 
  /* Stores description of number of iterations of LOOP derived from EXIT
     in NITER.  */
  
*************** number_of_iterations_exit (struct loop *
*** 540,545 ****
--- 650,665 ----
    niter->may_be_zero = simplify_using_outer_evolutions (loop,
  							niter->may_be_zero);
    niter->niter = simplify_using_outer_evolutions (loop, niter->niter);
+ 
+   niter->additional_info = boolean_true_node;
+   niter->assumptions
+ 	  = simplify_using_initial_conditions (loop,
+ 					       niter->assumptions,
+ 					       &niter->additional_info);
+   niter->may_be_zero
+ 	  = simplify_using_initial_conditions (loop,
+ 					       niter->may_be_zero,
+ 					       &niter->additional_info);
    return integer_onep (niter->assumptions);
  }
  
*************** struct nb_iter_bound
*** 787,800 ****
    tree bound;		/* The bound on the number of executions of anything
  			   after ...  */
    tree at_stmt;		/* ... this statement during one execution of loop.  */
    struct nb_iter_bound *next;
  			/* The next bound in a list.  */
  };
  
! /* Records that AT_STMT is executed at most BOUND times in LOOP.  */
  
  static void
! record_estimate (struct loop *loop, tree bound, tree at_stmt)
  {
    struct nb_iter_bound *elt = xmalloc (sizeof (struct nb_iter_bound));
  
--- 907,922 ----
    tree bound;		/* The bound on the number of executions of anything
  			   after ...  */
    tree at_stmt;		/* ... this statement during one execution of loop.  */
+   tree additional;	/* Additional information about the bound.  */
    struct nb_iter_bound *next;
  			/* The next bound in a list.  */
  };
  
! /* Records that AT_STMT is executed at most BOUND times in LOOP.  The
!    additional condition ADDITIONAL is recorded as well.  */
  
  static void
! record_estimate (struct loop *loop, tree bound, tree additional, tree at_stmt)
  {
    struct nb_iter_bound *elt = xmalloc (sizeof (struct nb_iter_bound));
  
*************** record_estimate (struct loop *loop, tree
*** 809,814 ****
--- 931,937 ----
  
    elt->bound = bound;
    elt->at_stmt = at_stmt;
+   elt->additional = additional;
    elt->next = loop->bounds;
    loop->bounds = elt;
  }
*************** estimate_numbers_of_iterations_loop (str
*** 830,836 ****
        type = TREE_TYPE (niter);
        niter = fold (build (MINUS_EXPR, type, niter,
  			   convert (type, integer_one_node)));
!       record_estimate (loop, niter, last_stmt (loop_exit_edge (loop, 0)->src));
      }
  
    /* Now use number_of_iterations_exit.  */
--- 953,960 ----
        type = TREE_TYPE (niter);
        niter = fold (build (MINUS_EXPR, type, niter,
  			   convert (type, integer_one_node)));
!       record_estimate (loop, niter, boolean_true_node,
! 		       last_stmt (loop_exit_edge (loop, 0)->src));
      }
  
    /* Now use number_of_iterations_exit.  */
*************** estimate_numbers_of_iterations_loop (str
*** 847,853 ****
  	niter = build (COND_EXPR, type, niter_desc.may_be_zero,
  		       convert (type, integer_zero_node),
  		       niter);
!       record_estimate (loop, niter, last_stmt (exits[i]->src));
      }
    free (exits);
    
--- 971,979 ----
  	niter = build (COND_EXPR, type, niter_desc.may_be_zero,
  		       convert (type, integer_zero_node),
  		       niter);
!       record_estimate (loop, niter,
! 		       niter_desc.additional_info,
! 		       last_stmt (exits[i]->src));
      }
    free (exits);
    
*************** compare_trees (tree a, tree b)
*** 901,914 ****
  /* Returns the largest value obtainable by casting something in INNER type to
     OUTER type.  */
  
! static tree
  upper_bound_in_type (tree outer, tree inner)
  {
    unsigned HOST_WIDE_INT lo, hi;
    unsigned bits = TYPE_PRECISION (inner);
  
!   if (TYPE_UNSIGNED (outer))
      {
        if (bits <= HOST_BITS_PER_WIDE_INT)
  	{
  	  hi = 0;
--- 1027,1041 ----
  /* Returns the largest value obtainable by casting something in INNER type to
     OUTER type.  */
  
! tree
  upper_bound_in_type (tree outer, tree inner)
  {
    unsigned HOST_WIDE_INT lo, hi;
    unsigned bits = TYPE_PRECISION (inner);
  
!   if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
      {
+       /* Zero extending in these cases.  */
        if (bits <= HOST_BITS_PER_WIDE_INT)
  	{
  	  hi = 0;
*************** upper_bound_in_type (tree outer, tree in
*** 924,929 ****
--- 1051,1057 ----
      }
    else
      {
+       /* Sign extending in these cases.  */
        if (bits <= HOST_BITS_PER_WIDE_INT)
  	{
  	  hi = 0;
*************** upper_bound_in_type (tree outer, tree in
*** 946,958 ****
  /* Returns the smallest value obtainable by casting something in INNER type to
     OUTER type.  */
  
! static tree
  lower_bound_in_type (tree outer, tree inner)
  {
    unsigned HOST_WIDE_INT lo, hi;
    unsigned bits = TYPE_PRECISION (inner);
  
!   if (TYPE_UNSIGNED (outer))
      lo = hi = 0;
    else if (bits <= HOST_BITS_PER_WIDE_INT)
      {
--- 1074,1086 ----
  /* Returns the smallest value obtainable by casting something in INNER type to
     OUTER type.  */
  
! tree
  lower_bound_in_type (tree outer, tree inner)
  {
    unsigned HOST_WIDE_INT lo, hi;
    unsigned bits = TYPE_PRECISION (inner);
  
!   if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
      lo = hi = 0;
    else if (bits <= HOST_BITS_PER_WIDE_INT)
      {
*************** stmt_dominates_stmt_p (tree s1, tree s2)
*** 998,1012 ****
  /* 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 in
!    the TYPE, otherwise return NULL_TREE.  */
  
  static tree
  can_count_iv_in_wider_type_bound (tree type, tree base, tree step,
  				  tree at_stmt,
! 				  tree bound, tree of)
  {
    tree inner_type = TREE_TYPE (base), b, bplusstep, new_step, new_step_abs;
    tree valid_niter, extreme, unsigned_type, delta, bound_type;
  
    b = convert (type, base);
    bplusstep = convert (type,
--- 1126,1158 ----
  /* 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 in
!    the TYPE, otherwise return NULL_TREE.
!    
!    ADDITIONAL is the additional information recorded for bound.  This is useful
!    in the following case, created by loop header copying:
! 
!    i = 0;
!    if (n > 0)
!      do
!        {
!          something;
!        } while (++i < n)
! 
!    If the n > 0 condition is taken into account, the number of iterations of the
!    loop can be expressed as n - 1.  If the type of n is signed, the ADDITIONAL
!    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 = convert (type, base);
    bplusstep = convert (type,
*************** can_count_iv_in_wider_type_bound (tree t
*** 1052,1070 ****
      {
        /* After the statement OF we know that anything is executed at most
  	 BOUND times.  */
!       if (integer_nonzerop (fold (build (GE_EXPR, boolean_type_node,
! 					 valid_niter, bound))))
! 	return new_step;
      }
    else
      {
        /* Before the statement OF we know that anything is executed at most
  	 BOUND + 1 times.  */
!       if (integer_nonzerop (fold (build (GT_EXPR, boolean_type_node,
! 					 valid_niter, bound))))
! 	return new_step;
      }
  
    return NULL_TREE;
  }
  
--- 1198,1224 ----
      {
        /* After the statement OF we know that anything is executed at most
  	 BOUND times.  */
!       cond = build (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 = build (GT_EXPR, boolean_type_node, valid_niter, bound);
      }
  
+   cond = fold (cond);
+   if (integer_nonzerop (cond))
+     return new_step;
+ 
+   /* Try taking additional conditions into account.  */
+   cond = build (TRUTH_OR_EXPR, boolean_type_node,
+ 		invert_truthvalue (additional),
+ 		cond);
+   cond = fold (cond);
+   if (integer_nonzerop (cond))
+     return new_step;
+ 
    return NULL_TREE;
  }
  
*************** can_count_iv_in_wider_type (struct loop 
*** 1085,1090 ****
--- 1239,1245 ----
        new_step = can_count_iv_in_wider_type_bound (type, base, step,
  						   at_stmt,
  						   bound->bound,
+ 						   bound->additional,
  						   bound->at_stmt);
  
        if (new_step)
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.154.2.14
diff -c -3 -p -r1.342.2.154.2.14 tree.h
*** tree.h	27 May 2004 14:33:11 -0000	1.342.2.154.2.14
--- tree.h	30 May 2004 09:22:12 -0000
*************** extern int tree_node_sizes[];
*** 3817,3821 ****
     be restricted.  False if we are not in gimple form and folding is not
     restricted to creating gimple expressions.  */
  extern bool in_gimple_form;
!     
  #endif  /* GCC_TREE_H  */
--- 3817,3826 ----
     be restricted.  False if we are not in gimple form and folding is not
     restricted to creating gimple expressions.  */
  extern bool in_gimple_form;
! 
! /* In tree-ssa-loop-niter.c.  */
! 
! tree lower_bound_in_type (tree, tree);
! tree upper_bound_in_type (tree, tree);
! 
  #endif  /* GCC_TREE_H  */
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.425.2.39.2.5
diff -c -3 -p -r1.425.2.39.2.5 i386.c
*** config/i386/i386.c	27 May 2004 14:35:09 -0000	1.425.2.39.2.5
--- config/i386/i386.c	30 May 2004 09:22:13 -0000
*************** legitimate_constant_p (rtx x)
*** 5823,5829 ****
  	  && tls_symbolic_operand (XEXP (inner, 0), Pmode))
  	return false;
  
!       if (GET_CODE (inner) == PLUS)
  	{
  	  if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
  	    return false;
--- 5823,5830 ----
  	  && tls_symbolic_operand (XEXP (inner, 0), Pmode))
  	return false;
  
!       if (GET_CODE (inner) == PLUS
! 	  || GET_CODE (inner) == MINUS)
  	{
  	  if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
  	    return false;


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