Commit 7e2ac86c by Zdenek Dvorak Committed by Zdenek Dvorak

re PR middle-end/30322 (((-i-1) + i) +1) is turned into ~i + (i+1) and never…

re PR middle-end/30322 (((-i-1) + i) +1) is turned into ~i + (i+1) and never into 0 on the tree level)

	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.

	* gcc.dg/tree-ssa/loop-21.c: New test.

From-SVN: r120630
parent 92c25b55
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> 2007-01-09 Carlos O'Donell <carlos@codesourcery.com>
* doc/tm.texi: Update documentation to reflect reality of exec * 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> 2007-01-08 Geoffrey Keating <geoffk@apple.com>
* g++.dg/rtti/darwin-builtin-linkage.C: New. * g++.dg/rtti/darwin-builtin-linkage.C: New.
/* 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" } } */
...@@ -180,6 +180,14 @@ aff_combination_add_elt (aff_tree *comb, tree elt, double_int scale) ...@@ -180,6 +180,14 @@ aff_combination_add_elt (aff_tree *comb, tree elt, double_int scale)
comb->rest = elt; 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. */ /* Adds COMB2 to COMB1. */
void void
...@@ -187,9 +195,7 @@ aff_combination_add (aff_tree *comb1, aff_tree *comb2) ...@@ -187,9 +195,7 @@ aff_combination_add (aff_tree *comb1, aff_tree *comb2)
{ {
unsigned i; unsigned i;
comb1->offset aff_combination_add_cst (comb1, comb2->offset);
= double_int_ext_for_comb (double_int_add (comb1->offset, comb2->offset),
comb1);
for (i = 0; i < comb2->n; i++) for (i = 0; i < comb2->n; i++)
aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef); aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef);
if (comb2->rest) if (comb2->rest)
...@@ -204,7 +210,13 @@ aff_combination_convert (aff_tree *comb, tree type) ...@@ -204,7 +210,13 @@ aff_combination_convert (aff_tree *comb, tree type)
unsigned i, j; unsigned i, j;
tree comb_type = comb->type; 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; comb->type = type;
if (comb->rest) if (comb->rest)
comb->rest = fold_convert (type, comb->rest); comb->rest = fold_convert (type, comb->rest);
...@@ -276,6 +288,13 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb) ...@@ -276,6 +288,13 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
aff_combination_scale (comb, double_int_minus_one); aff_combination_scale (comb, double_int_minus_one);
return; 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: case ADDR_EXPR:
core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos, core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
&toffset, &mode, &unsignedp, &volatilep, &toffset, &mode, &unsignedp, &volatilep,
...@@ -412,3 +431,65 @@ aff_combination_remove_elt (aff_tree *comb, unsigned m) ...@@ -412,3 +431,65 @@ aff_combination_remove_elt (aff_tree *comb, unsigned m)
comb->n++; 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);
}
...@@ -62,6 +62,7 @@ double_int double_int_ext_for_comb (double_int, aff_tree *); ...@@ -62,6 +62,7 @@ double_int double_int_ext_for_comb (double_int, aff_tree *);
void aff_combination_const (aff_tree *, tree, double_int); void aff_combination_const (aff_tree *, tree, double_int);
void aff_combination_elt (aff_tree *, tree, tree); void aff_combination_elt (aff_tree *, tree, tree);
void aff_combination_scale (aff_tree *, double_int); 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 (aff_tree *, aff_tree *);
void aff_combination_add_elt (aff_tree *, tree, double_int); void aff_combination_add_elt (aff_tree *, tree, double_int);
void aff_combination_remove_elt (aff_tree *, unsigned); void aff_combination_remove_elt (aff_tree *, unsigned);
......
...@@ -2565,21 +2565,6 @@ constant_multiple_of (tree top, tree bot, double_int *mul) ...@@ -2565,21 +2565,6 @@ constant_multiple_of (tree top, tree bot, double_int *mul)
} }
} }
/* 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 /* 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 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 BA to A and BB to B, and returns the type of BA. Otherwise, returns the
...@@ -3557,32 +3542,26 @@ determine_use_iv_cost_address (struct ivopts_data *data, ...@@ -3557,32 +3542,26 @@ determine_use_iv_cost_address (struct ivopts_data *data,
return cost != INFTY; 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 static void
iv_value (struct iv *iv, tree niter) 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); tree type = TREE_TYPE (iv->base);
niter = fold_convert (type, niter); tree_to_aff_combination (iv->step, type, &step);
val = fold_build2 (MULT_EXPR, type, iv->step, niter); tree_to_aff_combination (niter, TREE_TYPE (niter), &nit);
aff_combination_convert (&nit, type);
return fold_build2 (PLUS_EXPR, type, iv->base, val); aff_combination_mult (&nit, &step, &delta);
}
/* 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);
if (stmt_after_increment (loop, cand, at)) 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. */ /* Returns period of induction variable iv. */
...@@ -3637,6 +3616,7 @@ may_eliminate_iv (struct ivopts_data *data, ...@@ -3637,6 +3616,7 @@ may_eliminate_iv (struct ivopts_data *data,
tree nit, nit_type; tree nit, nit_type;
tree wider_type, period, per_type; tree wider_type, period, per_type;
struct loop *loop = data->current_loop; struct loop *loop = data->current_loop;
aff_tree bnd;
if (TREE_CODE (cand->iv->step) != INTEGER_CST) if (TREE_CODE (cand->iv->step) != INTEGER_CST)
return false; return false;
...@@ -3681,7 +3661,8 @@ may_eliminate_iv (struct ivopts_data *data, ...@@ -3681,7 +3661,8 @@ may_eliminate_iv (struct ivopts_data *data,
fold_convert (wider_type, nit)))) fold_convert (wider_type, nit))))
return false; 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; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment