+2007-01-09 Zdenek Dvorak <dvorakz@suse.cz>
+
+ PR tree-optimization/30322
+ * tree-ssa-loop-ivopts.c (fold_affine_expr, iv_value): Removed.
+ (cand_value_at): Return the value as aff_tree.
+ (may_eliminate_iv): Convert the bound from aff_tree to tree.
+ * tree-affine.c (aff_combination_add_cst, aff_combination_add_product,
+ aff_combination_mult): New functions.
+ (aff_combination_add): Use aff_combination_add_cst.
+ (aff_combination_convert): Allow conversions to a wider type.
+ (tree_to_aff_combination): Handle BIT_NOT_EXPR.
+ * tree-affine.h (aff_combination_mult): Declare.
+
2007-01-09 Carlos O'Donell <carlos@codesourcery.com>
* doc/tm.texi: Update documentation to reflect reality of exec
+2007-01-09 Zdenek Dvorak <dvorakz@suse.cz>
+
+ PR tree-optimization/30322
+ * gcc.dg/tree-ssa/loop-21.c: New test.
+
2007-01-08 Geoffrey Keating <geoffk@apple.com>
* g++.dg/rtti/darwin-builtin-linkage.C: New.
--- /dev/null
+/* PR tree-optimization/30322 */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-final_cleanup" } */
+
+extern void op( int, int);
+void foo(int f0, int f1, int e0, int e1)
+{
+ int i0, i1;
+
+ for (i1 = f1; i1 <= e1; ++i1)
+ for (i0 = f0; i0 <= e0; ++i0)
+ op(i0, i1);
+}
+
+/* { dg-final { scan-tree-dump-times "~" 0 "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
comb->rest = elt;
}
+/* Adds CST to C. */
+
+static void
+aff_combination_add_cst (aff_tree *c, double_int cst)
+{
+ c->offset = double_int_ext_for_comb (double_int_add (c->offset, cst), c);
+}
+
/* Adds COMB2 to COMB1. */
void
{
unsigned i;
- comb1->offset
- = double_int_ext_for_comb (double_int_add (comb1->offset, comb2->offset),
- comb1);
+ aff_combination_add_cst (comb1, comb2->offset);
for (i = 0; i < comb2->n; i++)
aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef);
if (comb2->rest)
unsigned i, j;
tree comb_type = comb->type;
- gcc_assert (TYPE_PRECISION (type) <= TYPE_PRECISION (comb_type));
+ if (TYPE_PRECISION (type) > TYPE_PRECISION (comb_type))
+ {
+ tree val = fold_convert (type, aff_combination_to_tree (comb));
+ tree_to_aff_combination (val, type, comb);
+ return;
+ }
+
comb->type = type;
if (comb->rest)
comb->rest = fold_convert (type, comb->rest);
aff_combination_scale (comb, double_int_minus_one);
return;
+ case BIT_NOT_EXPR:
+ /* ~x = -x - 1 */
+ tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+ aff_combination_scale (comb, double_int_minus_one);
+ aff_combination_add_cst (comb, double_int_minus_one);
+ return;
+
case ADDR_EXPR:
core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
&toffset, &mode, &unsignedp, &volatilep,
comb->n++;
}
}
+
+/* Adds C * COEF * VAL to R. VAL may be NULL, in that case only
+ C * COEF is added to R. */
+
+
+static void
+aff_combination_add_product (aff_tree *c, double_int coef, tree val,
+ aff_tree *r)
+{
+ unsigned i;
+ tree aval, type;
+
+ for (i = 0; i < c->n; i++)
+ {
+ aval = c->elts[i].val;
+ if (val)
+ {
+ type = TREE_TYPE (aval);
+ aval = fold_build2 (MULT_EXPR, type, aval,
+ fold_convert (type, val));
+ }
+
+ aff_combination_add_elt (r, aval,
+ double_int_mul (coef, c->elts[i].coef));
+ }
+
+ if (c->rest)
+ {
+ aval = c->rest;
+ if (val)
+ {
+ type = TREE_TYPE (aval);
+ aval = fold_build2 (MULT_EXPR, type, aval,
+ fold_convert (type, val));
+ }
+
+ aff_combination_add_elt (r, aval, coef);
+ }
+
+ if (val)
+ aff_combination_add_elt (r, val,
+ double_int_mul (coef, c->offset));
+ else
+ aff_combination_add_cst (r, double_int_mul (coef, c->offset));
+}
+
+/* Multiplies C1 by C2, storing the result to R */
+
+void
+aff_combination_mult (aff_tree *c1, aff_tree *c2, aff_tree *r)
+{
+ unsigned i;
+ gcc_assert (TYPE_PRECISION (c1->type) == TYPE_PRECISION (c2->type));
+
+ aff_combination_zero (r, c1->type);
+
+ for (i = 0; i < c2->n; i++)
+ aff_combination_add_product (c1, c2->elts[i].coef, c2->elts[i].val, r);
+ if (c2->rest)
+ aff_combination_add_product (c1, double_int_one, c2->rest, r);
+ aff_combination_add_product (c1, c2->offset, NULL, r);
+}
void aff_combination_const (aff_tree *, tree, double_int);
void aff_combination_elt (aff_tree *, tree, tree);
void aff_combination_scale (aff_tree *, double_int);
+void aff_combination_mult (aff_tree *, aff_tree *, aff_tree *);
void aff_combination_add (aff_tree *, aff_tree *);
void aff_combination_add_elt (aff_tree *, tree, double_int);
void aff_combination_remove_elt (aff_tree *, unsigned);
}
}
-/* Folds EXPR using the affine expressions framework. */
-
-static tree
-fold_affine_expr (tree expr)
-{
- tree type = TREE_TYPE (expr);
- struct affine_tree_combination comb;
-
- if (TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT)
- return expr;
-
- tree_to_aff_combination (expr, type, &comb);
- return aff_combination_to_tree (&comb);
-}
-
/* If A is (TYPE) BA and B is (TYPE) BB, and the types of BA and BB have the
same precision that is at least as wide as the precision of TYPE, stores
BA to A and BB to B, and returns the type of BA. Otherwise, returns the
return cost != INFTY;
}
-/* Computes value of induction variable IV in iteration NITER. */
+/* Computes value of candidate CAND at position AT in iteration NITER, and
+ stores it to VAL. */
-static tree
-iv_value (struct iv *iv, tree niter)
+static void
+cand_value_at (struct loop *loop, struct iv_cand *cand, tree at, tree niter,
+ aff_tree *val)
{
- tree val;
+ aff_tree step, delta, nit;
+ struct iv *iv = cand->iv;
tree type = TREE_TYPE (iv->base);
- niter = fold_convert (type, niter);
- val = fold_build2 (MULT_EXPR, type, iv->step, niter);
-
- return fold_build2 (PLUS_EXPR, type, iv->base, val);
-}
-
-/* Computes value of candidate CAND at position AT in iteration NITER. */
-
-static tree
-cand_value_at (struct loop *loop, struct iv_cand *cand, tree at, tree niter)
-{
- tree val = iv_value (cand->iv, niter);
- tree type = TREE_TYPE (cand->iv->base);
-
+ tree_to_aff_combination (iv->step, type, &step);
+ tree_to_aff_combination (niter, TREE_TYPE (niter), &nit);
+ aff_combination_convert (&nit, type);
+ aff_combination_mult (&nit, &step, &delta);
if (stmt_after_increment (loop, cand, at))
- val = fold_build2 (PLUS_EXPR, type, val, cand->iv->step);
+ aff_combination_add (&delta, &step);
- return val;
+ tree_to_aff_combination (iv->base, type, val);
+ aff_combination_add (val, &delta);
}
/* Returns period of induction variable iv. */
tree nit, nit_type;
tree wider_type, period, per_type;
struct loop *loop = data->current_loop;
+ aff_tree bnd;
if (TREE_CODE (cand->iv->step) != INTEGER_CST)
return false;
fold_convert (wider_type, nit))))
return false;
- *bound = fold_affine_expr (cand_value_at (loop, cand, use->stmt, nit));
+ cand_value_at (loop, cand, use->stmt, nit, &bnd);
+ *bound = aff_combination_to_tree (&bnd);
return true;
}