diff options
Diffstat (limited to 'gcc/tree-ssa-phiopt.c')
-rw-r--r-- | gcc/tree-ssa-phiopt.c | 105 |
1 files changed, 71 insertions, 34 deletions
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 0cef8ee..c195e3b 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -36,13 +36,14 @@ along with GCC; see the file COPYING3. If not see #include "domwalk.h" #include "cfgloop.h" #include "tree-data-ref.h" +#include "tree-pretty-print.h" static unsigned int tree_ssa_phiopt (void); static unsigned int tree_ssa_phiopt_worker (bool); static bool conditional_replacement (basic_block, basic_block, edge, edge, gimple, tree, tree); -static bool value_replacement (basic_block, basic_block, - edge, edge, gimple, tree, tree); +static int value_replacement (basic_block, basic_block, + edge, edge, gimple, tree, tree); static bool minmax_replacement (basic_block, basic_block, edge, edge, gimple, tree, tree); static bool abs_replacement (basic_block, basic_block, @@ -314,7 +315,24 @@ tree_ssa_phiopt_worker (bool do_store_elim) { gimple_seq phis = phi_nodes (bb2); gimple_stmt_iterator gsi; + bool candorest = true; + /* Value replacement can work with more than one PHI + so try that first. */ + for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi)) + { + phi = gsi_stmt (gsi); + arg0 = gimple_phi_arg_def (phi, e1->dest_idx); + arg1 = gimple_phi_arg_def (phi, e2->dest_idx); + if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2) + { + candorest = false; + cfgchanged = true; + break; + } + } + if (!candorest) + continue; /* Check to make sure that there is only one non-virtual PHI node. TODO: we could do it with more than one iff the other PHI nodes have the same elements for these two edges. */ @@ -343,8 +361,6 @@ tree_ssa_phiopt_worker (bool do_store_elim) /* Do the replacement of conditional if it can be done. */ if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) cfgchanged = true; - else if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) - cfgchanged = true; else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) cfgchanged = true; else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) @@ -624,12 +640,12 @@ jump_function_from_stmt (tree *arg, gimple stmt) } /* The function value_replacement does the main work of doing the value - replacement. Return true if the replacement is done. Otherwise return - false. + replacement. Return non-zero if the replacement is done. Otherwise return + 0. If we remove the middle basic block, return 2. BB is the basic block where the replacement is going to be done on. ARG0 is argument 0 from the PHI. Likewise for ARG1. */ -static bool +static int value_replacement (basic_block cond_bb, basic_block middle_bb, edge e0, edge e1, gimple phi, tree arg0, tree arg1) @@ -638,37 +654,36 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, gimple cond; edge true_edge, false_edge; enum tree_code code; + bool emtpy_or_with_defined_p = true; /* If the type says honor signed zeros we cannot do this optimization. */ if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1)))) - return false; + return 0; - /* Allow a single statement in MIDDLE_BB that defines one of the PHI - arguments. */ + /* If there is a statement in MIDDLE_BB that defines one of the PHI + arguments, then adjust arg0 or arg1. */ gsi = gsi_after_labels (middle_bb); - if (!gsi_end_p (gsi)) + if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) + gsi_next_nondebug (&gsi); + while (!gsi_end_p (gsi)) { - if (is_gimple_debug (gsi_stmt (gsi))) - gsi_next_nondebug (&gsi); - if (!gsi_end_p (gsi)) + gimple stmt = gsi_stmt (gsi); + tree lhs; + gsi_next_nondebug (&gsi); + if (!is_gimple_assign (stmt)) { - gimple stmt = gsi_stmt (gsi); - tree lhs; - gsi_next_nondebug (&gsi); - if (!gsi_end_p (gsi)) - return false; - if (!is_gimple_assign (stmt)) - return false; - /* Now try to adjust arg0 or arg1 according to the computation - in the single statement. */ - lhs = gimple_assign_lhs (stmt); - if (!((lhs == arg0 - && jump_function_from_stmt (&arg0, stmt)) - || (lhs == arg1 - && jump_function_from_stmt (&arg1, stmt)))) - return false; + emtpy_or_with_defined_p = false; + continue; } + /* Now try to adjust arg0 or arg1 according to the computation + in the statement. */ + lhs = gimple_assign_lhs (stmt); + if (!(lhs == arg0 + && jump_function_from_stmt (&arg0, stmt)) + || (lhs == arg1 + && jump_function_from_stmt (&arg1, stmt))) + emtpy_or_with_defined_p = false; } cond = last_stmt (cond_bb); @@ -676,7 +691,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, /* This transformation is only valid for equality comparisons. */ if (code != NE_EXPR && code != EQ_EXPR) - return false; + return 0; /* We need to know which is the true edge and which is the false edge so that we know if have abs or negative abs. */ @@ -720,12 +735,34 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, else arg = arg1; - replace_phi_edge_with_variable (cond_bb, e1, phi, arg); + /* If the middle basic block was empty or is defining the + PHI arguments and this is a singleton phi then we can remove + the middle basic block. */ + if (emtpy_or_with_defined_p + && gimple_seq_singleton_p (phi_nodes (gimple_bb (phi)))) + { + replace_phi_edge_with_variable (cond_bb, e1, phi, arg); + /* Note that we optimized this PHI. */ + return 2; + } + else + { + /* Replace the PHI arguments with arg. */ + SET_PHI_ARG_DEF (phi, e0->dest_idx, arg); + SET_PHI_ARG_DEF (phi, e1->dest_idx, arg); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "PHI "); + print_generic_expr (dump_file, gimple_phi_result (phi), 0); + fprintf (dump_file, " reduced for COND_EXPR in block %d to ", cond_bb->index); + print_generic_expr (dump_file, arg, 0); + fprintf (dump_file, ".\n"); + } + return 1; + } - /* Note that we optimized this PHI. */ - return true; } - return false; + return 0; } /* The function minmax_replacement does the main work of doing the minmax |