Commit 3ac01fde by Zdenek Dvorak Committed by Zdenek Dvorak

re PR tree-optimization/22325 (missed optimization in loop)

	PR tree-optimization/22325
	* tree-flow.h (compute_phi_arg_on_exit, force_expr_to_var_cost):
	Declare.
	* tree-scalar-evolution.c (scev_const_prop): Add generic final
	value replacement.
	* tree-ssa-loop-ivopts.c (force_expr_to_var_cost): Split from ...
	(force_var_cost): ... this function.
	(compute_phi_arg_on_exit): Export.

From-SVN: r102426
parent 77fcaf4b
2005-07-27 Zdenek Dvorak <dvorakz@suse.cz> 2005-07-27 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/22325
* tree-flow.h (compute_phi_arg_on_exit, force_expr_to_var_cost):
Declare.
* tree-scalar-evolution.c (scev_const_prop): Add generic final
value replacement.
* tree-ssa-loop-ivopts.c (force_expr_to_var_cost): Split from ...
(force_var_cost): ... this function.
(compute_phi_arg_on_exit): Export.
2005-07-27 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/20773 PR tree-optimization/20773
* tree-ssa-loop-ch.c (copy_loop_headers): Select the correct latch * tree-ssa-loop-ch.c (copy_loop_headers): Select the correct latch
edge. edge.
......
...@@ -738,6 +738,8 @@ bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *); ...@@ -738,6 +738,8 @@ bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
void create_iv (tree, tree, tree, struct loop *, block_stmt_iterator *, bool, void create_iv (tree, tree, tree, struct loop *, block_stmt_iterator *, bool,
tree *, tree *); tree *, tree *);
void split_loop_exit_edge (edge); void split_loop_exit_edge (edge);
void compute_phi_arg_on_exit (edge, tree, tree);
unsigned force_expr_to_var_cost (tree);
basic_block bsi_insert_on_edge_immediate_loop (edge, tree); basic_block bsi_insert_on_edge_immediate_loop (edge, tree);
void standard_iv_increment_position (struct loop *, block_stmt_iterator *, void standard_iv_increment_position (struct loop *, block_stmt_iterator *,
bool *); bool *);
......
...@@ -2608,8 +2608,8 @@ scev_finalize (void) ...@@ -2608,8 +2608,8 @@ scev_finalize (void)
} }
/* Replace ssa names for that scev can prove they are constant by the /* Replace ssa names for that scev can prove they are constant by the
appropriate constants. Most importantly, this takes care of final appropriate constants. Also perform final value replacement in loops,
value replacement. in case the replacement expressions are cheap.
We only consider SSA names defined by phi nodes; rest is left to the We only consider SSA names defined by phi nodes; rest is left to the
ordinary constant propagation pass. */ ordinary constant propagation pass. */
...@@ -2618,9 +2618,10 @@ void ...@@ -2618,9 +2618,10 @@ void
scev_const_prop (void) scev_const_prop (void)
{ {
basic_block bb; basic_block bb;
tree name, phi, type, ev; tree name, phi, next_phi, type, ev;
struct loop *loop; struct loop *loop, *ex_loop;
bitmap ssa_names_to_remove = NULL; bitmap ssa_names_to_remove = NULL;
unsigned i;
if (!current_loops) if (!current_loops)
return; return;
...@@ -2675,4 +2676,56 @@ scev_const_prop (void) ...@@ -2675,4 +2676,56 @@ scev_const_prop (void)
BITMAP_FREE (ssa_names_to_remove); BITMAP_FREE (ssa_names_to_remove);
scev_reset (); scev_reset ();
} }
/* Now the regular final value replacement. */
for (i = current_loops->num - 1; i > 0; i--)
{
edge exit;
tree def, stmts;
loop = current_loops->parray[i];
if (!loop)
continue;
/* If we do not know exact number of iterations of the loop, we cannot
replace the final value. */
exit = loop->single_exit;
if (!exit
|| number_of_iterations_in_loop (loop) == chrec_dont_know)
continue;
ex_loop = exit->dest->loop_father;
for (phi = phi_nodes (exit->dest); phi; phi = next_phi)
{
next_phi = PHI_CHAIN (phi);
def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
if (!is_gimple_reg (def)
|| expr_invariant_in_loop_p (loop, def))
continue;
if (!POINTER_TYPE_P (TREE_TYPE (def))
&& !INTEGRAL_TYPE_P (TREE_TYPE (def)))
continue;
def = analyze_scalar_evolution_in_loop (ex_loop, ex_loop, def);
if (!tree_does_not_contain_chrecs (def)
|| chrec_contains_symbols_defined_in_loop (def, loop->num))
continue;
/* If computing the expression is expensive, let it remain in
loop. TODO -- we should take the cost of computing the expression
in loop into account. */
if (force_expr_to_var_cost (def) >= target_spill_cost)
continue;
if (is_gimple_val (def))
stmts = NULL_TREE;
else
def = force_gimple_operand (def, &stmts, true,
SSA_NAME_VAR (PHI_RESULT (phi)));
SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, exit), def);
if (stmts)
compute_phi_arg_on_exit (exit, stmts, def);
}
}
} }
...@@ -3415,12 +3415,11 @@ get_address_cost (bool symbol_present, bool var_present, ...@@ -3415,12 +3415,11 @@ get_address_cost (bool symbol_present, bool var_present,
return cost + acost; return cost + acost;
} }
/* Estimates cost of forcing EXPR into a variable. DEPENDS_ON is a set of the
invariants the computation depends on. */
static unsigned /* Estimates cost of forcing expression EXPR into a variable. */
force_var_cost (struct ivopts_data *data,
tree expr, bitmap *depends_on) unsigned
force_expr_to_var_cost (tree expr)
{ {
static bool costs_initialized = false; static bool costs_initialized = false;
static unsigned integer_cost; static unsigned integer_cost;
...@@ -3452,7 +3451,7 @@ force_var_cost (struct ivopts_data *data, ...@@ -3452,7 +3451,7 @@ force_var_cost (struct ivopts_data *data,
build_int_cst_type (type, 2000))) + 1; build_int_cst_type (type, 2000))) + 1;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "force_var_cost:\n"); fprintf (dump_file, "force_expr_to_var_cost:\n");
fprintf (dump_file, " integer %d\n", (int) integer_cost); fprintf (dump_file, " integer %d\n", (int) integer_cost);
fprintf (dump_file, " symbol %d\n", (int) symbol_cost); fprintf (dump_file, " symbol %d\n", (int) symbol_cost);
fprintf (dump_file, " address %d\n", (int) address_cost); fprintf (dump_file, " address %d\n", (int) address_cost);
...@@ -3465,12 +3464,6 @@ force_var_cost (struct ivopts_data *data, ...@@ -3465,12 +3464,6 @@ force_var_cost (struct ivopts_data *data,
STRIP_NOPS (expr); STRIP_NOPS (expr);
if (depends_on)
{
fd_ivopts_data = data;
walk_tree (&expr, find_depends, depends_on, NULL);
}
if (SSA_VAR_P (expr)) if (SSA_VAR_P (expr))
return 0; return 0;
...@@ -3505,12 +3498,12 @@ force_var_cost (struct ivopts_data *data, ...@@ -3505,12 +3498,12 @@ force_var_cost (struct ivopts_data *data,
if (is_gimple_val (op0)) if (is_gimple_val (op0))
cost0 = 0; cost0 = 0;
else else
cost0 = force_var_cost (data, op0, NULL); cost0 = force_expr_to_var_cost (op0);
if (is_gimple_val (op1)) if (is_gimple_val (op1))
cost1 = 0; cost1 = 0;
else else
cost1 = force_var_cost (data, op1, NULL); cost1 = force_expr_to_var_cost (op1);
break; break;
...@@ -3550,6 +3543,22 @@ force_var_cost (struct ivopts_data *data, ...@@ -3550,6 +3543,22 @@ force_var_cost (struct ivopts_data *data,
return cost < target_spill_cost ? cost : target_spill_cost; return cost < target_spill_cost ? cost : target_spill_cost;
} }
/* Estimates cost of forcing EXPR into a variable. DEPENDS_ON is a set of the
invariants the computation depends on. */
static unsigned
force_var_cost (struct ivopts_data *data,
tree expr, bitmap *depends_on)
{
if (depends_on)
{
fd_ivopts_data = data;
walk_tree (&expr, find_depends, depends_on, NULL);
}
return force_expr_to_var_cost (expr);
}
/* Estimates cost of expressing address ADDR as var + symbol + offset. The /* Estimates cost of expressing address ADDR as var + symbol + offset. The
value of offset is added to OFFSET, SYMBOL_PRESENT and VAR_PRESENT are set value of offset is added to OFFSET, SYMBOL_PRESENT and VAR_PRESENT are set
to false if the corresponding part is missing. DEPENDS_ON is a set of the to false if the corresponding part is missing. DEPENDS_ON is a set of the
...@@ -5600,7 +5609,7 @@ protect_loop_closed_ssa_form (edge exit, tree stmt) ...@@ -5600,7 +5609,7 @@ protect_loop_closed_ssa_form (edge exit, tree stmt)
so that they are emitted on the correct place, and so that the loop closed so that they are emitted on the correct place, and so that the loop closed
ssa form is preserved. */ ssa form is preserved. */
static void void
compute_phi_arg_on_exit (edge exit, tree stmts, tree op) compute_phi_arg_on_exit (edge exit, tree stmts, tree op)
{ {
tree_stmt_iterator tsi; tree_stmt_iterator tsi;
......
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