#include "array.h"
#include "pset.h"
+#include "pmap.h"
#include "eset.h"
#include "pdeq.h" /* Fuer code placement */
#include "xmalloc.h"
#include "cgana.h"
#include "trouts.h"
+
#include "irflag_t.h"
#include "irhooks.h"
#include "iredges_t.h"
/* Defined in iropt.c */
pset *new_identities (void);
void del_identities (pset *value_table);
-void add_identities (pset *value_table, ir_node *node);
+void add_identities (pset *value_table, ir_node *node);
/*------------------------------------------------------------------*/
/* apply optimizations of iropt to all nodes. */
if (get_opt_global_cse())
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);
+ set_irg_outs_inconsistent(current_ir_graph);
set_irg_doms_inconsistent(current_ir_graph);
set_irg_loopinfo_inconsistent(current_ir_graph);
#endif
set_new_node(n, nn);
+ hook_dead_node_elim_subst(current_ir_graph, n, nn);
}
/**
struct obstack *rebirth_obst = NULL;
if (get_opt_optimize() && get_opt_dead_node_elimination()) {
- assert(! edges_activated(irg) && "dead node elimination requieres disabled edges");
+ assert(! edges_activated(irg) && "dead node elimination requires disabled edges");
/* inform statistics that we started a dead-node elimination run */
hook_dead_node_elim(irg, 1);
}
+/*
+ __ _ __ __
+ (_ __ o _ | \/ |_
+ __)|_| | \_/ | \_/(/_ |_/\__|__
+
+ The following stuff implements a facility that automatically patches
+ registered ir_node pointers to the new node when a dead node elimination occurs.
+*/
+
+struct _survive_dce_t {
+ struct obstack obst;
+ pmap *places;
+ pmap *new_places;
+ hook_entry_t dead_node_elim;
+ hook_entry_t dead_node_elim_subst;
+};
+
+typedef struct _survive_dce_list_t {
+ struct _survive_dce_list_t *next;
+ ir_node **place;
+} survive_dce_list_t;
+
+static void dead_node_hook(void *context, ir_graph *irg, int start)
+{
+ survive_dce_t *sd = context;
+
+ /* Create a new map before the dead node elimination is performed. */
+ if(start) {
+ sd->new_places = pmap_create_ex(pmap_count(sd->places));
+ }
+
+ /* Patch back all nodes if dead node elimination is over and something is to be done. */
+ else {
+ pmap_destroy(sd->places);
+ sd->places = sd->new_places;
+ sd->new_places = NULL;
+ }
+}
+
+static void dead_node_subst_hook(void *context, ir_graph *irg, ir_node *old, ir_node *nw)
+{
+ survive_dce_t *sd = context;
+ survive_dce_list_t *list = pmap_get(sd->places, old);
+
+ /* If the node is to be patched back, write the new address to all registered locations. */
+ if(list) {
+ survive_dce_list_t *p;
+
+ for(p = list; p; p = p->next)
+ *(p->place) = nw;
+
+ pmap_insert(sd->new_places, nw, list);
+ }
+}
+
+/**
+ * Make a new Survive DCE environment.
+ */
+survive_dce_t *new_survive_dce(void)
+{
+ survive_dce_t *res = xmalloc(sizeof(res[0]));
+ obstack_init(&res->obst);
+ res->places = pmap_create();
+ res->new_places = NULL;
+
+ res->dead_node_elim.hook._hook_dead_node_elim = dead_node_hook;
+ res->dead_node_elim.context = res;
+ res->dead_node_elim.next = NULL;
+
+ res->dead_node_elim_subst.hook._hook_dead_node_elim_subst = dead_node_subst_hook;
+ res->dead_node_elim_subst.context = res;
+ res->dead_node_elim_subst.next = NULL;
+
+ register_hook(hook_dead_node_elim, &res->dead_node_elim);
+ register_hook(hook_dead_node_elim_subst, &res->dead_node_elim_subst);
+ return res;
+}
+
+/**
+ * Free a Survive DCE environment.
+ */
+void free_survive_dce(survive_dce_t *sd)
+{
+ obstack_free(&sd->obst, NULL);
+ pmap_destroy(sd->places);
+ unregister_hook(hook_dead_node_elim, &sd->dead_node_elim);
+ unregister_hook(hook_dead_node_elim_subst, &sd->dead_node_elim_subst);
+ free(sd);
+}
+
+/**
+ * Register a node pointer to be patched upon DCE.
+ * When DCE occurs, the node pointer specified by @p place will be
+ * patched to the new address of the node it is pointing to.
+ *
+ * @param sd The Survive DCE environment.
+ * @param place The address of the node pointer.
+ */
+void survive_dce_register_irn(survive_dce_t *sd, ir_node **place)
+{
+ if(*place != NULL) {
+ ir_node *irn = *place;
+ survive_dce_list_t *curr = pmap_get(sd->places, irn);
+ survive_dce_list_t *nw = obstack_alloc(&sd->obst, sizeof(nw));
+
+ nw->next = curr;
+ nw->place = place;
+
+ pmap_insert(sd->places, irn, nw);
+ }
+}
+
/*--------------------------------------------------------------------*/
/* Functionality for inlining */
/*--------------------------------------------------------------------*/
*/
static INLINE void
copy_node_inline (ir_node *n, void *env) {
- ir_node *new;
+ ir_node *nn;
ir_type *frame_tp = (ir_type *)env;
copy_node(n, NULL);
if (get_irn_op(n) == op_Sel) {
- new = get_new_node (n);
- assert(get_irn_op(new) == op_Sel);
+ nn = get_new_node (n);
+ assert(is_Sel(nn));
if (get_entity_owner(get_Sel_entity(n)) == frame_tp) {
- set_Sel_entity(new, get_entity_link(get_Sel_entity(n)));
+ set_Sel_entity(nn, get_entity_link(get_Sel_entity(n)));
}
} else if (get_irn_op(n) == op_Block) {
- new = get_new_node (n);
- new->attr.block.irg = current_ir_graph;
+ nn = get_new_node (n);
+ nn->attr.block.irg = current_ir_graph;
}
}
assert(get_irg_phase_state(current_ir_graph) != phase_building);
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_outs_inconsistent(current_ir_graph);
+ set_irg_extblk_inconsistent(current_ir_graph);
+ set_irg_doms_inconsistent(current_ir_graph);
set_irg_loopinfo_inconsistent(current_ir_graph);
set_irg_callee_info_state(current_ir_graph, irg_callee_info_inconsistent);
/* -- Check preconditions -- */
- assert(get_irn_op(call) == op_Call);
+ assert(is_Call(call));
/* @@@ does not work for InterfaceIII.java after cgana
assert(get_Call_type(call) == get_entity_type(get_irg_entity(called_graph)));
assert(smaller_type(get_entity_type(get_irg_entity(called_graph)),
for (i = 0; i < arity; i++) {
ir_node *ret;
ret = get_irn_n(end_bl, i);
- if (get_irn_op(ret) == op_Return) {
+ if (is_Return(ret)) {
cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_block(ret));
n_ret++;
}
n_ret = 0;
for (i = 0; i < arity; i++) {
ret = get_irn_n(end_bl, i);
- if (get_irn_op(ret) == op_Return) {
+ if (is_Return(ret)) {
cf_pred[n_ret] = get_Return_mem(ret);
n_ret++;
}
for (i = 0; i < arity; i++) {
ir_node *ret;
ret = skip_Proj(get_irn_n(end_bl, i));
- if (get_irn_op(ret) == op_Call) {
+ if (is_Call(ret)) {
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)) {
ir_node *addr;
ir_graph *called_irg = NULL;
- assert(get_irn_op(call) == op_Call);
+ assert(is_Call(call));
addr = get_Call_ptr(call);
if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind (addr) == symconst_addr_ent)) {
static void collect_calls(ir_node *call, void *env) {
ir_node *addr;
- if (get_irn_op(call) != op_Call) return;
+ if (! is_Call(call)) return;
addr = get_Call_ptr(call);
* Place an empty block to an edge between a blocks of multiple
* predecessors and a block of multiple successors.
*
- * @param n IR node
- * @param env Environment of walker. This field is unused and has
- * the value NULL.
+ * @param n IR node
+ * @param env Environment of walker. The changed field.
*/
static void walk_critical_cf_edges(ir_node *n, void *env) {
int arity, i;
- ir_node *pre, *block, **in, *jmp;
+ ir_node *pre, *block, *jmp;
+ int *changed = env;
/* Block has multiple predecessors */
- if ((op_Block == get_irn_op(n)) &&
- (get_irn_arity(n) > 1)) {
- arity = get_irn_arity(n);
-
+ if (is_Block(n) && (get_irn_arity(n) > 1)) {
if (n == get_irg_end_block(current_ir_graph))
return; /* No use to add a block here. */
+ arity = get_irn_arity(n);
for (i=0; i<arity; i++) {
pre = get_irn_n(n, i);
- /* Predecessor has multiple successors. Insert new flow edge */
- if ((NULL != pre) &&
- (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. Insert new control flow edge. */
+ if (op_Raise != get_irn_op(skip_Proj(pre))) {
+ /* set predecessor of new block */
+ block = new_Block(1, &pre);
+ /* 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);
+ *changed = 1;
} /* predecessor has multiple successors */
} /* for all predecessors */
} /* n is a block */
}
void remove_critical_cf_edges(ir_graph *irg) {
- if (get_opt_critical_edges())
- irg_walk_graph(irg, NULL, walk_critical_cf_edges, NULL);
+ int changed = 0;
+ irg_walk_graph(irg, NULL, walk_critical_cf_edges, &changed);
+
+ if (changed) {
+ /* control flow changed */
+ set_irg_outs_inconsistent(irg);
+ set_irg_extblk_inconsistent(irg);
+ set_irg_doms_inconsistent(current_ir_graph);
+ set_irg_loopinfo_inconsistent(current_ir_graph);
+ }
+
}