/* Reassociation for trees.
- Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Daniel Berlin <dan@dberlin.org>
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "errors.h"
#include "ggc.h"
#include "tree.h"
#include "basic-block.h"
Thus, this is what we do. When we have three ops left, we check to see
what order to put them in, and call it a day. As a nod to vector sum
- reduction, we check if any of ops are a really a phi node that is a
+ reduction, we check if any of the ops are really a phi node that is a
destructive update for the associating op, and keep the destructive
update together for vector sum reduction recognition. */
}
else
{
- gsi = gsi_for_stmt (op2def);
- gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
+ if (!stmt_ends_bb_p (op2def))
+ {
+ gsi = gsi_for_stmt (op2def);
+ gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
+ }
+ else
+ {
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, gimple_bb (op2def)->succs)
+ if (e->flags & EDGE_FALLTHRU)
+ gsi_insert_on_edge_immediate (e, sum);
+ }
}
}
else
}
else
{
- gsi = gsi_for_stmt (op1def);
- gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
+ if (!stmt_ends_bb_p (op1def))
+ {
+ gsi = gsi_for_stmt (op1def);
+ gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
+ }
+ else
+ {
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, gimple_bb (op1def)->succs)
+ if (e->flags & EDGE_FALLTHRU)
+ gsi_insert_on_edge_immediate (e, sum);
+ }
}
}
update_stmt (sum);
return false;
}
+/* Remove def stmt of VAR if VAR has zero uses and recurse
+ on rhs1 operand if so. */
+
+static void
+remove_visited_stmt_chain (tree var)
+{
+ gimple stmt;
+ gimple_stmt_iterator gsi;
+
+ while (1)
+ {
+ if (TREE_CODE (var) != SSA_NAME || !has_zero_uses (var))
+ return;
+ stmt = SSA_NAME_DEF_STMT (var);
+ if (!is_gimple_assign (stmt)
+ || !gimple_visited_p (stmt))
+ return;
+ var = gimple_assign_rhs1 (stmt);
+ gsi = gsi_for_stmt (stmt);
+ gsi_remove (&gsi, true);
+ release_defs (stmt);
+ }
+}
+
/* Recursively rewrite our linearized statements so that the operators
match those in OPS[OPINDEX], putting the computation in rank
order. */
static void
rewrite_expr_tree (gimple stmt, unsigned int opindex,
- VEC(operand_entry_t, heap) * ops)
+ VEC(operand_entry_t, heap) * ops, bool moved)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs2 = gimple_assign_rhs2 (stmt);
gimple_assign_set_rhs1 (stmt, oe1->op);
gimple_assign_set_rhs2 (stmt, oe2->op);
update_stmt (stmt);
+ if (rhs1 != oe1->op && rhs1 != oe2->op)
+ remove_visited_stmt_chain (rhs1);
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (oe->op != rhs2)
{
+ if (!moved)
+ {
+ gimple_stmt_iterator gsinow, gsirhs1;
+ gimple stmt1 = stmt, stmt2;
+ unsigned int count;
+
+ gsinow = gsi_for_stmt (stmt);
+ count = VEC_length (operand_entry_t, ops) - opindex - 2;
+ while (count-- != 0)
+ {
+ stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
+ gsirhs1 = gsi_for_stmt (stmt2);
+ gsi_move_before (&gsirhs1, &gsinow);
+ gsi_prev (&gsinow);
+ stmt1 = stmt2;
+ }
+ moved = true;
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
{
}
/* Recurse on the LHS of the binary operator, which is guaranteed to
be the non-leaf side. */
- rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops);
+ rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops, moved);
}
/* Transform STMT, which is really (A +B) + (C + D) into the left
linearize_expr_tree (VEC(operand_entry_t, heap) **ops, gimple stmt,
bool is_associative, bool set_visited)
{
- gimple_stmt_iterator gsinow, gsilhs;
tree binlhs = gimple_assign_rhs1 (stmt);
tree binrhs = gimple_assign_rhs2 (stmt);
gimple binlhsdef, binrhsdef;
gcc_assert (TREE_CODE (binrhs) != SSA_NAME
|| !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs),
rhscode, loop));
- gsinow = gsi_for_stmt (stmt);
- gsilhs = gsi_for_stmt (SSA_NAME_DEF_STMT (binlhs));
- gsi_move_before (&gsilhs, &gsinow);
linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs),
is_associative, set_visited);
add_to_ops_vec (ops, binrhs);
fprintf (dump_file, "Transforming ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
-
+
+ rhs1 = gimple_assign_rhs1 (stmt);
gimple_assign_set_rhs_from_tree (&gsi,
VEC_last (operand_entry_t,
ops)->op);
update_stmt (stmt);
+ remove_visited_stmt_chain (rhs1);
if (dump_file && (dump_flags & TDF_DETAILS))
{
}
}
else
- {
- rewrite_expr_tree (stmt, 0, ops);
- }
+ rewrite_expr_tree (stmt, 0, ops, false);
VEC_free (operand_entry_t, heap, ops);
}