diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2012-09-17 14:50:13 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2012-09-17 14:50:13 +0000 |
commit | fea4ea737fa4a9ab3d979b6f0b969a96cbbb4cd1 (patch) | |
tree | d096ec551125ec07018795cb4a794091435c90a9 /gcc | |
parent | 9bf714c23f5dd6d340571d090f2b22d7f67a9503 (diff) | |
download | gcc-fea4ea737fa4a9ab3d979b6f0b969a96cbbb4cd1.zip gcc-fea4ea737fa4a9ab3d979b6f0b969a96cbbb4cd1.tar.gz gcc-fea4ea737fa4a9ab3d979b6f0b969a96cbbb4cd1.tar.bz2 |
* 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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/loop_optimization12.adb | 22 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/loop_optimization12.ads | 27 | ||||
-rw-r--r-- | gcc/tree-cfgcleanup.c | 39 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivcanon.c | 114 |
6 files changed, 178 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f406688..587f878 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +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> PR tree-optimization/54563 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2cbdb5a..7581988 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +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> PR fortran/54285 diff --git a/gcc/testsuite/gnat.dg/loop_optimization12.adb b/gcc/testsuite/gnat.dg/loop_optimization12.adb new file mode 100644 index 0000000..2408746 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization12.adb @@ -0,0 +1,22 @@ +-- { 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; diff --git a/gcc/testsuite/gnat.dg/loop_optimization12.ads b/gcc/testsuite/gnat.dg/loop_optimization12.ads new file mode 100644 index 0000000..0ed4e8b --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization12.ads @@ -0,0 +1,27 @@ +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; diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 45f3368..9c52286 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -88,40 +88,11 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi) switch (gimple_code (stmt)) { case GIMPLE_COND: - { - tree lhs = gimple_cond_lhs (stmt); - tree rhs = gimple_cond_rhs (stmt); - /* For conditions try harder and lookup single-argument - PHI nodes. Only do so from the same basic-block though - 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; - } + val = fold_binary_loc (loc, gimple_cond_code (stmt), + boolean_type_node, + gimple_cond_lhs (stmt), + gimple_cond_rhs (stmt)); + break; case GIMPLE_SWITCH: val = gimple_switch_index (stmt); diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index e1584b4..1e44dd4 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -503,6 +503,80 @@ canonicalize_induction_variables (void) 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 MAY_INCREASE_SIZE is true, perform the unrolling only if the size of the code does not increase. */ @@ -510,6 +584,7 @@ canonicalize_induction_variables (void) unsigned int 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; struct loop *loop; bool changed; @@ -522,22 +597,51 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) 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) /* Unroll outermost loops only if asked to do so or they do not cause code growth. */ - && (unroll_outer - || loop_outer (loop_outer (loop)))) + && (unroll_outer || loop_outer (loop_father))) ul = UL_ALL; else 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) { + struct loop **iter; + unsigned i; + 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 from the loop structures so we can continue unrolling now innermost loops. */ @@ -552,5 +656,7 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) while (changed && ++iteration <= PARAM_VALUE (PARAM_MAX_UNROLL_ITERATIONS)); + VEC_free (loop_p, stack, father_stack); + return 0; } |