* Michael Beck
* @version $Id$
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
+#include "iroptimize.h"
#include "adt/pdeq.h"
#include "irnode_t.h"
#include "irouts.h"
#include "irgopt.h"
+#include "irpass.h"
/**
* Returns non-zero, is a block is not reachable from Start.
*
* @param block the block to test
*/
-static int
-is_Block_unreachable(ir_node *block) {
+static int is_Block_unreachable(ir_node *block)
+{
return is_Block_dead(block) || get_Block_dom_depth(block) < 0;
}
* @param n the node to be placed
* @param worklist a worklist, predecessors of non-floating nodes are placed here
*/
-static void
-place_floats_early(ir_node *n, waitq *worklist) {
+static void place_floats_early(ir_node *n, waitq *worklist)
+{
int i, irn_arity;
/* we must not run into an infinite loop */
- assert(irn_not_visited(n));
+ assert(!irn_visited(n));
mark_irn_visited(n);
/* Place floating nodes. */
ir_node *pred = get_irn_n(n, i);
ir_node *pred_block;
- if ((irn_not_visited(pred))
+ if (!irn_visited(pred)
&& (get_irn_pinned(pred) == op_pin_state_floats)) {
/*
* If the current node is NOT in a dead block, but one of its
- * predecessors is, we must move the predecessor to a live block.
- * Such thing can happen, if global CSE chose a node from a dead block.
- * We move it simply to our block.
+ * predecessors is, we must move the predecessor to a live
+ * block.
+ * Such thing can happen, if global CSE chose a node from a
+ * dead block. We move it simply to our block.
* Note that neither Phi nor End nodes are floating, so we don't
* need to handle them here.
*/
if (in_dead_block)
continue;
- /* Because all loops contain at least one op_pin_state_pinned node, now all
- our inputs are either op_pin_state_pinned or place_early() has already
- been finished on them. We do not have any unfinished inputs! */
+ /* Because all loops contain at least one op_pin_state_pinned node,
+ now all our inputs are either op_pin_state_pinned or
+ place_early() has already been finished on them.
+ We do not have any unfinished inputs! */
pred_block = get_nodes_block(pred);
if ((!is_Block_dead(pred_block)) &&
(get_Block_dom_depth(pred_block) > depth)) {
b = pred_block;
depth = get_Block_dom_depth(pred_block);
}
- /* Avoid that the node is placed in the Start block */
+ /* Avoid that the node is placed in the Start block if we are not
+ in the backend phase. */
if (depth == 1 &&
get_Block_dom_depth(get_nodes_block(n)) > 1 &&
get_irg_phase_state(current_ir_graph) != phase_backend) {
/*
* Add predecessors of non floating nodes and non-floating predecessors
- * of floating nodes to worklist and fix their blocks if the are in dead block.
+ * of floating nodes to worklist and fix their blocks if the are in dead
+ * block.
*/
irn_arity = get_irn_arity(n);
*/
for (i = -1; i < irn_arity; ++i) {
ir_node *pred = get_irn_n(n, i);
- if (irn_not_visited(pred))
+ if (!irn_visited(pred))
waitq_put(worklist, pred);
}
} else if (is_Block(n)) {
*/
for (i = irn_arity - 1; i >= 0; --i) {
ir_node *pred = get_irn_n(n, i);
- if (irn_not_visited(pred))
+ if (!irn_visited(pred))
waitq_put(worklist, pred);
}
} else if (is_Phi(n)) {
* of the Phi-input if the Phi is not in a bad block.
*/
pred = get_nodes_block(n);
- if (irn_not_visited(pred))
+ if (!irn_visited(pred))
waitq_put(worklist, pred);
for (i = irn_arity - 1; i >= 0; --i) {
ir_node *pred = get_irn_n(n, i);
- if (irn_not_visited(pred)) {
+ if (!irn_visited(pred)) {
if (! in_dead_block &&
get_irn_pinned(pred) == op_pin_state_floats &&
is_Block_unreachable(get_nodes_block(pred))) {
* All other nodes: move nodes from dead blocks into the same block.
*/
pred = get_nodes_block(n);
- if (irn_not_visited(pred))
+ if (!irn_visited(pred))
waitq_put(worklist, pred);
for (i = irn_arity - 1; i >= 0; --i) {
ir_node *pred = get_irn_n(n, i);
- if (irn_not_visited(pred)) {
+ if (!irn_visited(pred)) {
if (! in_dead_block &&
get_irn_pinned(pred) == op_pin_state_floats &&
is_Block_unreachable(get_nodes_block(pred))) {
/**
* Floating nodes form subgraphs that begin at nodes as Const, Load,
- * Start, Call and that end at op_pin_state_pinned nodes as Store, Call. Place_early
- * places all floating nodes reachable from its argument through floating
- * nodes and adds all beginnings at op_pin_state_pinned nodes to the worklist.
+ * Start, Call and that end at op_pin_state_pinned nodes as Store, Call.
+ * Place_early places all floating nodes reachable from its argument through
+ * floating nodes and adds all beginnings at op_pin_state_pinned nodes to the
+ * worklist.
*
* @param worklist a worklist, used for the algorithm, empty on in/output
*/
-static void place_early(waitq *worklist) {
+static void place_early(waitq *worklist)
+{
assert(worklist);
inc_irg_visited(current_ir_graph);
/* Work the content of the worklist. */
while (!waitq_empty(worklist)) {
ir_node *n = waitq_get(worklist);
- if (irn_not_visited(n))
+ if (!irn_visited(n))
place_floats_early(n, worklist);
}
-
- set_irg_outs_inconsistent(current_ir_graph);
set_irg_pinned(current_ir_graph, op_pin_state_pinned);
}
/**
- * Compute the deepest common ancestor of block and dca.
+ * Compute the deepest common dominator tree ancestor of block and dca.
+ *
+ * @param dca the deepest common dominator tree ancestor so far,
+ * might be NULL
+ * @param block a block
+ *
+ * @return the deepest common dominator tree ancestor of block and dca
*/
-static ir_node *calc_dca(ir_node *dca, ir_node *block) {
- assert(block);
+static ir_node *calc_dom_dca(ir_node *dca, ir_node *block)
+{
+ assert(block != NULL);
/* we do not want to place nodes in dead blocks */
if (is_Block_dead(block))
while (block != dca) {
block = get_Block_idom(block); dca = get_Block_idom(dca);
}
-
return dca;
}
-/** Deepest common dominance ancestor of DCA and CONSUMER of PRODUCER.
+/**
+ * Deepest common dominance ancestor of DCA and CONSUMER of PRODUCER.
* I.e., DCA is the block where we might place PRODUCER.
* A data flow edge points from producer to consumer.
*/
ir_node *new_block = get_Block_cfgpred_block(phi_block, i);
if (!is_Block_unreachable(new_block))
- dca = calc_dca(dca, new_block);
+ dca = calc_dom_dca(dca, new_block);
}
}
} else {
- dca = calc_dca(dca, get_nodes_block(consumer));
+ dca = calc_dom_dca(dca, get_nodes_block(consumer));
}
-
return dca;
}
-/* FIXME: the name clashes here with the function from ana/field_temperature.c
- * please rename. */
-static INLINE int get_irn_loop_depth(ir_node *n) {
- return get_loop_depth(get_irn_loop(n));
+static inline int get_block_loop_depth(ir_node *block)
+{
+ return get_loop_depth(get_irn_loop(block));
}
/**
* @param n the node that should be moved
* @param early the earliest block we can n move to
*/
-static void move_out_of_loops(ir_node *n, ir_node *early) {
+static void move_out_of_loops(ir_node *n, ir_node *early)
+{
ir_node *best, *dca;
assert(n && early);
while (dca != early) {
dca = get_Block_idom(dca);
if (!dca || is_Bad(dca)) break; /* may be Bad if not reachable from Start */
- if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
+ if (get_block_loop_depth(dca) < get_block_loop_depth(best)) {
best = dca;
}
}
- if (best != get_nodes_block(n)) {
- /* debug output
- printf("Moving out of loop: "); DDMN(n);
- printf(" Outermost block: "); DDMN(early);
- printf(" Best block: "); DDMN(best);
- printf(" Innermost block: "); DDMN(get_nodes_block(n));
- */
+ if (best != get_nodes_block(n))
set_nodes_block(n, best);
- }
}
-/* deepest common ancestor in the dominator tree of all nodes'
- blocks depending on us; our final placement has to dominate DCA. */
-static ir_node *get_deepest_common_ancestor(ir_node *node, ir_node *dca)
+/**
+ * Calculate the deepest common ancestor in the dominator tree of all nodes'
+ * blocks depending on node; our final placement has to dominate DCA.
+ *
+ * @param node the definition node
+ * @param dca the deepest common ancestor block so far, initially
+ * NULL
+ *
+ * @return the deepest common dominator ancestor of all blocks of node's users
+ */
+static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca)
{
int i;
}
if (is_Proj(succ)) {
- dca = get_deepest_common_ancestor(succ, dca);
+ /* Proj nodes are in the same block as node, so
+ * the users of Proj are our users. */
+ dca = get_deepest_common_dom_ancestor(succ, dca);
} else {
/* ignore if succ is in dead code */
ir_node *succ_blk = get_nodes_block(succ);
dca = consumer_dom_dca(dca, succ, node);
}
}
-
return dca;
}
+/**
+ * Put all the Proj nodes of a node into a given block.
+ *
+ * @param node the mode_T node
+ * @param block the block to put the Proj nodes to
+ */
static void set_projs_block(ir_node *node, ir_node *block)
{
int i;
assert(is_Proj(succ));
- if(get_irn_mode(succ) == mode_T) {
+ if (get_irn_mode(succ) == mode_T) {
set_projs_block(succ, block);
}
set_nodes_block(succ, block);
* @param worklist a worklist, all successors of non-floating nodes are
* placed here
*/
-static void place_floats_late(ir_node *n, pdeq *worklist) {
+static void place_floats_late(ir_node *n, pdeq *worklist)
+{
int i, n_outs;
ir_node *early_blk;
- assert(irn_not_visited(n)); /* no multiple placement */
+ assert(!irn_visited(n)); /* no multiple placement */
mark_irn_visited(n);
producer of one of their inputs in the same block anyway. */
for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
ir_node *succ = get_irn_out(n, i);
- if (irn_not_visited(succ) && !is_Phi(succ))
+ if (!irn_visited(succ) && !is_Phi(succ))
place_floats_late(succ, worklist);
}
/* deepest common ancestor in the dominator tree of all nodes'
blocks depending on us; our final placement has to dominate
DCA. */
- ir_node *dca = get_deepest_common_ancestor(n, NULL);
+ ir_node *dca = get_deepest_common_dom_ancestor(n, NULL);
if (dca != NULL) {
set_nodes_block(n, dca);
move_out_of_loops(n, early_blk);
n_outs = get_irn_n_outs(n);
for (i = 0; i < n_outs; i++) {
ir_node *succ = get_irn_out(n, i);
- if (irn_not_visited(get_irn_out(n, i))) {
+ if (!irn_visited(succ)) {
pdeq_putr(worklist, succ);
}
}
*
* @param worklist the worklist containing the nodes to place
*/
-static void place_late(waitq *worklist) {
+static void place_late(waitq *worklist)
+{
assert(worklist);
inc_irg_visited(current_ir_graph);
/* And now empty the worklist again... */
while (!waitq_empty(worklist)) {
ir_node *n = waitq_get(worklist);
- if (irn_not_visited(n))
+ if (!irn_visited(n))
place_floats_late(n, worklist);
}
}
/* Code Placement. */
-void place_code(ir_graph *irg) {
+void place_code(ir_graph *irg)
+{
waitq *worklist;
ir_graph *rem = current_ir_graph;
current_ir_graph = irg;
+ remove_critical_cf_edges(irg);
/* Handle graph state */
assert(get_irg_phase_state(irg) != phase_building);
+ assure_irg_outs(irg);
assure_doms(irg);
if (1 || get_irg_loopinfo_state(irg) != loopinfo_consistent) {
worklist = new_waitq();
place_early(worklist);
- /* place_early() invalidates the outs, place_late needs them. */
- compute_irg_outs(irg);
+ /* Note: place_early changes only blocks, no data edges. So, the
+ * data out edges are still valid, no need to recalculate them here. */
/* Now move the nodes down in the dominator tree. This reduces the
unnecessary executions of the node. */
place_late(worklist);
- set_irg_outs_inconsistent(current_ir_graph);
- set_irg_loopinfo_inconsistent(current_ir_graph);
+ set_irg_outs_inconsistent(irg);
+ set_irg_loopinfo_inconsistent(irg);
del_waitq(worklist);
current_ir_graph = rem;
}
+
+/**
+ * Wrapper for place_code() inside the place_code pass.
+ */
+static void place_code_wrapper(ir_graph *irg)
+{
+ set_opt_global_cse(1);
+ optimize_graph_df(irg);
+ place_code(irg);
+ set_opt_global_cse(0);
+}
+
+ir_graph_pass_t *place_code_pass(const char *name)
+{
+ return def_graph_pass(name ? name : "place", place_code_wrapper);
+}