# include <config.h>
#endif
-# include <assert.h>
-# include <stdbool.h>
-
-# include "irprog.h"
-# include "irgopt.h"
-# include "irnode_t.h"
-# include "irgraph_t.h"
-# include "iropt_t.h"
-# include "irgwalk.h"
-# include "ircons.h"
-# include "irgmod.h"
-# include "array.h"
-# include "pset.h"
-# include "eset.h"
-# include "pdeq.h" /* Fuer code placement */
-# include "irouts.h"
-# include "irloop.h"
-# include "irbackedge_t.h"
-# include "irflag_t.h"
-# include "firmstat.h"
+#include <assert.h>
+#include <stdbool.h>
+
+#include "irnode_t.h"
+#include "irgraph_t.h"
+#include "irprog_t.h"
+
+#include "ircons.h"
+#include "iropt_t.h"
+#include "irgopt.h"
+#include "irgmod.h"
+#include "irgwalk.h"
+
+#include "array.h"
+#include "pset.h"
+#include "eset.h"
+#include "pdeq.h" /* Fuer code placement */
+
+#include "irouts.h"
+#include "irloop_t.h"
+#include "irbackedge_t.h"
+#include "cgana.h"
+
+#include "irflag_t.h"
+#include "firmstat.h"
/* Defined in iropt.c */
pset *new_identities (void);
int i, irn_arity;
ir_node *optimized, *old;
- irn_arity = intern_get_irn_arity(n);
+ irn_arity = get_irn_arity(n);
for (i = 0; i < irn_arity; i++) {
/* get_irn_n skips Id nodes, so comparison old != optimized does not
show all optimizations. Therefore always set new predecessor. */
- old = intern_get_irn_intra_n(n, i);
+ old = get_irn_intra_n(n, i);
optimized = optimize_in_place_2(old);
set_irn_n(n, i, optimized);
}
- if (intern_get_irn_op(n) == op_Block) {
+ if (get_irn_op(n) == op_Block) {
optimized = optimize_in_place_2(n);
if (optimized != n) exchange (n, optimized);
}
#endif
-
-void
-local_optimize_graph (ir_graph *irg) {
- ir_graph *rem = current_ir_graph;
- current_ir_graph = irg;
-
+static INLINE void do_local_optimize(ir_node *n) {
/* Handle graph state */
- assert(get_irg_phase_state(irg) != phase_building);
+ assert(get_irg_phase_state(current_ir_graph) != phase_building);
if (get_opt_global_cse())
- set_irg_pinned(current_ir_graph, floats);
+ set_irg_pinned(current_ir_graph, op_pin_state_floats);
if (get_irg_outs_state(current_ir_graph) == outs_consistent)
set_irg_outs_inconsistent(current_ir_graph);
if (get_irg_dom_state(current_ir_graph) == dom_consistent)
set_irg_dom_inconsistent(current_ir_graph);
+ set_irg_loopinfo_inconsistent(current_ir_graph);
+
/* Clean the value_table in irg for the cse. */
- del_identities(irg->value_table);
- irg->value_table = new_identities();
+ del_identities(current_ir_graph->value_table);
+ current_ir_graph->value_table = new_identities();
/* walk over the graph */
- irg_walk(irg->end, init_link, optimize_in_place_wrapper, NULL);
+ irg_walk(n, init_link, optimize_in_place_wrapper, NULL);
+}
+
+void local_optimize_node(ir_node *n) {
+ ir_graph *rem = current_ir_graph;
+ current_ir_graph = get_irn_irg(n);
+
+ do_local_optimize(n);
+
+ current_ir_graph = rem;
+
+}
+
+void
+local_optimize_graph (ir_graph *irg) {
+ ir_graph *rem = current_ir_graph;
+ current_ir_graph = irg;
+
+ do_local_optimize(irg->end);
current_ir_graph = rem;
}
+
/*------------------------------------------------------------------*/
/* Routines for dead node elimination / copying garbage collection */
/* of the obstack. */
return block_v - irg_v;
} else {
/* compute the number of good predecessors */
- res = irn_arity = intern_get_irn_arity(b);
+ res = irn_arity = get_irn_arity(b);
for (i = 0; i < irn_arity; i++)
- if (intern_get_irn_opcode(intern_get_irn_n(b, i)) == iro_Bad) res--;
+ if (get_irn_opcode(get_irn_n(b, i)) == iro_Bad) res--;
/* save it in the flag. */
set_Block_block_visited(b, irg_v + res);
return res;
/* TODO: add an ir_op operation */
static INLINE void new_backedge_info(ir_node *n) {
- switch(intern_get_irn_opcode(n)) {
+ switch(get_irn_opcode(n)) {
case iro_Block:
n->attr.block.cg_backedge = NULL;
- n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, intern_get_irn_arity(n));
+ n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
break;
case iro_Phi:
- n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, intern_get_irn_arity(n));
+ n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
break;
case iro_Filter:
- n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, intern_get_irn_arity(n));
+ n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
break;
default: ;
}
copy_node (ir_node *n, void *env) {
ir_node *nn, *block;
int new_arity;
-
+ opcode op = get_irn_opcode(n);
/* The end node looses it's flexible in array. This doesn't matter,
as dead node elimination builds End by hand, inlineing doesn't use
the End node. */
/* assert(n->op == op_End || ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC)); */
- if (intern_get_irn_opcode(n) == iro_Block) {
+ if (op == iro_Bad) {
+ /* node copied already */
+ return;
+ } else if (op == iro_Block) {
block = NULL;
new_arity = compute_new_arity(n);
n->attr.block.graph_arr = NULL;
} else {
- block = get_nodes_Block(n);
- if (intern_get_irn_opcode(n) == iro_Phi) {
+ block = get_nodes_block(n);
+ if (get_irn_opcode(n) == iro_Phi) {
new_arity = compute_new_arity(block);
} else {
- new_arity = intern_get_irn_arity(n);
+ new_arity = get_irn_arity(n);
}
}
nn = new_ir_node(get_irn_dbg_info(n),
current_ir_graph,
block,
- intern_get_irn_op(n),
- intern_get_irn_mode(n),
+ get_irn_op(n),
+ get_irn_mode(n),
new_arity,
get_irn_in(n));
/* Copy the attributes. These might point to additional data. If this
/* printf("\n old node: "); DDMSG2(n);
printf(" new node: "); DDMSG2(nn);
- printf(" arities: old: %d, new: %d\n", intern_get_irn_arity(n), intern_get_irn_arity(nn)); */
+ printf(" arities: old: %d, new: %d\n", get_irn_arity(n), get_irn_arity(nn)); */
- if (intern_get_irn_opcode(n) == iro_Block) {
+ if (get_irn_opcode(n) == iro_Block) {
/* Don't copy Bad nodes. */
j = 0;
- irn_arity = intern_get_irn_arity(n);
+ irn_arity = get_irn_arity(n);
for (i = 0; i < irn_arity; i++)
- if (intern_get_irn_opcode(intern_get_irn_n(n, i)) != iro_Bad) {
- set_irn_n (nn, j, get_new_node(intern_get_irn_n(n, i)));
+ if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
+ set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
/*if (is_backedge(n, i)) set_backedge(nn, j);*/
j++;
}
that the fields in ir_graph are set properly. */
if ((get_opt_control_flow_straightening()) &&
(get_Block_n_cfgpreds(nn) == 1) &&
- (intern_get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp))
- exchange(nn, get_nodes_Block(get_Block_cfgpred(nn, 0)));
- } else if (intern_get_irn_opcode(n) == iro_Phi) {
+ (get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)) {
+ ir_node *old = get_nodes_block(get_Block_cfgpred(nn, 0));
+ if (nn == old) {
+ /* Jmp jumps into the block it is in -- deal self cycle. */
+ assert(is_Bad(get_new_node(get_irg_bad(current_ir_graph))));
+ exchange(nn, get_new_node(get_irg_bad(current_ir_graph)));
+ } else {
+ exchange(nn, old);
+ }
+ }
+ } else if (get_irn_opcode(n) == iro_Phi) {
/* Don't copy node if corresponding predecessor in block is Bad.
The Block itself should not be Bad. */
- block = get_nodes_Block(n);
+ block = get_nodes_block(n);
set_irn_n (nn, -1, get_new_node(block));
j = 0;
- irn_arity = intern_get_irn_arity(n);
+ irn_arity = get_irn_arity(n);
for (i = 0; i < irn_arity; i++)
- if (intern_get_irn_opcode(intern_get_irn_n(block, i)) != iro_Bad) {
- set_irn_n (nn, j, get_new_node(intern_get_irn_n(n, i)));
+ if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
+ set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
/*if (is_backedge(n, i)) set_backedge(nn, j);*/
j++;
}
/* If the pre walker reached this Phi after the post walker visited the
block block_visited is > 0. */
- set_Block_block_visited(get_nodes_Block(n), 0);
+ set_Block_block_visited(get_nodes_block(n), 0);
/* Compacting the Phi's ins might generate Phis with only one
predecessor. */
- if (intern_get_irn_arity(n) == 1)
- exchange(n, intern_get_irn_n(n, 0));
+ if (get_irn_arity(n) == 1)
+ exchange(n, get_irn_n(n, 0));
} else {
- irn_arity = intern_get_irn_arity(n);
+ irn_arity = get_irn_arity(n);
for (i = -1; i < irn_arity; i++)
- set_irn_n (nn, i, get_new_node(intern_get_irn_n(n, i)));
+ set_irn_n (nn, i, get_new_node(get_irn_n(n, i)));
}
/* Now the new node is complete. We can add it to the hash table for cse.
@@@ inlinening aborts if we identify End. Why? */
- if(intern_get_irn_op(nn) != op_End)
+ if(get_irn_op(nn) != op_End)
add_identities (current_ir_graph->value_table, nn);
}
*/
static void
copy_graph (void) {
- ir_node *oe, *ne; /* old end, new end */
+ ir_node *oe, *ne, *ob, *nb; /* old end, new end, old bad, new bad */
ir_node *ka; /* keep alive */
int i, irn_arity;
copy_attrs(oe, ne);
set_new_node(oe, ne);
+ ob = get_irg_bad(current_ir_graph);
+ nb = new_ir_node(get_irn_dbg_info(ob),
+ current_ir_graph,
+ NULL,
+ op_Bad,
+ mode_T,
+ 0,
+ NULL);
+ set_new_node(ob, nb);
+
/* copy the live nodes */
- irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
+ irg_walk(get_nodes_block(oe), copy_node, copy_preds, NULL);
/* copy_preds for the end node ... */
- set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
+ set_nodes_block(ne, get_new_node(get_nodes_block(oe)));
+ set_nodes_block(nb, get_new_node(get_nodes_block(ob)));
/*- ... and now the keep alives. -*/
/* First pick the not marked block nodes and walk them. We must pick these
first as else we will oversee blocks reachable from Phis. */
- irn_arity = intern_get_irn_arity(oe);
+ irn_arity = get_irn_arity(oe);
for (i = 0; i < irn_arity; i++) {
- ka = intern_get_irn_intra_n(oe, i);
- if ((intern_get_irn_op(ka) == op_Block) &&
+ ka = get_irn_intra_n(oe, i);
+ if ((get_irn_op(ka) == op_Block) &&
(get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
/* We must keep the block alive and copy everything reachable */
set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
}
/* Now pick the Phis. Here we will keep all! */
- irn_arity = intern_get_irn_arity(oe);
+ irn_arity = get_irn_arity(oe);
for (i = 0; i < irn_arity; i++) {
- ka = intern_get_irn_intra_n(oe, i);
- if ((intern_get_irn_op(ka) == op_Phi)) {
+ ka = get_irn_intra_n(oe, i);
+ if ((get_irn_op(ka) == op_Phi)) {
if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
/* We didn't copy the Phi yet. */
set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
/* Not all nodes remembered in current_ir_graph might be reachable
from the end node. Assure their link is set to NULL, so that
we can test whether new nodes have been computed. */
- set_irn_link(get_irg_frame (current_ir_graph), NULL);
- set_irn_link(get_irg_globals(current_ir_graph), NULL);
- set_irn_link(get_irg_args (current_ir_graph), NULL);
+ set_irn_link(get_irg_frame (current_ir_graph), NULL);
+ set_irn_link(get_irg_globals (current_ir_graph), NULL);
+ set_irn_link(get_irg_args (current_ir_graph), NULL);
+ set_irn_link(get_irg_initial_mem(current_ir_graph), NULL);
/* we use the block walk flag for removing Bads from Blocks ins. */
inc_irg_block_visited(current_ir_graph);
/* fix the fields in current_ir_graph */
old_end = get_irg_end(current_ir_graph);
- set_irg_end (current_ir_graph, get_new_node(old_end));
+ set_irg_end (current_ir_graph, get_new_node(old_end));
set_irg_end_except (current_ir_graph, get_irg_end(current_ir_graph));
set_irg_end_reg (current_ir_graph, get_irg_end(current_ir_graph));
free_End(old_end);
copy_node (get_irg_globals(current_ir_graph), NULL);
copy_preds(get_irg_globals(current_ir_graph), NULL);
}
+ if (get_irn_link(get_irg_initial_mem(current_ir_graph)) == NULL) {
+ copy_node (get_irg_initial_mem(current_ir_graph), NULL);
+ copy_preds(get_irg_initial_mem(current_ir_graph), NULL);
+ }
if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
copy_node (get_irg_args(current_ir_graph), NULL);
copy_preds(get_irg_args(current_ir_graph), NULL);
}
- set_irg_start (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
+ set_irg_start (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
set_irg_start_block(current_ir_graph,
get_new_node(get_irg_start_block(current_ir_graph)));
- set_irg_frame (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
- set_irg_globals(current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
- set_irg_args (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
+ set_irg_frame (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
+ set_irg_globals (current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
+ set_irg_initial_mem(current_ir_graph, get_new_node(get_irg_initial_mem(current_ir_graph)));
+ set_irg_args (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
+
if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
copy_node(get_irg_bad(current_ir_graph), NULL);
copy_preds(get_irg_bad(current_ir_graph), NULL);
}
set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
- /* GL removed: we need unknown with mode for analyses.
- if (get_irn_link(get_irg_unknown(current_ir_graph)) == NULL) {
- copy_node(get_irg_unknown(current_ir_graph), NULL);
- copy_preds(get_irg_unknown(current_ir_graph), NULL);
- }
- set_irg_unknown(current_ir_graph, get_new_node(get_irg_unknown(current_ir_graph)));
- */
}
/**
* Adds all new nodes to a new hash table for cse. Does not
* perform cse, so the hash table might contain common subexpressions.
*/
-/* Amroq call this emigrate() */
void
dead_node_elimination(ir_graph *irg) {
ir_graph *rem;
struct obstack *graveyard_obst = NULL;
struct obstack *rebirth_obst = NULL;
+ /* inform statistics that we started a dead-node elimination run */
stat_dead_node_elim_start(irg);
/* Remember external state of current_ir_graph. */
/* Handle graph state */
assert(get_irg_phase_state(current_ir_graph) != phase_building);
- assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
+ free_callee_info(current_ir_graph);
free_outs(current_ir_graph);
-
/* @@@ so far we loose loops when copying */
free_loop_information(current_ir_graph);
xfree (graveyard_obst); /* ... then free it. */
}
+ /* inform statistics that the run is over */
stat_dead_node_elim_stop(irg);
current_ir_graph = rem;
/* if link field of block is NULL, look for bad predecessors otherwise
this is allready done */
- if (intern_get_irn_op(n) == op_Block &&
+ if (get_irn_op(n) == op_Block &&
get_irn_link(n) == NULL) {
/* save old predecessors in link field (position 0 is the block operand)*/
set_irn_link(n, (void *)get_irn_in(n));
/* count predecessors without bad nodes */
- old_irn_arity = intern_get_irn_arity(n);
+ old_irn_arity = get_irn_arity(n);
for (i = 0; i < old_irn_arity; i++)
- if (!is_Bad(intern_get_irn_n(n, i))) new_irn_arity++;
+ if (!is_Bad(get_irn_n(n, i))) new_irn_arity++;
/* arity changing: set new predecessors without bad nodes */
if (new_irn_arity < old_irn_arity) {
new_in[0] = NULL;
new_irn_n = 1;
for (i = 1; i < old_irn_arity; i++) {
- irn = intern_get_irn_n(n, i);
+ irn = get_irn_n(n, i);
if (!is_Bad(irn)) new_in[new_irn_n++] = irn;
}
n->in = new_in;
} /* Block is not relinked */
}
-/**
+/*
* Relinks Bad predecesors from Bocks and Phis called by walker
* remove_bad_predecesors(). If n is a Block, call
* relink_bad_block_redecessors(). If n is a Phinode, call also the relinking
int i, old_irn_arity, new_irn_arity;
/* relink bad predeseccors of a block */
- if (intern_get_irn_op(n) == op_Block)
+ if (get_irn_op(n) == op_Block)
relink_bad_block_predecessors(n, env);
/* If Phi node relink its block and its predecessors */
- if (intern_get_irn_op(n) == op_Phi) {
+ if (get_irn_op(n) == op_Phi) {
/* Relink predeseccors of phi's block */
- block = get_nodes_Block(n);
+ block = get_nodes_block(n);
if (get_irn_link(block) == NULL)
relink_bad_block_predecessors(block, env);
type *frame_tp = (type *)env;
copy_node(n, NULL);
- if (intern_get_irn_op(n) == op_Sel) {
+ if (get_irn_op(n) == op_Sel) {
new = get_new_node (n);
- assert(intern_get_irn_op(new) == op_Sel);
+ assert(get_irn_op(new) == op_Sel);
if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
}
- } else if (intern_get_irn_op(n) == op_Block) {
+ } else if (get_irn_op(n) == op_Block) {
new = get_new_node (n);
new->attr.block.irg = current_ir_graph;
}
{
type *call_type = get_Call_type(call);
int params, ress, i, res;
-
assert(is_method_type(call_type));
params = get_method_n_params(call_type);
return res;
}
-void inline_method(ir_node *call, ir_graph *called_graph) {
+int inline_method(ir_node *call, ir_graph *called_graph) {
ir_node *pre_call;
ir_node *post_call, *post_bl;
ir_node *in[5];
type *called_frame;
irg_inline_property prop = get_irg_inline_property(called_graph);
- if ( (prop != irg_inline_forced) && (!get_opt_optimize() || !get_opt_inline() ||
- (prop == irg_inline_forbidden))) return;
+ if ( (prop != irg_inline_forced) &&
+ (!get_opt_optimize() || !get_opt_inline() || (prop == irg_inline_forbidden))) return 0;
/*
* - graphs that take the address of a parameter
*/
if (! can_inline(call, called_graph))
- return;
+ return 0;
/* -- Turn off optimizations, this can cause problems when allocating new nodes. -- */
rem_opt = get_opt_optimize();
/* Handle graph state */
assert(get_irg_phase_state(current_ir_graph) != phase_building);
- assert(get_irg_pinned(current_ir_graph) == pinned);
- assert(get_irg_pinned(called_graph) == pinned);
+ assert(get_irg_pinned(current_ir_graph) == op_pin_state_pinned);
+ assert(get_irg_pinned(called_graph) == op_pin_state_pinned);
if (get_irg_outs_state(current_ir_graph) == outs_consistent)
set_irg_outs_inconsistent(current_ir_graph);
+ set_irg_loopinfo_inconsistent(current_ir_graph);
/* -- Check preconditions -- */
assert(get_irn_op(call) == op_Call);
/* @@@ does not work for InterfaceIII.java after cgana
- assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
- assert(smaller_type(get_entity_type(get_irg_ent(called_graph)),
+ assert(get_Call_type(call) == get_entity_type(get_irg_entity(called_graph)));
+ assert(smaller_type(get_entity_type(get_irg_entity(called_graph)),
get_Call_type(call)));
*/
assert(get_type_tpop(get_Call_type(call)) == type_method);
if (called_graph == current_ir_graph) {
set_optimize(rem_opt);
- return;
+ return 0;
}
/* here we know we WILL inline, so inform the statistics */
/* -- Decide how to handle exception control flow: Is there a handler
for the Call node, or do we branch directly to End on an exception?
exc_handling: 0 There is a handler.
- 1 Branches to End.
- 2 Exception handling not represented in Firm. -- */
+ 1 Branches to End.
+ 2 Exception handling not represented in Firm. -- */
{
ir_node *proj, *Mproj = NULL, *Xproj = NULL;
for (proj = (ir_node *)get_irn_link(call); proj; proj = (ir_node *)get_irn_link(proj)) {
/* --
- the procedure and later replaces the Start node of the called graph.
- Post_call is the old Call node and collects the results of the called
- graph. Both will end up being a tuple. -- */
- post_bl = get_nodes_Block(call);
+ the procedure and later replaces the Start node of the called graph.
+ Post_call is the old Call node and collects the results of the called
+ graph. Both will end up being a tuple. -- */
+ post_bl = get_nodes_block(call);
set_irg_current_block(current_ir_graph, post_bl);
/* XxMxPxP of Start + parameter of Call */
in[pn_Start_X_initial_exec] = new_Jmp();
post_call = call;
/* --
- The new block gets the ins of the old block, pre_call and all its
- predecessors and all Phi nodes. -- */
+ The new block gets the ins of the old block, pre_call and all its
+ predecessors and all Phi nodes. -- */
part_block(pre_call);
/* -- Prepare state for dead node elimination -- */
Further mark these nodes so that they are not visited by the
copying. */
set_irn_link(get_irg_start(called_graph), pre_call);
- set_irn_visited(get_irg_start(called_graph),
- get_irg_visited(current_ir_graph));
- set_irn_link(get_irg_start_block(called_graph),
- get_nodes_Block(pre_call));
- set_irn_visited(get_irg_start_block(called_graph),
- get_irg_visited(current_ir_graph));
+ set_irn_visited(get_irg_start(called_graph), get_irg_visited(current_ir_graph));
+ set_irn_link(get_irg_start_block(called_graph), get_nodes_block(pre_call));
+ set_irn_visited(get_irg_start_block(called_graph), get_irg_visited(current_ir_graph));
+ set_irn_link(get_irg_bad(called_graph), get_irg_bad(current_ir_graph));
+ set_irn_visited(get_irg_bad(called_graph), get_irg_visited(current_ir_graph));
/* Initialize for compaction of in arrays */
inc_irg_block_visited(current_ir_graph);
entities. */
/* @@@ endless loops are not copied!! -- they should be, I think... */
irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
- get_irg_frame_type(called_graph));
+ get_irg_frame_type(called_graph));
/* Repair called_graph */
set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
/* -- Merge the end of the inlined procedure with the call site -- */
/* We will turn the old Call node into a Tuple with the following
predecessors:
- -1: Block of Tuple.
- 0: Phi of all Memories of Return statements.
- 1: Jmp from new Block that merges the control flow from all exception
- predecessors of the old end block.
- 2: Tuple of all arguments.
- 3: Phi of Exception memories.
+ -1: Block of Tuple.
+ 0: Phi of all Memories of Return statements.
+ 1: Jmp from new Block that merges the control flow from all exception
+ predecessors of the old end block.
+ 2: Tuple of all arguments.
+ 3: Phi of Exception memories.
In case the old Call directly branches to End on an exception we don't
need the block merging all exceptions nor the Phi of the exception
memories.
/* -- Precompute some values -- */
end_bl = get_new_node(get_irg_end_block(called_graph));
end = get_new_node(get_irg_end(called_graph));
- arity = intern_get_irn_arity(end_bl); /* arity = n_exc + n_ret */
+ arity = get_irn_arity(end_bl); /* arity = n_exc + n_ret */
n_res = get_method_n_ress(get_Call_type(call));
res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
/* -- archive keepalives -- */
- irn_arity = intern_get_irn_arity(end);
+ irn_arity = get_irn_arity(end);
for (i = 0; i < irn_arity; i++)
- add_End_keepalive(get_irg_end(current_ir_graph), intern_get_irn_n(end, i));
+ add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
/* The new end node will die. We need not free as the in array is on the obstack:
copy_node only generated 'D' arrays. */
n_ret = 0;
for (i = 0; i < arity; i++) {
ir_node *ret;
- ret = intern_get_irn_n(end_bl, i);
- if (intern_get_irn_op(ret) == op_Return) {
- cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
+ ret = get_irn_n(end_bl, i);
+ if (get_irn_op(ret) == op_Return) {
+ cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_block(ret));
n_ret++;
}
}
/* First the Memory-Phi */
n_ret = 0;
for (i = 0; i < arity; i++) {
- ret = intern_get_irn_n(end_bl, i);
- if (intern_get_irn_op(ret) == op_Return) {
+ ret = get_irn_n(end_bl, i);
+ if (get_irn_op(ret) == op_Return) {
cf_pred[n_ret] = get_Return_mem(ret);
n_ret++;
}
phi = new_Phi(n_ret, cf_pred, mode_M);
set_Tuple_pred(call, pn_Call_M_regular, phi);
/* Conserve Phi-list for further inlinings -- but might be optimized */
- if (get_nodes_Block(phi) == post_bl) {
+ if (get_nodes_block(phi) == post_bl) {
set_irn_link(phi, get_irn_link(post_bl));
set_irn_link(post_bl, phi);
}
for (j = 0; j < n_res; j++) {
n_ret = 0;
for (i = 0; i < arity; i++) {
- ret = intern_get_irn_n(end_bl, i);
- if (intern_get_irn_op(ret) == op_Return) {
- cf_pred[n_ret] = get_Return_res(ret, j);
- n_ret++;
- }
+ ret = get_irn_n(end_bl, i);
+ if (get_irn_op(ret) == op_Return) {
+ cf_pred[n_ret] = get_Return_res(ret, j);
+ n_ret++;
+ }
}
- phi = new_Phi(n_ret, cf_pred, intern_get_irn_mode(cf_pred[0]));
+ if (n_ret > 0)
+ phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
+ else
+ phi = new_Bad();
res_pred[j] = phi;
/* Conserve Phi-list for further inlinings -- but might be optimized */
- if (get_nodes_Block(phi) == post_bl) {
- set_irn_link(phi, get_irn_link(post_bl));
- set_irn_link(post_bl, phi);
+ if (get_nodes_block(phi) == post_bl) {
+ set_irn_link(phi, get_irn_link(post_bl));
+ set_irn_link(post_bl, phi);
}
}
set_Tuple_pred(call, pn_Call_T_result, new_Tuple(n_res, res_pred));
n_exc = 0;
for (i = 0; i < arity; i++) {
ir_node *ret;
- ret = intern_get_irn_n(end_bl, i);
- if (is_fragile_op(skip_Proj(ret)) || (intern_get_irn_op(skip_Proj(ret)) == op_Raise)) {
- cf_pred[n_exc] = ret;
- n_exc++;
+ ret = get_irn_n(end_bl, i);
+ if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
+ cf_pred[n_exc] = ret;
+ n_exc++;
}
}
if (n_exc > 0) {
/* The Phi for the memories with the exception objects */
n_exc = 0;
for (i = 0; i < arity; i++) {
- ir_node *ret;
- ret = skip_Proj(intern_get_irn_n(end_bl, i));
- if (intern_get_irn_op(ret) == op_Call) {
- cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
- n_exc++;
- } else if (is_fragile_op(ret)) {
- /* We rely that all cfops have the memory output at the same position. */
- cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
- n_exc++;
- } else if (intern_get_irn_op(ret) == op_Raise) {
- cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
- n_exc++;
- }
+ ir_node *ret;
+ ret = skip_Proj(get_irn_n(end_bl, i));
+ if (get_irn_op(ret) == op_Call) {
+ cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_block(ret), ret, mode_M, 3);
+ n_exc++;
+ } else if (is_fragile_op(ret)) {
+ /* We rely that all cfops have the memory output at the same position. */
+ cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_block(ret), ret, mode_M, 0);
+ n_exc++;
+ } else if (get_irn_op(ret) == op_Raise) {
+ cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_block(ret), ret, mode_M, 1);
+ n_exc++;
+ }
}
set_Tuple_pred(call, pn_Call_M_except, new_Phi(n_exc, cf_pred, mode_M));
} else {
/* assert(exc_handling == 1 || no exceptions. ) */
n_exc = 0;
for (i = 0; i < arity; i++) {
- ir_node *ret = intern_get_irn_n(end_bl, i);
+ ir_node *ret = get_irn_n(end_bl, i);
- if (is_fragile_op(skip_Proj(ret)) || (intern_get_irn_op(skip_Proj(ret)) == op_Raise)) {
+ if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
cf_pred[n_exc] = ret;
n_exc++;
}
}
main_end_bl = get_irg_end_block(current_ir_graph);
- main_end_bl_arity = intern_get_irn_arity(main_end_bl);
+ main_end_bl_arity = get_irn_arity(main_end_bl);
end_preds = (ir_node **) malloc ((n_exc + main_end_bl_arity) * sizeof (ir_node *));
for (i = 0; i < main_end_bl_arity; ++i)
- end_preds[i] = intern_get_irn_n(main_end_bl, i);
+ end_preds[i] = get_irn_n(main_end_bl, i);
for (i = 0; i < n_exc; ++i)
end_preds[main_end_bl_arity + i] = cf_pred[i];
set_irn_in(main_end_bl, n_exc + main_end_bl_arity, end_preds);
end_bl = get_irg_end_block(current_ir_graph);
for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
cf_op = get_Block_cfgpred(end_bl, i);
- if (intern_get_irn_op(cf_op) == op_Proj) {
- cf_op = get_Proj_pred(cf_op);
- if ((intern_get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
- /* There are unoptimized tuples from inlineing before when no exc */
- assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
- cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
- assert(intern_get_irn_op(cf_op) == op_Jmp);
- break;
- }
+ if (get_irn_op(cf_op) == op_Proj) {
+ cf_op = get_Proj_pred(cf_op);
+ if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
+ /* There are unoptimized tuples from inlineing before when no exc */
+ assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
+ cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
+ assert(get_irn_op(cf_op) == op_Jmp);
+ break;
+ }
}
}
/* repair */
if (i < get_Block_n_cfgpreds(end_bl)) {
- bl = get_nodes_Block(cf_op);
+ bl = get_nodes_block(cf_op);
arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
for (j = 0; j < i; j++)
- cf_pred[j] = get_Block_cfgpred(end_bl, j);
+ cf_pred[j] = get_Block_cfgpred(end_bl, j);
for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
- cf_pred[j] = get_Block_cfgpred(bl, j-i);
+ cf_pred[j] = get_Block_cfgpred(bl, j-i);
for (j = j; j < arity; j++)
- cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
+ cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
set_irn_in(end_bl, arity, cf_pred);
free(cf_pred);
/* Remove the exception pred from post-call Tuple. */
/* -- Turn cse back on. -- */
set_optimize(rem_opt);
+
+ return 1;
}
/********************************************************************/
*/
static ir_graph *get_call_called_irg(ir_node *call) {
ir_node *addr;
- tarval *tv;
ir_graph *called_irg = NULL;
assert(get_irn_op(call) == op_Call);
addr = get_Call_ptr(call);
- if (intern_get_irn_op(addr) == op_Const) {
- /* Check whether the constant is the pointer to a compiled entity. */
- tv = get_Const_tarval(addr);
- if (tarval_to_entity(tv))
- called_irg = get_entity_irg(tarval_to_entity(tv));
+ if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind (addr) == symconst_addr_ent)) {
+ called_irg = get_entity_irg(get_SymConst_entity(addr));
}
+
return called_irg;
}
static void collect_calls(ir_node *call, void *env) {
- inline_env_t *ienv = env;
ir_node *addr;
- tarval *tv;
- ir_graph *called_irg;
- if (intern_get_irn_op(call) != op_Call) return;
+ if (get_irn_op(call) != op_Call) return;
addr = get_Call_ptr(call);
- if (intern_get_irn_op(addr) == op_Const) {
- /* Check whether the constant is the pointer to a compiled entity. */
- tv = get_Const_tarval(addr);
- if (tarval_to_entity(tv)) {
- called_irg = get_entity_irg(tarval_to_entity(tv));
+
+ if (get_irn_op(addr) == op_SymConst) {
+ if (get_SymConst_kind(addr) == symconst_addr_ent) {
+ ir_graph *called_irg = get_entity_irg(get_SymConst_entity(addr));
+ inline_env_t *ienv = (inline_env_t *)env;
if (called_irg && ienv->pos < MAX_INLINE) {
- /* The Call node calls a locally defined method. Remember to inline. */
- ienv->calls[ienv->pos++] = call;
+ /* The Call node calls a locally defined method. Remember to inline. */
+ ienv->calls[ienv->pos++] = call;
}
}
}
void inline_small_irgs(ir_graph *irg, int size) {
int i;
ir_graph *rem = current_ir_graph;
- inline_env_t env;
+ inline_env_t env /* = {0, NULL}*/;
if (!(get_opt_optimize() && get_opt_inline())) return;
current_ir_graph = irg;
/* Handle graph state */
assert(get_irg_phase_state(current_ir_graph) != phase_building);
- assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
+ free_callee_info(current_ir_graph);
/* Find Call nodes to inline.
(We can not inline during a walk of the graph, as inlineing the same
/* There are calls to inline */
collect_phiprojs(irg);
for (i = 0; i < env.pos; i++) {
- tarval *tv;
ir_graph *callee;
- tv = get_Const_tarval(get_Call_ptr(env.calls[i]));
- callee = get_entity_irg(tarval_to_entity(tv));
+ callee = get_entity_irg(get_SymConst_entity(get_Call_ptr(env.calls[i])));
if (((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) ||
- (get_irg_inline_property(callee) == irg_inline_forced)) {
+ (get_irg_inline_property(callee) == irg_inline_forced)) {
inline_method(env.calls[i], callee);
}
}
static void collect_calls2(ir_node *call, void *env) {
inline_irg_env *x = (inline_irg_env *)env;
- ir_op *op = intern_get_irn_op(call);
+ ir_op *op = get_irn_op(call);
ir_graph *callee;
/* count nodes in irg */
}
-/**
+/*
* Inlines small leave methods at call sites where the called address comes
* from a Const node that references the entity representing the called
* method.
for (i = 0; i < n_irgs; ++i) {
current_ir_graph = get_irp_irg(i);
assert(get_irg_phase_state(current_ir_graph) != phase_building);
- assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
+ free_callee_info(current_ir_graph);
irg_walk(get_irg_end(current_ir_graph), NULL, collect_calls2,
- get_irg_link(current_ir_graph));
+ get_irg_link(current_ir_graph));
}
- /* and now inline.
- Inline leaves recursively -- we might construct new leaves. */
- /* int itercnt = 1; */
+ /* -- and now inline. -- */
+
+ /* Inline leaves recursively -- we might construct new leaves. */
while (did_inline) {
- /* printf("iteration %d\n", itercnt++); */
did_inline = 0;
+
for (i = 0; i < n_irgs; ++i) {
ir_node *call;
- eset *walkset;
int phiproj_computed = 0;
current_ir_graph = get_irp_irg(i);
env = (inline_irg_env *)get_irg_link(current_ir_graph);
- /* we can not walk and change a set, nor remove from it.
- So recompute.*/
- walkset = env->call_nodes;
- env->call_nodes = eset_create();
- for (call = eset_first(walkset); call; call = eset_next(walkset)) {
- inline_irg_env *callee_env;
+ for (call = eset_first(env->call_nodes); call; call = eset_next(env->call_nodes)) {
+ if (get_irn_op(call) == op_Tuple) continue; /* We already inlined. */
ir_graph *callee = get_call_called_irg(call);
- if (env->n_nodes > maxsize) break;
- if (callee &&
- ((is_leave(callee) && is_smaller(callee, leavesize)) ||
- (get_irg_inline_property(callee) == irg_inline_forced))) {
+ if (env->n_nodes > maxsize) continue; // break;
+
+ if (callee && (is_leave(callee) && is_smaller(callee, leavesize))) {
if (!phiproj_computed) {
phiproj_computed = 1;
collect_phiprojs(current_ir_graph);
}
- callee_env = (inline_irg_env *)get_irg_link(callee);
-/* printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
-/* get_entity_name(get_irg_entity(callee))); */
- inline_method(call, callee);
- did_inline = 1;
- env->n_call_nodes--;
- eset_insert_all(env->call_nodes, callee_env->call_nodes);
- env->n_call_nodes += callee_env->n_call_nodes;
- env->n_nodes += callee_env->n_nodes;
- callee_env->n_callers--;
- } else {
- eset_insert(env->call_nodes, call);
- }
+ did_inline = inline_method(call, callee);
+
+ if (did_inline) {
+ /* Do some statistics */
+ inline_irg_env *callee_env = (inline_irg_env *)get_irg_link(callee);
+ env->n_call_nodes --;
+ env->n_nodes += callee_env->n_nodes;
+ callee_env->n_callers--;
+ }
+ }
}
- eset_destroy(walkset);
}
}
- /* printf("Non leaves\n"); */
/* inline other small functions. */
for (i = 0; i < n_irgs; ++i) {
ir_node *call;
walkset = env->call_nodes;
env->call_nodes = eset_create();
for (call = eset_first(walkset); call; call = eset_next(walkset)) {
- inline_irg_env *callee_env;
+ if (get_irn_op(call) == op_Tuple) continue; /* We already inlined. */
ir_graph *callee = get_call_called_irg(call);
- if (env->n_nodes > maxsize) break;
- if (callee && is_smaller(callee, size)) {
+ if (callee &&
+ ((is_smaller(callee, size) && (env->n_nodes < maxsize)) || /* small function */
+ (get_irg_inline_property(callee) == irg_inline_forced))) {
if (!phiproj_computed) {
phiproj_computed = 1;
collect_phiprojs(current_ir_graph);
}
- callee_env = (inline_irg_env *)get_irg_link(callee);
-/* printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
-/* get_entity_name(get_irg_entity(callee))); */
- inline_method(call, callee);
- did_inline = 1;
- env->n_call_nodes--;
- eset_insert_all(env->call_nodes, callee_env->call_nodes);
- env->n_call_nodes += callee_env->n_call_nodes;
- env->n_nodes += callee_env->n_nodes;
- callee_env->n_callers--;
+ if (inline_method(call, callee)) {
+ inline_irg_env *callee_env = (inline_irg_env *)get_irg_link(callee);
+ env->n_call_nodes--;
+ eset_insert_all(env->call_nodes, callee_env->call_nodes); /* @@@ ??? This are the wrong nodes !? Not the copied ones. */
+ env->n_call_nodes += callee_env->n_call_nodes;
+ env->n_nodes += callee_env->n_nodes;
+ callee_env->n_callers--;
+ }
} else {
eset_insert(env->call_nodes, call);
}
#if 0
env = (inline_irg_env *)get_irg_link(current_ir_graph);
if ((env->n_call_nodes_orig != env->n_call_nodes) ||
- (env->n_callers_orig != env->n_callers))
+ (env->n_callers_orig != env->n_callers))
printf("Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
- env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
- env->n_callers_orig, env->n_callers,
- get_entity_name(get_irg_entity(current_ir_graph)));
+ env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
+ env->n_callers_orig, env->n_callers,
+ get_entity_name(get_irg_entity(current_ir_graph)));
#endif
free_inline_irg_env((inline_irg_env *)get_irg_link(current_ir_graph));
}
mark_irn_visited(n);
/* Place floating nodes. */
- if (get_op_pinned(intern_get_irn_op(n)) == floats) {
- int depth = 0;
- ir_node *b = new_Bad(); /* The block to place this node in */
+ if (get_op_pinned(get_irn_op(n)) == op_pin_state_floats) {
+ int depth = 0;
+ ir_node *b = new_Bad(); /* The block to place this node in */
+ int bad_recursion = is_Bad(get_nodes_block(n));
- assert(intern_get_irn_op(n) != op_Block);
+ assert(get_irn_op(n) != op_Block);
- if ((intern_get_irn_op(n) == op_Const) ||
- (intern_get_irn_op(n) == op_SymConst) ||
+ if ((get_irn_op(n) == op_Const) ||
+ (get_irn_op(n) == op_SymConst) ||
(is_Bad(n)) ||
- (intern_get_irn_op(n) == op_Unknown)) {
+ (get_irn_op(n) == op_Unknown)) {
/* These nodes will not be placed by the loop below. */
b = get_irg_start_block(current_ir_graph);
depth = 1;
}
/* find the block for this node. */
- irn_arity = intern_get_irn_arity(n);
+ irn_arity = get_irn_arity(n);
for (i = 0; i < irn_arity; i++) {
- ir_node *dep = intern_get_irn_n(n, i);
+ ir_node *dep = get_irn_n(n, i);
ir_node *dep_block;
- if ((irn_not_visited(dep)) &&
- (get_op_pinned(intern_get_irn_op(dep)) == floats)) {
- place_floats_early(dep, worklist);
+
+ if ((irn_not_visited(dep))
+ && (get_op_pinned(get_irn_op(dep)) == op_pin_state_floats)) {
+ place_floats_early(dep, worklist);
}
- /* Because all loops contain at least one pinned node, now all
- our inputs are either pinned or place_early has already
+
+ /*
+ * A node in the Bad block must stay in the bad block,
+ * so don't compute a new block for it.
+ */
+ if (bad_recursion)
+ 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! */
- dep_block = get_nodes_Block(dep);
+ dep_block = get_nodes_block(dep);
if ((!is_Bad(dep_block)) &&
- (get_Block_dom_depth(dep_block) > depth)) {
- b = dep_block;
- depth = get_Block_dom_depth(dep_block);
+ (get_Block_dom_depth(dep_block) > depth)) {
+ b = dep_block;
+ depth = get_Block_dom_depth(dep_block);
}
/* Avoid that the node is placed in the Start block */
- if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
- b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
- assert(b != get_irg_start_block(current_ir_graph));
- depth = 2;
+ if ((depth == 1) && (get_Block_dom_depth(get_nodes_block(n)) > 1)) {
+ b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
+ assert(b != get_irg_start_block(current_ir_graph));
+ depth = 2;
}
}
- set_nodes_Block(n, b);
+ set_nodes_block(n, b);
}
/* Add predecessors of non floating nodes on worklist. */
- start = (intern_get_irn_op(n) == op_Block) ? 0 : -1;
- irn_arity = intern_get_irn_arity(n);
+ start = (get_irn_op(n) == op_Block) ? 0 : -1;
+ irn_arity = get_irn_arity(n);
for (i = start; i < irn_arity; i++) {
- ir_node *pred = intern_get_irn_n(n, i);
+ ir_node *pred = get_irn_n(n, i);
if (irn_not_visited(pred)) {
pdeq_putr (worklist, pred);
}
/**
* Floating nodes form subgraphs that begin at nodes as Const, Load,
- * Start, Call and end at pinned nodes as Store, Call. Place_early
+ * 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 pinned nodes to the worklist.
+ * nodes and adds all beginnings at op_pin_state_pinned nodes to the worklist.
*/
static INLINE void place_early(pdeq* worklist) {
assert(worklist);
}
set_irg_outs_inconsistent(current_ir_graph);
- current_ir_graph->pinned = pinned;
+ current_ir_graph->op_pin_state_pinned = op_pin_state_pinned;
}
/* Compute the latest block into which we can place a node so that it is
before consumer. */
- if (intern_get_irn_op(consumer) == op_Phi) {
+ if (get_irn_op(consumer) == op_Phi) {
/* our consumer is a Phi-node, the effective use is in all those
blocks through which the Phi-node reaches producer */
int i, irn_arity;
- ir_node *phi_block = get_nodes_Block(consumer);
- irn_arity = intern_get_irn_arity(consumer);
+ ir_node *phi_block = get_nodes_block(consumer);
+ irn_arity = get_irn_arity(consumer);
for (i = 0; i < irn_arity; i++) {
- if (intern_get_irn_n(consumer, i) == producer) {
- block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
+ if (get_irn_n(consumer, i) == producer) {
+ block = get_nodes_block(get_Block_cfgpred(phi_block, i));
}
}
} else {
assert(is_no_Block(consumer));
- block = get_nodes_Block(consumer);
+ block = get_nodes_block(consumer);
}
/* Compute the deepest common ancestor of block and dca. */
/* Find the region deepest in the dominator tree dominating
dca with the least loop nesting depth, but still dominated
by our early placement. */
- dca = get_nodes_Block(n);
+ dca = get_nodes_block(n);
best = dca;
while (dca != early) {
dca = get_Block_idom(dca);
best = dca;
}
}
- if (best != get_nodes_Block(n)) {
+ 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));
+ printf(" Innermost block: "); DDMN(get_nodes_block(n));
*/
- set_nodes_Block(n, best);
+ set_nodes_block(n, best);
}
}
assert (irn_not_visited(n)); /* no multiple placement */
/* no need to place block nodes, control nodes are already placed. */
- if ((intern_get_irn_op(n) != op_Block) &&
+ if ((get_irn_op(n) != op_Block) &&
(!is_cfop(n)) &&
- (intern_get_irn_mode(n) != mode_X)) {
+ (get_irn_mode(n) != mode_X)) {
/* Remember the early placement of this block to move it
out of loop no further than the early placement. */
- early = get_nodes_Block(n);
+ early = get_nodes_block(n);
/* Assure that our users are all placed, except the Phi-nodes.
--- Each data flow cycle contains at least one Phi-node. We
have to break the `user has to be placed before the
producer' dependence cycle and the Phi-nodes are the
place to do so, because we need to base our placement on the
final region of our users, which is OK with Phi-nodes, as they
- are pinned, and they never have to be placed after a
+ are op_pin_state_pinned, and they never have to be placed after a
producer of one of their inputs in the same block anyway. */
for (i = 0; i < get_irn_n_outs(n); i++) {
ir_node *succ = get_irn_out(n, i);
- if (irn_not_visited(succ) && (intern_get_irn_op(succ) != op_Phi))
- place_floats_late(succ, worklist);
+ if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
+ place_floats_late(succ, worklist);
}
/* We have to determine the final block of this node... except for
constants. */
- if ((get_op_pinned(intern_get_irn_op(n)) == floats) &&
- (intern_get_irn_op(n) != op_Const) &&
- (intern_get_irn_op(n) != op_SymConst)) {
+ if ((get_op_pinned(get_irn_op(n)) == op_pin_state_floats) &&
+ (get_irn_op(n) != op_Const) &&
+ (get_irn_op(n) != op_SymConst)) {
ir_node *dca = NULL; /* deepest common ancestor in the
dominator tree of all nodes'
blocks depending on us; our final
placement has to dominate DCA. */
for (i = 0; i < get_irn_n_outs(n); i++) {
- dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
+ dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
}
- set_nodes_Block(n, dca);
+ set_nodes_block(n, dca);
move_out_of_loops (n, early);
}
if (get_irg_dom_state(irg) != dom_consistent)
compute_doms(irg);
- if (get_irg_loopinfo_state(irg) != loopinfo_consistent) {
+ if (1 || get_irg_loopinfo_state(irg) != loopinfo_consistent) {
free_loop_information(irg);
construct_backedges(irg);
}
int i;
set_irn_link(n, NULL);
- if (intern_get_irn_op(n) == op_Block) {
+ if (get_irn_op(n) == op_Block) {
/* Remove Tuples */
for (i = 0; i < get_Block_n_cfgpreds(n); i++)
/* GL @@@ : is this possible? if (get_opt_normalize()) -- added, all tests go through.
A different order of optimizations might cause problems. */
if (get_opt_normalize())
- set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
- } else if (get_opt_optimize() && (intern_get_irn_mode(n) == mode_X)) {
+ set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
+ } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
/* We will soon visit a block. Optimize it before visiting! */
- ir_node *b = get_nodes_Block(n);
+ ir_node *b = get_nodes_block(n);
ir_node *new_node = equivalent_node(b);
while (irn_not_visited(b) && (!is_Bad(new_node)) && (new_node != b)) {
/* We would have to run gigo if new is bad, so we
b = new_node;
new_node = equivalent_node(b);
}
- /* GL @@@ get_opt_normalize hinzugefuegt, 5.5.2003 */
if (is_Bad(new_node) && get_opt_normalize()) exchange(n, new_Bad());
}
}
*/
static void collect_nodes(ir_node *n, void *env) {
if (is_no_Block(n)) {
- ir_node *b = get_nodes_Block(n);
+ ir_node *b = get_nodes_block(n);
- if ((intern_get_irn_op(n) == op_Phi)) {
+ if ((get_irn_op(n) == op_Phi)) {
/* Collect Phi nodes to compact ins along with block's ins. */
set_irn_link(n, get_irn_link(b));
set_irn_link(b, n);
- } else if (intern_get_irn_op(n) != op_Jmp) { /* Check for non empty block. */
+ } else if ((get_irn_op(n) != op_Jmp) && !is_Bad(b)) { /* Check for non empty block. */
mark_Block_block_visited(b);
}
}
static int is_pred_of(ir_node *pred, ir_node *b) {
int i;
for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
- ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
+ ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
if (b_pred == pred) return 1;
}
return 0;
int i, j, n_preds = 1;
int dispensable = 1;
ir_node *cfop = get_Block_cfgpred(b, pos);
- ir_node *pred = get_nodes_Block(cfop);
+ ir_node *pred = get_nodes_block(cfop);
if (get_Block_block_visited(pred) + 1
< get_irg_block_visited(current_ir_graph)) {
/* b's pred blocks and pred's pred blocks must be pairwise disjunct.
Work preds < pos as if they were already removed. */
for (i = 0; i < pos; i++) {
- ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
- if (get_Block_block_visited(b_pred) + 1
- < get_irg_block_visited(current_ir_graph)) {
- for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
- ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
- if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
- }
- } else {
- if (is_pred_of(b_pred, pred)) dispensable = 0;
- }
+ ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
+ if (get_Block_block_visited(b_pred) + 1
+ < get_irg_block_visited(current_ir_graph)) {
+ for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
+ ir_node *b_pred_pred = get_nodes_block(get_Block_cfgpred(b_pred, j));
+ if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
+ }
+ } else {
+ if (is_pred_of(b_pred, pred)) dispensable = 0;
+ }
}
for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
- ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
- if (is_pred_of(b_pred, pred)) dispensable = 0;
+ ir_node *b_pred = get_nodes_block(get_Block_cfgpred(b, i));
+ if (is_pred_of(b_pred, pred)) dispensable = 0;
}
if (!dispensable) {
- set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
- n_preds = 1;
+ set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
+ n_preds = 1;
} else {
n_preds = get_Block_n_cfgpreds(pred);
}
/*-
printf(" working on "); DDMN(b);
for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
- pred = get_nodes_Block(get_Block_cfgpred(b, i));
+ pred = get_nodes_block(get_Block_cfgpred(b, i));
if (is_Bad(get_Block_cfgpred(b, i))) {
printf(" removing Bad %i\n ", i);
} else if (get_Block_block_visited(pred) +1
/*- Fix the Phi nodes -*/
phi = get_irn_link(b);
while (phi) {
- assert(intern_get_irn_op(phi) == op_Phi);
+ assert(get_irn_op(phi) == op_Phi);
/* Find the new predecessors for the Phi */
n_preds = 0;
for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
- pred = get_nodes_Block(get_Block_cfgpred(b, i));
+ pred = get_nodes_block(get_Block_cfgpred(b, i));
if (is_Bad(get_Block_cfgpred(b, i))) {
- /* Do nothing */
+ /* Do nothing */
} else if (get_Block_block_visited(pred) +1
< get_irg_block_visited(current_ir_graph)) {
- /* It's an empty block and not yet visited. */
- ir_node *phi_pred = get_Phi_pred(phi, i);
- for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
- if (get_nodes_Block(phi_pred) == pred) {
- assert(intern_get_irn_op(phi_pred) == op_Phi); /* Block is empty!! */
- in[n_preds] = get_Phi_pred(phi_pred, j);
- } else {
- in[n_preds] = phi_pred;
- }
- n_preds++;
- }
- /* The Phi_pred node is replaced now if it is a Phi.
- In Schleifen kann offenbar der entfernte Phi Knoten legal verwendet werden.
- Daher muss der Phiknoten durch den neuen ersetzt werden.
- Weiter muss der alte Phiknoten entfernt werden (durch ersetzen oder
- durch einen Bad) damit er aus den keep_alive verschwinden kann.
- Man sollte also, falls keine Schleife vorliegt, exchange mit new_Bad
- aufrufen. */
- if (get_nodes_Block(phi_pred) == pred) {
- /* remove the Phi as it might be kept alive. Further there
- might be other users. */
- exchange(phi_pred, phi); /* geht, ist aber doch semantisch falsch! Warum?? */
- }
+ /* It's an empty block and not yet visited. */
+ ir_node *phi_pred = get_Phi_pred(phi, i);
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ if (get_nodes_block(phi_pred) == pred) {
+ assert(get_irn_op(phi_pred) == op_Phi); /* Block is empty!! */
+ in[n_preds] = get_Phi_pred(phi_pred, j);
} else {
- in[n_preds] = get_Phi_pred(phi, i);
- n_preds ++;
+ in[n_preds] = phi_pred;
+ }
+ n_preds++;
+ }
+ /* The Phi_pred node is replaced now if it is a Phi.
+ In Schleifen kann offenbar der entfernte Phi Knoten legal verwendet werden.
+ Daher muss der Phiknoten durch den neuen ersetzt werden.
+ Weiter muss der alte Phiknoten entfernt werden (durch ersetzen oder
+ durch einen Bad) damit er aus den keep_alive verschwinden kann.
+ Man sollte also, falls keine Schleife vorliegt, exchange mit new_Bad
+ aufrufen. */
+ if (get_nodes_block(phi_pred) == pred) {
+ /* remove the Phi as it might be kept alive. Further there
+ might be other users. */
+ exchange(phi_pred, phi); /* geht, ist aber doch semantisch falsch! Warum?? */
+ }
+ } else {
+ in[n_preds] = get_Phi_pred(phi, i);
+ n_preds ++;
}
}
/* Fix the node */
/*-
This happens only if merge between loop backedge and single loop entry. -*/
for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
- pred = get_nodes_Block(get_Block_cfgpred(b, k));
+ pred = get_nodes_block(get_Block_cfgpred(b, k));
if (get_Block_block_visited(pred)+1 < get_irg_block_visited(current_ir_graph)) {
phi = get_irn_link(pred);
while (phi) {
- if (intern_get_irn_op(phi) == op_Phi) {
- set_nodes_Block(phi, b);
-
- n_preds = 0;
- for (i = 0; i < k; i++) {
- pred = get_nodes_Block(get_Block_cfgpred(b, i));
- if (is_Bad(get_Block_cfgpred(b, i))) {
- /* Do nothing */
- } else if (get_Block_block_visited(pred) +1
- < get_irg_block_visited(current_ir_graph)) {
- /* It's an empty block and not yet visited. */
- for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
- /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
- muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
- Anweisungen.) Trotzdem tuts bisher!! */
- in[n_preds] = phi;
- n_preds++;
- }
- } else {
- in[n_preds] = phi;
- n_preds++;
- }
- }
- for (i = 0; i < get_Phi_n_preds(phi); i++) {
- in[n_preds] = get_Phi_pred(phi, i);
- n_preds++;
- }
- for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
- pred = get_nodes_Block(get_Block_cfgpred(b, i));
- if (is_Bad(get_Block_cfgpred(b, i))) {
- /* Do nothing */
- } else if (get_Block_block_visited(pred) +1
- < get_irg_block_visited(current_ir_graph)) {
- /* It's an empty block and not yet visited. */
- for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
- in[n_preds] = phi;
- n_preds++;
- }
- } else {
- in[n_preds] = phi;
- n_preds++;
- }
- }
- set_irn_in(phi, n_preds, in);
- }
- phi = get_irn_link(phi);
+ if (get_irn_op(phi) == op_Phi) {
+ set_nodes_block(phi, b);
+
+ n_preds = 0;
+ for (i = 0; i < k; i++) {
+ pred = get_nodes_block(get_Block_cfgpred(b, i));
+ if (is_Bad(get_Block_cfgpred(b, i))) {
+ /* Do nothing */
+ } else if (get_Block_block_visited(pred) +1
+ < get_irg_block_visited(current_ir_graph)) {
+ /* It's an empty block and not yet visited. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
+ muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
+ Anweisungen.) Trotzdem tuts bisher!! */
+ in[n_preds] = phi;
+ n_preds++;
+ }
+ } else {
+ in[n_preds] = phi;
+ n_preds++;
+ }
+ }
+ for (i = 0; i < get_Phi_n_preds(phi); i++) {
+ in[n_preds] = get_Phi_pred(phi, i);
+ n_preds++;
+ }
+ for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
+ pred = get_nodes_block(get_Block_cfgpred(b, i));
+ if (is_Bad(get_Block_cfgpred(b, i))) {
+ /* Do nothing */
+ } else if (get_Block_block_visited(pred) +1
+ < get_irg_block_visited(current_ir_graph)) {
+ /* It's an empty block and not yet visited. */
+ for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
+ in[n_preds] = phi;
+ n_preds++;
+ }
+ } else {
+ in[n_preds] = phi;
+ n_preds++;
+ }
+ }
+ set_irn_in(phi, n_preds, in);
+ }
+ phi = get_irn_link(phi);
}
}
}
/*- Fix the block -*/
n_preds = 0;
for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
- pred = get_nodes_Block(get_Block_cfgpred(b, i));
+ pred = get_nodes_block(get_Block_cfgpred(b, i));
if (is_Bad(get_Block_cfgpred(b, i))) {
/* Do nothing */
} else if (get_Block_block_visited(pred) +1
assert(get_Block_n_cfgpreds(b) > 1);
/* Else it should be optimized by equivalent_node. */
for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
- in[n_preds] = get_Block_cfgpred(pred, j);
- n_preds++;
+ in[n_preds] = get_Block_cfgpred(pred, j);
+ n_preds++;
}
/* Remove block as it might be kept alive. */
exchange(pred, b/*new_Bad()*/);
/* Walk all keep alives, optimize them if block, add to new in-array
for end if useful. */
in = NEW_ARR_F (ir_node *, 1);
- in[0] = get_nodes_Block(end);
+ in[0] = get_nodes_block(end);
inc_irg_visited(current_ir_graph);
for(i = 0; i < get_End_n_keepalives(end); i++) {
ir_node *ka = get_End_keepalive(end, i);
if (irn_not_visited(ka)) {
- if ((intern_get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
- set_irg_block_visited(current_ir_graph, /* Don't walk all the way to Start. */
- get_irg_block_visited(current_ir_graph)-1);
- irg_block_walk(ka, optimize_blocks, NULL, NULL);
- mark_irn_visited(ka);
- ARR_APP1 (ir_node *, in, ka);
- } else if (intern_get_irn_op(ka) == op_Phi) {
- mark_irn_visited(ka);
- ARR_APP1 (ir_node *, in, ka);
+ if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
+ set_irg_block_visited(current_ir_graph, /* Don't walk all the way to Start. */
+ get_irg_block_visited(current_ir_graph)-1);
+ irg_block_walk(ka, optimize_blocks, NULL, NULL);
+ mark_irn_visited(ka);
+ ARR_APP1 (ir_node *, in, ka);
+ } else if (get_irn_op(ka) == op_Phi) {
+ mark_irn_visited(ka);
+ ARR_APP1 (ir_node *, in, ka);
}
}
}
ir_node *pre, *block, **in, *jmp;
/* Block has multiple predecessors */
- if ((op_Block == intern_get_irn_op(n)) &&
- (intern_get_irn_arity(n) > 1)) {
- arity = intern_get_irn_arity(n);
+ if ((op_Block == get_irn_op(n)) &&
+ (get_irn_arity(n) > 1)) {
+ arity = get_irn_arity(n);
if (n == get_irg_end_block(current_ir_graph))
return; /* No use to add a block here. */
for (i=0; i<arity; i++) {
- pre = intern_get_irn_n(n, i);
+ pre = get_irn_n(n, i);
/* Predecessor has multiple successors. Insert new flow edge */
if ((NULL != pre) &&
- (op_Proj == intern_get_irn_op(pre)) &&
- op_Raise != intern_get_irn_op(skip_Proj(pre))) {
-
- /* set predecessor array for new block */
- in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
- /* set predecessor of new block */
- in[0] = pre;
- block = new_Block(1, in);
- /* insert new jmp node to new block */
- switch_block(block);
- jmp = new_Jmp();
- switch_block(n);
- /* set successor of new block */
- set_irn_n(n, i, jmp);
+ (op_Proj == get_irn_op(pre)) &&
+ op_Raise != get_irn_op(skip_Proj(pre))) {
+
+ /* set predecessor array for new block */
+ in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
+ /* set predecessor of new block */
+ in[0] = pre;
+ block = new_Block(1, in);
+ /* insert new jmp node to new block */
+ set_cur_block(block);
+ jmp = new_Jmp();
+ set_cur_block(n);
+ /* set successor of new block */
+ set_irn_n(n, i, jmp);
} /* predecessor has multiple successors */
} /* for all predecessors */