Commit b697aed4 by Zdenek Dvorak Committed by Zdenek Dvorak

tree-ssa-loop-ivopts.c (extract_cond_operands): Split from find_interesting_uses_cond.

	* tree-ssa-loop-ivopts.c (extract_cond_operands): Split from
	find_interesting_uses_cond.
	(find_interesting_uses_cond): Use extract_cond_operands.
	(rewrite_use_compare): Use extract_cond_operands and
	force_gimple_operand_bsi.  Do not call update_stmt.
	(determine_use_iv_cost_condition): Use extract_cond_operands.
	Return cheaper of using original bound and changing the exit bound.

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

From-SVN: r120697
parent 662c02b3
2007-01-11 Zdenek Dvorak <dvorakz@suse.cz> 2007-01-11 Zdenek Dvorak <dvorakz@suse.cz>
* tree-ssa-loop-ivopts.c (extract_cond_operands): Split from
find_interesting_uses_cond.
(find_interesting_uses_cond): Use extract_cond_operands.
(rewrite_use_compare): Use extract_cond_operands and
force_gimple_operand_bsi. Do not call update_stmt.
(determine_use_iv_cost_condition): Use extract_cond_operands.
Return cheaper of using original bound and changing the exit bound.
2007-01-11 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/29516 PR tree-optimization/29516
* tree-ssa-address.c (tree_mem_ref_addr, add_to_parts, * tree-ssa-address.c (tree_mem_ref_addr, add_to_parts,
most_expensive_mult_to_index, addr_to_parts, most_expensive_mult_to_index, addr_to_parts,
......
2007-01-11 Zdenek Dvorak <dvorakz@suse.cz> 2007-01-11 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/loop-22.c: New test.
2007-01-11 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/29516 PR tree-optimization/29516
* gcc.dg/tree-ssa/loop-20.c: New test. * gcc.dg/tree-ssa/loop-20.c: New test.
/* { dg-options "-O2 -fdump-tree-final_cleanup" } */
int a[100];
void test (int n)
{
int i;
for (i = 0; i < n; i += 3)
a[i] = i;
}
/* We used to replace the exit test "i < n" by "i != ((n-1)/3) * 3 + 1". Although
correct, this transformation is obviously harmful. */
/* { dg-final { scan-tree-dump-times "/" 0 "final_cleanup" } } */
/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
...@@ -1183,67 +1183,96 @@ find_interesting_uses_op (struct ivopts_data *data, tree op) ...@@ -1183,67 +1183,96 @@ find_interesting_uses_op (struct ivopts_data *data, tree op)
return use; return use;
} }
/* Checks whether the condition *COND_P in STMT is interesting /* Given a condition *COND_P, checks whether it is a compare of an induction
and if so, records it. */ variable and an invariant. If this is the case, CONTROL_VAR is set
to location of the iv, BOUND to the location of the invariant,
static void IV_VAR and IV_BOUND are set to the corresponding induction variable
find_interesting_uses_cond (struct ivopts_data *data, tree stmt, tree *cond_p) descriptions, and true is returned. If this is not the case,
{ CONTROL_VAR and BOUND are set to the arguments of the condition and
tree *op0_p; false is returned. */
tree *op1_p;
struct iv *iv0 = NULL, *iv1 = NULL, *civ;
struct iv const_iv;
tree zero = integer_zero_node;
static bool
extract_cond_operands (struct ivopts_data *data, tree *cond_p,
tree **control_var, tree **bound,
struct iv **iv_var, struct iv **iv_bound)
{
/* The nodes returned when COND has just one operand. Note that you should
not modify anything in BOUND or IV_BOUND because of this. */
static struct iv const_iv;
static tree zero;
tree cond = *cond_p;
tree *op0 = &zero, *op1 = &zero, *tmp_op;
struct iv *iv0 = &const_iv, *iv1 = &const_iv, *tmp_iv;
bool ret = false;
zero = integer_zero_node;
const_iv.step = integer_zero_node; const_iv.step = integer_zero_node;
if (TREE_CODE (*cond_p) != SSA_NAME if (TREE_CODE (cond) == SSA_NAME)
&& !COMPARISON_CLASS_P (*cond_p))
return;
if (TREE_CODE (*cond_p) == SSA_NAME)
{ {
op0_p = cond_p; op0 = cond_p;
op1_p = &zero; iv0 = get_iv (data, cond);
ret = (iv0 && !integer_zerop (iv0->step));
goto end;
} }
else
if (!COMPARISON_CLASS_P (cond))
{ {
op0_p = &TREE_OPERAND (*cond_p, 0); op0 = cond_p;
op1_p = &TREE_OPERAND (*cond_p, 1); goto end;
} }
if (TREE_CODE (*op0_p) == SSA_NAME) op0 = &TREE_OPERAND (cond, 0);
iv0 = get_iv (data, *op0_p); op1 = &TREE_OPERAND (cond, 1);
else if (TREE_CODE (*op0) == SSA_NAME)
iv0 = &const_iv; iv0 = get_iv (data, *op0);
if (TREE_CODE (*op1) == SSA_NAME)
iv1 = get_iv (data, *op1);
if (TREE_CODE (*op1_p) == SSA_NAME) /* Exactly one of the compared values must be an iv, and the other one must
iv1 = get_iv (data, *op1_p); be an invariant. */
else if (!iv0 || !iv1)
iv1 = &const_iv; goto end;
if (/* When comparing with non-invariant value, we may not do any senseful if (integer_zerop (iv0->step))
induction variable elimination. */ {
(!iv0 || !iv1) /* Control variable may be on the other side. */
/* Eliminating condition based on two ivs would be nontrivial. tmp_op = op0; op0 = op1; op1 = tmp_op;
??? TODO -- it is not really important to handle this case. */ tmp_iv = iv0; iv0 = iv1; iv1 = tmp_iv;
|| (!integer_zerop (iv0->step)
&& !integer_zerop (iv1->step)))
{
find_interesting_uses_op (data, *op0_p);
find_interesting_uses_op (data, *op1_p);
return;
} }
ret = !integer_zerop (iv0->step) && integer_zerop (iv1->step);
end:
if (control_var)
*control_var = op0;;
if (iv_var)
*iv_var = iv0;;
if (bound)
*bound = op1;
if (iv_bound)
*iv_bound = iv1;
return ret;
}
/* Checks whether the condition *COND_P in STMT is interesting
and if so, records it. */
static void
find_interesting_uses_cond (struct ivopts_data *data, tree stmt, tree *cond_p)
{
tree *var_p, *bound_p;
struct iv *var_iv, *civ;
if (integer_zerop (iv0->step) if (!extract_cond_operands (data, cond_p, &var_p, &bound_p, &var_iv, NULL))
&& integer_zerop (iv1->step))
{ {
/* If both are invariants, this is a work for unswitching. */ find_interesting_uses_op (data, *var_p);
find_interesting_uses_op (data, *bound_p);
return; return;
} }
civ = XNEW (struct iv); civ = XNEW (struct iv);
*civ = integer_zerop (iv0->step) ? *iv1: *iv0; *civ = *var_iv;
record_use (data, cond_p, civ, stmt, USE_COMPARE); record_use (data, cond_p, civ, stmt, USE_COMPARE);
} }
...@@ -3672,9 +3701,11 @@ static bool ...@@ -3672,9 +3701,11 @@ static bool
determine_use_iv_cost_condition (struct ivopts_data *data, determine_use_iv_cost_condition (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand) struct iv_use *use, struct iv_cand *cand)
{ {
tree bound = NULL_TREE, op, cond; tree bound = NULL_TREE;
bitmap depends_on = NULL; struct iv *cmp_iv;
unsigned cost; bitmap depends_on_elim = NULL, depends_on_express = NULL, depends_on;
unsigned elim_cost, express_cost, cost;
bool ok;
/* Only consider real candidates. */ /* Only consider real candidates. */
if (!cand->iv) if (!cand->iv)
...@@ -3683,35 +3714,44 @@ determine_use_iv_cost_condition (struct ivopts_data *data, ...@@ -3683,35 +3714,44 @@ determine_use_iv_cost_condition (struct ivopts_data *data,
return false; return false;
} }
/* Try iv elimination. */
if (may_eliminate_iv (data, use, cand, &bound)) if (may_eliminate_iv (data, use, cand, &bound))
{ elim_cost = force_var_cost (data, bound, &depends_on_elim);
cost = force_var_cost (data, bound, &depends_on); else
elim_cost = INFTY;
set_use_iv_cost (data, use, cand, cost, depends_on, bound); /* Try expressing the original giv. If it is compared with an invariant,
return cost != INFTY; note that we cannot get rid of it. */
} ok = extract_cond_operands (data, use->op_p, NULL, NULL, NULL, &cmp_iv);
gcc_assert (ok);
/* The induction variable elimination failed; just express the original express_cost = get_computation_cost (data, use, cand, false,
giv. If it is compared with an invariant, note that we cannot get &depends_on_express);
rid of it. */ fd_ivopts_data = data;
cost = get_computation_cost (data, use, cand, false, &depends_on); walk_tree (&cmp_iv->base, find_depends, &depends_on_express, NULL);
cond = *use->op_p; /* Choose the better approach. */
if (TREE_CODE (cond) != SSA_NAME) if (elim_cost < express_cost)
{ {
op = TREE_OPERAND (cond, 0); cost = elim_cost;
if (TREE_CODE (op) == SSA_NAME depends_on = depends_on_elim;
&& !integer_zerop (get_iv (data, op)->step)) depends_on_elim = NULL;
op = TREE_OPERAND (cond, 1); }
if (TREE_CODE (op) == SSA_NAME) else
{ {
op = get_iv (data, op)->base; cost = express_cost;
fd_ivopts_data = data; depends_on = depends_on_express;
walk_tree (&op, find_depends, &depends_on, NULL); depends_on_express = NULL;
} bound = NULL_TREE;
} }
set_use_iv_cost (data, use, cand, cost, depends_on, NULL); set_use_iv_cost (data, use, cand, cost, depends_on, bound);
if (depends_on_elim)
BITMAP_FREE (depends_on_elim);
if (depends_on_express)
BITMAP_FREE (depends_on_express);
return cost != INFTY; return cost != INFTY;
} }
...@@ -5087,12 +5127,12 @@ static void ...@@ -5087,12 +5127,12 @@ static void
rewrite_use_compare (struct ivopts_data *data, rewrite_use_compare (struct ivopts_data *data,
struct iv_use *use, struct iv_cand *cand) struct iv_use *use, struct iv_cand *cand)
{ {
tree comp; tree comp, *var_p, op, bound;
tree *op_p, cond, op, stmts, bound;
block_stmt_iterator bsi = bsi_for_stmt (use->stmt); block_stmt_iterator bsi = bsi_for_stmt (use->stmt);
enum tree_code compare; enum tree_code compare;
struct cost_pair *cp = get_use_iv_cost (data, use, cand); struct cost_pair *cp = get_use_iv_cost (data, use, cand);
bool ok;
bound = cp->value; bound = cp->value;
if (bound) if (bound)
{ {
...@@ -5100,15 +5140,10 @@ rewrite_use_compare (struct ivopts_data *data, ...@@ -5100,15 +5140,10 @@ rewrite_use_compare (struct ivopts_data *data,
tree var_type = TREE_TYPE (var); tree var_type = TREE_TYPE (var);
compare = iv_elimination_compare (data, use); compare = iv_elimination_compare (data, use);
bound = fold_convert (var_type, bound); bound = unshare_expr (fold_convert (var_type, bound));
op = force_gimple_operand (unshare_expr (bound), &stmts, op = force_gimple_operand_bsi (&bsi, bound, true, NULL_TREE);
true, NULL_TREE);
if (stmts)
bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
*use->op_p = build2 (compare, boolean_type_node, var, op); *use->op_p = build2 (compare, boolean_type_node, var, op);
update_stmt (use->stmt);
return; return;
} }
...@@ -5117,17 +5152,10 @@ rewrite_use_compare (struct ivopts_data *data, ...@@ -5117,17 +5152,10 @@ rewrite_use_compare (struct ivopts_data *data,
comp = get_computation (data->current_loop, use, cand); comp = get_computation (data->current_loop, use, cand);
gcc_assert (comp != NULL_TREE); gcc_assert (comp != NULL_TREE);
cond = *use->op_p; ok = extract_cond_operands (data, use->op_p, &var_p, NULL, NULL, NULL);
op_p = &TREE_OPERAND (cond, 0); gcc_assert (ok);
if (TREE_CODE (*op_p) != SSA_NAME
|| integer_zerop (get_iv (data, *op_p)->step))
op_p = &TREE_OPERAND (cond, 1);
op = force_gimple_operand (comp, &stmts, true, SSA_NAME_VAR (*op_p));
if (stmts)
bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
*op_p = op; *var_p = force_gimple_operand_bsi (&bsi, comp, true, SSA_NAME_VAR (*var_p));
} }
/* Rewrites USE using candidate CAND. */ /* Rewrites USE using candidate CAND. */
......
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