* often.
* @author Christian Schaefer, Goetz Lindenmaier, Sebastian Felis,
* Michael Beck
- * @version $Id$
*
* The idea here is to push nodes as deep into the dominance tree as their
* dependencies allow. After pushing them back up out of as many loops as
#include "iroptimize.h"
#include "adt/pdeq.h"
#include "irnode_t.h"
-#include "irouts.h"
+#include "iredges_t.h"
#include "irgopt.h"
#include "irpass.h"
-#include "opt_manage.h"
static bool is_block_reachable(ir_node *block)
{
return get_Block_dom_depth(block) >= 0;
}
+/**
+ * Firm keepalive edges are broken (the user should really be the endless loop
+ * and not the End node.) This wrong place of the user will lead to wrong
+ * results in place_early()/place_late(). We work around these problems by not
+ * moving nodes which just have keepalive edges as their users (or no users at
+ * all)
+ */
+static bool float_exceptions(const ir_node *node)
+{
+ foreach_out_edge(node, edge) {
+ ir_node *succ = get_edge_src_irn(edge);
+ if (is_End(succ))
+ continue;
+ /* found a real user */
+ return false;
+ }
+ return true;
+}
+
/**
* Find the earliest correct block for node n. --- Place n into the
* same Block as its dominance-deepest Input.
* This works because in firm each cycle contains a Phi or Block node
* (which are pinned)
*/
- if (get_irn_pinned(n) != op_pin_state_floats) {
+ if (get_irn_pinned(n) != op_pin_state_floats || float_exceptions(n)) {
/* we can't move pinned nodes */
arity = get_irn_arity(n);
for (i = 0; i < arity; ++i) {
start_block = get_irg_start_block(irg);
if (new_block == start_block && block != start_block &&
get_irg_phase_state(irg) != phase_backend) {
- assert(get_Block_n_cfg_outs(start_block) == 1);
- new_block = get_Block_cfg_out(start_block, 0);
+ assert(get_irn_n_edges_kind(start_block, EDGE_KIND_BLOCK) == 1);
+ const ir_edge_t *edge = get_block_succ_first(start_block);
+ new_block = get_edge_src_irn(edge);
}
/* Set the new block */
*/
static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca)
{
- int i;
-
- for (i = get_irn_n_outs(node) - 1; i >= 0; --i) {
- ir_node *succ = get_irn_out(node, i);
+ foreach_out_edge(node, edge) {
+ ir_node *succ = get_edge_src_irn(edge);
/* keepalive edges are special and don't respect the dominance */
if (is_End(succ))
dca = consumer_dom_dca(dca, succ, node);
}
}
+ foreach_out_edge_kind(node, edge, EDGE_KIND_DEP) {
+ ir_node *succ = get_edge_src_irn(edge);
+ assert(is_block_reachable(get_nodes_block(succ)));
+ dca = consumer_dom_dca(dca, succ, node);
+ }
return dca;
}
*/
static void set_projs_block(ir_node *node, ir_node *block)
{
- int i;
+ foreach_out_edge(node, edge) {
+ ir_node *succ = get_edge_src_irn(edge);
- for (i = get_irn_n_outs(node) - 1; i >= 0; --i) {
- ir_node *succ = get_irn_out(node, i);
-
- assert(is_Proj(succ));
+ if (!is_Proj(succ))
+ continue;
+ set_nodes_block(succ, block);
if (get_irn_mode(succ) == mode_T) {
set_projs_block(succ, block);
}
- set_nodes_block(succ, block);
}
}
*/
static void place_floats_late(ir_node *n, pdeq *worklist)
{
- int n_outs;
- int i;
ir_node *block;
ir_node *dca;
if (irn_visited_else_mark(n))
return;
- n_outs = get_irn_n_outs(n);
/* break cycles at pinned nodes (see place place_floats_early) as to why */
if (get_irn_pinned(n) != op_pin_state_floats) {
- for (i = 0; i < n_outs; ++i) {
- ir_node *succ = get_irn_out(n, i);
+ foreach_out_edge(n, edge) {
+ ir_node *succ = get_edge_src_irn(edge);
pdeq_putr(worklist, succ);
}
return;
}
/* place our users */
- for (i = 0; i < n_outs; ++i) {
- ir_node *succ = get_irn_out(n, i);
+ foreach_out_edge(n, edge) {
+ ir_node *succ = get_edge_src_irn(edge);
place_floats_late(succ, worklist);
}
return;
/* some nodes should simply stay in the startblock */
if (is_irn_start_block_placed(n)) {
-#ifndef NDEBUG
- ir_graph *irg = get_irn_irg(n);
- ir_node *start_block = get_irg_start_block(irg);
- assert(get_nodes_block(n) == start_block);
-#endif
+ assert(get_nodes_block(n) == get_irg_start_block(get_irn_irg(n)));
return;
}
}
/* Code Placement. */
-static ir_graph_state_t do_codeplacement(ir_graph *irg)
+void place_code(ir_graph *irg)
{
waitq *worklist;
/* Handle graph state */
assert(get_irg_phase_state(irg) != phase_building);
+ assure_irg_properties(irg,
+ IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES |
+ IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE |
+ IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES |
+ IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE |
+ IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
/* Place all floating nodes as early as possible. This guarantees
a legal code placement. */
place_late(irg, worklist);
del_waitq(worklist);
- return 0;
-}
-
-optdesc_t opt_codeplacement = {
- "code-placement",
- IR_GRAPH_STATE_NO_CRITICAL_EDGES |
- IR_GRAPH_STATE_CONSISTENT_OUTS |
- IR_GRAPH_STATE_CONSISTENT_DOMINANCE |
- IR_GRAPH_STATE_CONSISTENT_LOOPINFO,
- do_codeplacement,
-};
-
-void place_code(ir_graph *irg)
-{
- perform_irg_optimization(irg, &opt_codeplacement);
+ confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW);
}
/**
set_opt_global_cse(0);
}
-static ir_graph_state_t do_gcse(ir_graph *irg)
-{
- set_opt_global_cse(1);
- optimize_graph_df(irg);
- do_codeplacement(irg);
- set_opt_global_cse(0);
- return 0;
-}
-
-optdesc_t opt_gcse = {
- "gcse",
- IR_GRAPH_STATE_NO_CRITICAL_EDGES |
- IR_GRAPH_STATE_CONSISTENT_OUTS |
- IR_GRAPH_STATE_CONSISTENT_DOMINANCE |
- IR_GRAPH_STATE_CONSISTENT_LOOPINFO,
- do_gcse,
-};
-
ir_graph_pass_t *place_code_pass(const char *name)
{
return def_graph_pass(name ? name : "place", place_code_wrapper);