This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [lno] symbolic number of iterations
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: Olga Golovanevsky <OLGA at il dot ibm dot com>
- Cc: Sebastian Pop <sebastian dot pop at cri dot ensmp dot fr>,Devang Patel <dpatel at apple dot com>, Dorit Naishlos <DORIT at il dot ibm dot com>,GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Sun, 30 May 2004 11:33:41 +0200
- Subject: Re: [lno] symbolic number of iterations
- References: <20040524094803.GB1433@cri.ensmp.fr> <OFB7BEFF08.57A99D7B-ONC2256E9E.0047CD89-C2256E9E.004913EA@il.ibm.com>
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;