Commit fea4ea73 by Eric Botcazou Committed by Eric Botcazou

* tree-cfgcleanup. (cleanup_control_expr_graph) <GIMPLE_COND>: Remove

	code doing propagation from degenerate PHI nodes.
	* tree-ssa-loop-ivcanon.c (propagate_into_all_uses): New function.
	(propagate_constants_for_unrolling): Likewise.
	(tree_unroll_loops_completely): If the current loop has been unrolled
	and its father isn't the entire function, propagate constants within
	the new basic blocks by means of propagate_constants_for_unrolling.

From-SVN: r191387
parent 9bf714c2
2012-09-17 Eric Botcazou <ebotcazou@adacore.com>
* tree-cfgcleanup. (cleanup_control_expr_graph) <GIMPLE_COND>: Remove
code doing propagation from degenerate PHI nodes.
* tree-ssa-loop-ivcanon.c (propagate_into_all_uses): New function.
(propagate_constants_for_unrolling): Likewise.
(tree_unroll_loops_completely): If the current loop has been unrolled
and its father isn't the entire function, propagate constants within
the new basic blocks by means of propagate_constants_for_unrolling.
2012-09-17 Jakub Jelinek <jakub@redhat.com> 2012-09-17 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/54563 PR tree-optimization/54563
......
2012-09-17 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/loop_optimization12.ad[sb]: New test.
2012-09-17 Janus Weil <janus@gcc.gnu.org> 2012-09-17 Janus Weil <janus@gcc.gnu.org>
PR fortran/54285 PR fortran/54285
......
-- { dg-do compile }
-- { dg-options "-O2" }
package body Loop_Optimization12 is
procedure Reset (S : Rec_Ptr) is
begin
for I in Enum1 loop
S.F (I).all := (others =>
(others =>
(others =>
(others =>
(others =>
(others =>
(others =>
(others =>
(others =>
(others => 0))))))))));
end loop;
end;
end Loop_Optimization12;
package Loop_Optimization12 is
type Enum1 is (A, B, C, D, E, F, G, H, I, J);
type Enum2 is (A, B, C);
type Enum3 is (A, B, C, D, E, F);
type Enum4 is (A, B, C, D);
type Enum5 is (A, B, C, D, E);
type Arr is array (Enum3, Enum4, Enum4, Enum5, Enum5, Enum3,
Enum2, Enum3, Enum5, Enum3) of Natural;
type Arr_Ptr is access Arr;
type Ext_Arr is array (Enum1) of Arr_Ptr;
type Rec is record
F : Ext_Arr;
end record;
type Rec_Ptr is access Rec;
procedure Reset (S : Rec_Ptr);
end Loop_Optimization12;
...@@ -88,40 +88,11 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi) ...@@ -88,40 +88,11 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi)
switch (gimple_code (stmt)) switch (gimple_code (stmt))
{ {
case GIMPLE_COND: case GIMPLE_COND:
{ val = fold_binary_loc (loc, gimple_cond_code (stmt),
tree lhs = gimple_cond_lhs (stmt); boolean_type_node,
tree rhs = gimple_cond_rhs (stmt); gimple_cond_lhs (stmt),
/* For conditions try harder and lookup single-argument gimple_cond_rhs (stmt));
PHI nodes. Only do so from the same basic-block though break;
as other basic-blocks may be dead already. */
if (TREE_CODE (lhs) == SSA_NAME
&& !name_registered_for_update_p (lhs))
{
gimple def_stmt = SSA_NAME_DEF_STMT (lhs);
if (gimple_code (def_stmt) == GIMPLE_PHI
&& gimple_phi_num_args (def_stmt) == 1
&& gimple_bb (def_stmt) == gimple_bb (stmt)
&& (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME
|| !name_registered_for_update_p (PHI_ARG_DEF (def_stmt,
0))))
lhs = PHI_ARG_DEF (def_stmt, 0);
}
if (TREE_CODE (rhs) == SSA_NAME
&& !name_registered_for_update_p (rhs))
{
gimple def_stmt = SSA_NAME_DEF_STMT (rhs);
if (gimple_code (def_stmt) == GIMPLE_PHI
&& gimple_phi_num_args (def_stmt) == 1
&& gimple_bb (def_stmt) == gimple_bb (stmt)
&& (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME
|| !name_registered_for_update_p (PHI_ARG_DEF (def_stmt,
0))))
rhs = PHI_ARG_DEF (def_stmt, 0);
}
val = fold_binary_loc (loc, gimple_cond_code (stmt),
boolean_type_node, lhs, rhs);
break;
}
case GIMPLE_SWITCH: case GIMPLE_SWITCH:
val = gimple_switch_index (stmt); val = gimple_switch_index (stmt);
......
...@@ -503,6 +503,80 @@ canonicalize_induction_variables (void) ...@@ -503,6 +503,80 @@ canonicalize_induction_variables (void)
return 0; return 0;
} }
/* Propagate VAL into all uses of SSA_NAME. */
static void
propagate_into_all_uses (tree ssa_name, tree val)
{
imm_use_iterator iter;
gimple use_stmt;
FOR_EACH_IMM_USE_STMT (use_stmt, iter, ssa_name)
{
gimple_stmt_iterator use_stmt_gsi = gsi_for_stmt (use_stmt);
use_operand_p use;
FOR_EACH_IMM_USE_ON_STMT (use, iter)
SET_USE (use, val);
if (is_gimple_assign (use_stmt)
&& get_gimple_rhs_class (gimple_assign_rhs_code (use_stmt))
== GIMPLE_SINGLE_RHS)
{
tree rhs = gimple_assign_rhs1 (use_stmt);
if (TREE_CODE (rhs) == ADDR_EXPR)
recompute_tree_invariant_for_addr_expr (rhs);
}
fold_stmt_inplace (&use_stmt_gsi);
update_stmt (use_stmt);
}
}
/* Propagate constant SSA_NAMEs defined in basic block BB. */
static void
propagate_constants_for_unrolling (basic_block bb)
{
gimple_stmt_iterator gsi;
/* Look for degenerate PHI nodes with constant argument. */
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
{
gimple phi = gsi_stmt (gsi);
tree result = gimple_phi_result (phi);
tree arg = gimple_phi_arg_def (phi, 0);
if (gimple_phi_num_args (phi) == 1 && TREE_CODE (arg) == INTEGER_CST)
{
propagate_into_all_uses (result, arg);
gsi_remove (&gsi, true);
release_ssa_name (result);
}
else
gsi_next (&gsi);
}
/* Look for assignments to SSA names with constant RHS. */
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
{
gimple stmt = gsi_stmt (gsi);
tree lhs;
if (is_gimple_assign (stmt)
&& (lhs = gimple_assign_lhs (stmt), TREE_CODE (lhs) == SSA_NAME)
&& gimple_assign_rhs_code (stmt) == INTEGER_CST)
{
propagate_into_all_uses (lhs, gimple_assign_rhs1 (stmt));
gsi_remove (&gsi, true);
release_ssa_name (lhs);
}
else
gsi_next (&gsi);
}
}
/* Unroll LOOPS completely if they iterate just few times. Unless /* Unroll LOOPS completely if they iterate just few times. Unless
MAY_INCREASE_SIZE is true, perform the unrolling only if the MAY_INCREASE_SIZE is true, perform the unrolling only if the
size of the code does not increase. */ size of the code does not increase. */
...@@ -510,6 +584,7 @@ canonicalize_induction_variables (void) ...@@ -510,6 +584,7 @@ canonicalize_induction_variables (void)
unsigned int unsigned int
tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
{ {
VEC(loop_p,stack) *father_stack = VEC_alloc (loop_p, stack, 16);
loop_iterator li; loop_iterator li;
struct loop *loop; struct loop *loop;
bool changed; bool changed;
...@@ -522,22 +597,51 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) ...@@ -522,22 +597,51 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST) FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
{ {
struct loop *loop_father = loop_outer (loop);
if (may_increase_size && optimize_loop_for_speed_p (loop) if (may_increase_size && optimize_loop_for_speed_p (loop)
/* Unroll outermost loops only if asked to do so or they do /* Unroll outermost loops only if asked to do so or they do
not cause code growth. */ not cause code growth. */
&& (unroll_outer && (unroll_outer || loop_outer (loop_father)))
|| loop_outer (loop_outer (loop))))
ul = UL_ALL; ul = UL_ALL;
else else
ul = UL_NO_GROWTH; ul = UL_NO_GROWTH;
changed |= canonicalize_loop_induction_variables
(loop, false, ul, !flag_tree_loop_ivcanon); if (canonicalize_loop_induction_variables (loop, false, ul,
!flag_tree_loop_ivcanon))
{
changed = true;
/* If we'll continue unrolling, we need to propagate constants
within the new basic blocks to fold away induction variable
computations; otherwise, the size might blow up before the
iteration is complete and the IR eventually cleaned up. */
if (loop_outer (loop_father) && !loop_father->aux)
{
VEC_safe_push (loop_p, stack, father_stack, loop_father);
loop_father->aux = loop_father;
}
}
} }
if (changed) if (changed)
{ {
struct loop **iter;
unsigned i;
update_ssa (TODO_update_ssa); update_ssa (TODO_update_ssa);
/* Propagate the constants within the new basic blocks. */
FOR_EACH_VEC_ELT (loop_p, father_stack, i, iter)
{
unsigned j;
basic_block *body = get_loop_body_in_dom_order (*iter);
for (j = 0; j < (*iter)->num_nodes; j++)
propagate_constants_for_unrolling (body[j]);
free (body);
(*iter)->aux = NULL;
}
VEC_truncate (loop_p, father_stack, 0);
/* This will take care of removing completely unrolled loops /* This will take care of removing completely unrolled loops
from the loop structures so we can continue unrolling now from the loop structures so we can continue unrolling now
innermost loops. */ innermost loops. */
...@@ -552,5 +656,7 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) ...@@ -552,5 +656,7 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
while (changed while (changed
&& ++iteration <= PARAM_VALUE (PARAM_MAX_UNROLL_ITERATIONS)); && ++iteration <= PARAM_VALUE (PARAM_MAX_UNROLL_ITERATIONS));
VEC_free (loop_p, stack, father_stack);
return 0; return 0;
} }
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