X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-copy.c;h=4c6d9927bbd23c8f72cc9530ef1ae6c94f886199;hb=9bdb68e5d565ddcf00209638d7365a32ac72a7db;hp=d552c3ab61ba0f3ec904ac84b4a6d6c1c75a9a5f;hpb=0d63aa16f49c5afb74d2572d84163c07d48874d8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c index d552c3ab61b..4c6d9927bbd 100644 --- a/gcc/tree-ssa-copy.c +++ b/gcc/tree-ssa-copy.c @@ -191,7 +191,10 @@ propagate_value (use_operand_p op_p, tree val) Use this version when not const/copy propagating values. For example, PRE uses this version when building expressions as they would appear - in specific blocks taking into account actions of PHI nodes. */ + in specific blocks taking into account actions of PHI nodes. + + The statement in which an expression has been replaced should be + folded using fold_stmt_inplace. */ void replace_exp (use_operand_p op_p, tree val) @@ -241,7 +244,6 @@ propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val) expr = gimple_assign_rhs1 (stmt); propagate_tree_value (&expr, val); gimple_assign_set_rhs_from_tree (gsi, expr); - stmt = gsi_stmt (*gsi); } else if (gimple_code (stmt) == GIMPLE_COND) { @@ -313,8 +315,9 @@ stmt_may_generate_copy (gimple stmt) /* Otherwise, the only statements that generate useful copies are assignments whose RHS is just an SSA name that doesn't flow through abnormal edges. */ - return (gimple_assign_rhs_code (stmt) == SSA_NAME - && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt))); + return ((gimple_assign_rhs_code (stmt) == SSA_NAME + && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt))) + || is_gimple_min_invariant (gimple_assign_rhs1 (stmt))); } @@ -564,6 +567,7 @@ copy_prop_visit_phi_node (gimple phi) for (i = 0; i < gimple_phi_num_args (phi); i++) { prop_value_t *arg_val; + tree arg_value; tree arg = gimple_phi_arg_def (phi, i); edge e = gimple_phi_arg_edge (phi, i); @@ -572,24 +576,9 @@ copy_prop_visit_phi_node (gimple phi) if (!(e->flags & EDGE_EXECUTABLE)) continue; - /* Constants in the argument list never generate a useful copy. - Similarly, names that flow through abnormal edges cannot be - used to derive copies. */ - if (TREE_CODE (arg) != SSA_NAME || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg)) - { - phi_val.value = lhs; - break; - } - - /* Avoid copy propagation from an inner into an outer loop. - Otherwise, this may move loop variant variables outside of - their loops and prevent coalescing opportunities. If the - value was loop invariant, it will be hoisted by LICM and - exposed for copy propagation. Not a problem for virtual - operands though. - ??? The value will be always loop invariant. */ - if (is_gimple_reg (lhs) - && loop_depth_of_name (arg) > loop_depth_of_name (lhs)) + /* Names that flow through abnormal edges cannot be used to + derive copies. */ + if (TREE_CODE (arg) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg)) { phi_val.value = lhs; break; @@ -602,26 +591,51 @@ copy_prop_visit_phi_node (gimple phi) fprintf (dump_file, "\n"); } - arg_val = get_copy_of_val (arg); + if (TREE_CODE (arg) == SSA_NAME) + { + arg_val = get_copy_of_val (arg); - /* If we didn't visit the definition of arg yet treat it as - UNDEFINED. This also handles PHI arguments that are the - same as lhs. We'll come here again. */ - if (!arg_val->value) - continue; + /* If we didn't visit the definition of arg yet treat it as + UNDEFINED. This also handles PHI arguments that are the + same as lhs. We'll come here again. */ + if (!arg_val->value) + continue; + + arg_value = arg_val->value; + } + else + arg_value = valueize_val (arg); + + /* Avoid copy propagation from an inner into an outer loop. + Otherwise, this may move loop variant variables outside of + their loops and prevent coalescing opportunities. If the + value was loop invariant, it will be hoisted by LICM and + exposed for copy propagation. + ??? The value will be always loop invariant. + In loop-closed SSA form do not copy-propagate through + PHI nodes in blocks with a loop exit edge predecessor. */ + if (current_loops + && TREE_CODE (arg_value) == SSA_NAME + && (loop_depth_of_name (arg_value) > loop_depth_of_name (lhs) + || (loops_state_satisfies_p (LOOP_CLOSED_SSA) + && loop_exit_edge_p (e->src->loop_father, e)))) + { + phi_val.value = lhs; + break; + } /* If the LHS didn't have a value yet, make it a copy of the first argument we find. */ if (phi_val.value == NULL_TREE) { - phi_val.value = arg_val->value; + phi_val.value = arg_value; continue; } /* If PHI_VAL and ARG don't have a common copy-of chain, then this PHI node cannot be a copy operation. */ - if (phi_val.value != arg_val->value - && !operand_equal_p (phi_val.value, arg_val->value, 0)) + if (phi_val.value != arg_value + && !operand_equal_p (phi_val.value, arg_value, 0)) { phi_val.value = lhs; break; @@ -666,7 +680,6 @@ init_copy_prop (void) { gimple_stmt_iterator si; int depth = bb->loop_depth; - bool loop_exit_p = false; for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) { @@ -703,26 +716,13 @@ init_copy_prop (void) set_copy_of_val (def, def); } - /* In loop-closed SSA form do not copy-propagate through - PHI nodes in blocks with a loop exit edge predecessor. */ - if (current_loops - && loops_state_satisfies_p (LOOP_CLOSED_SSA)) - { - edge_iterator ei; - edge e; - FOR_EACH_EDGE (e, ei, bb->preds) - if (loop_exit_edge_p (e->src->loop_father, e)) - loop_exit_p = true; - } - for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si)) { gimple phi = gsi_stmt (si); tree def; def = gimple_phi_result (phi); - if (!is_gimple_reg (def) - || loop_exit_p) + if (!is_gimple_reg (def)) prop_set_simulate_again (phi, false); else prop_set_simulate_again (phi, true); @@ -769,6 +769,7 @@ fini_copy_prop (void) of the representative to the first solution we find if it doesn't have one already. */ if (copy_of[i].value != var + && TREE_CODE (copy_of[i].value) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (var)) && SSA_NAME_PTR_INFO (var) && !SSA_NAME_PTR_INFO (copy_of[i].value)) @@ -847,7 +848,6 @@ struct gimple_opt_pass pass_copy_prop = 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_cleanup_cfg - | TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa | TODO_update_ssa /* todo_flags_finish */