#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,
{
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. */
/* 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))
}
/* 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)
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);
/* 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. */
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