X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fopt_inline.c;h=6bd787e7c6d030a2324422d9fac50ba3eacc7b46;hb=a5d5f207f602198e3a9d809f431ea1855dc86fb7;hp=92c24462ed685d7725a561c60b476c97ff964dc9;hpb=2807bb5b1ed34c23dc30d228ab0686c6fc9d6ae3;p=libfirm diff --git a/ir/opt/opt_inline.c b/ir/opt/opt_inline.c index 92c24462e..6bd787e7c 100644 --- a/ir/opt/opt_inline.c +++ b/ir/opt/opt_inline.c @@ -89,357 +89,6 @@ static inline ir_node *get_new_node(ir_node *old_node) return (ir_node*) get_irn_link(old_node); } -/** a pointer to the new phases */ -static ir_phase *new_phases[PHASE_LAST]; - -/** - * Copies the node to the new obstack. The Ins of the new node point to - * the predecessors on the old obstack. For block/phi nodes not all - * predecessors might be copied. n->link points to the new node. - * - * @param n The node to be copied - * @param irg The irg onto which the node should be copied - */ -static ir_node *copy_node(ir_node *n, ir_graph *irg) -{ - ir_op *op = get_irn_op(n); - int arity = get_irn_arity(n); - dbg_info *dbgi = get_irn_dbg_info(n); - ir_mode *mode = get_irn_mode(n); - ir_node *nn; - ir_node *block; - int i; - - if (op == op_Block) { - block = NULL; - n->attr.block.graph_arr = NULL; - } else { - block = get_nodes_block(n); - } - if (op->opar == oparity_dynamic) { - nn = new_ir_node(dbgi, irg, block, op, mode, -1, NULL); - for (i = 0; i < arity; ++i) { - ir_node *in = get_irn_n(n, i); - add_irn_n(nn, in); - } - } else { - ir_node **ins = get_irn_in(n)+1; - nn = new_ir_node(dbgi, irg, block, op, mode, arity, ins); - } - - /* Copy the attributes. These might point to additional data. If this - was allocated on the old obstack the pointers now are dangling. */ - copy_node_attr(irg, n, nn); - if (op == op_Block) { - /* we cannot allow blocks WITHOUT macroblock input */ - set_Block_MacroBlock(nn, get_Block_MacroBlock(n)); - } - - /* copy phase information for this node */ - for (i = PHASE_NOT_IRG_MANAGED+1; i < PHASE_LAST; i++) { - ir_graph *old_irg = get_irn_irg(n); - ir_phase *old_ph = get_irg_phase(old_irg, i); - if (old_ph == NULL) - continue; - if (!phase_get_irn_data(old_ph, n)) - continue; - phase_set_irn_data(new_phases[i], nn, phase_get_irn_data(old_ph, n)); - } - - set_new_node(n, nn); - hook_dead_node_elim_subst(current_ir_graph, n, nn); - - return nn; -} - -static void copy_node_with_number(ir_node *node, void *env) -{ - ir_graph *new_irg = (ir_graph*) env; - ir_node *new_node = copy_node(node, new_irg); - - /* preserve the node numbers for easier debugging */ - new_node->node_nr = node->node_nr; -} - -/** - * Reroute the inputs of a node from nodes in the old graph to copied nodes in - * the new graph - */ -static void set_preds(ir_node *node, void *env) -{ - ir_graph *new_irg = (ir_graph*) env; - ir_node *new_node; - int arity; - int i; - - new_node = get_new_node(node); - - if (is_Block(node)) { - /* copy the macro block header */ - ir_node *mbh = get_Block_MacroBlock(node); - - /* get the macro block header */ - ir_node *nmbh = get_new_node(mbh); - assert(nmbh != NULL); - set_Block_MacroBlock(new_node, nmbh); - } else { - ir_node *block = get_nodes_block(node); - ir_node *new_block = get_new_node(block); - set_nodes_block(new_node, new_block); - } - - arity = get_irn_arity(new_node); - for (i = 0; i < arity; ++i) { - ir_node *in = get_irn_n(node, i); - ir_node *new_in = get_new_node(in); - set_irn_n(new_node, i, new_in); - } - - /* Now the new node is complete. We can add it to the hash table for CSE. */ - add_identities(new_irg->value_table, new_node); -} - -/** - * Copies the graph reachable from current_ir_graph->end to the obstack - * in current_ir_graph and fixes the environment. - * Then fixes the fields in current_ir_graph containing nodes of the - * graph. - * - * @param copy_node_nr If non-zero, the node number will be copied - */ -static void copy_graph_env(ir_graph *irg) -{ - ir_node *old_end; - ir_node *new_anchor; - ir_phase *old_ph; - int i; - - /* init the new_phases array */ - for (i = PHASE_NOT_IRG_MANAGED+1; i < PHASE_LAST; i++) { - old_ph = get_irg_phase(irg, i); - if (old_ph == NULL) { - new_phases[i] = NULL; - } else { - new_phases[i] = xmalloc(sizeof(ir_phase)); - phase_init(new_phases[i], "", irg, old_ph->growth_factor, - old_ph->data_init, old_ph->priv); - } - } - - /* remove end_except and end_reg nodes */ - old_end = get_irg_end(irg); - set_irg_end_except(irg, old_end); - set_irg_end_reg (irg, old_end); - - /* copy nodes */ - irg_walk(irg->anchor, copy_node_with_number, set_preds, irg); - - /* fix the anchor */ - new_anchor = get_new_node(irg->anchor); - assert(new_anchor != NULL); - irg->anchor = new_anchor; - - /* copy the new phases into the irg */ - for (i = PHASE_NOT_IRG_MANAGED+1; i < PHASE_LAST; i++) { - old_ph = get_irg_phase(irg, i); - if (old_ph == NULL) - continue; - - free_irg_phase(irg, i); - irg->phases[i] = new_phases[i]; - } - - free_End(old_end); -} - -/** - * Copies all reachable nodes to a new obstack. Removes bad inputs - * from block nodes and the corresponding inputs from Phi nodes. - * Merges single exit blocks with single entry blocks and removes - * 1-input Phis. - * Adds all new nodes to a new hash table for CSE. Does not - * perform CSE, so the hash table might contain common subexpressions. - */ -void dead_node_elimination(ir_graph *irg) -{ - ir_graph *rem; -#ifdef INTERPROCEDURAL_VIEW - int rem_ipview = get_interprocedural_view(); -#endif - struct obstack *graveyard_obst = NULL; - struct obstack *rebirth_obst = NULL; - - edges_deactivate(irg); - - /* inform statistics that we started a dead-node elimination run */ - hook_dead_node_elim(irg, 1); - - /* Remember external state of current_ir_graph. */ - rem = current_ir_graph; - current_ir_graph = irg; -#ifdef INTERPROCEDURAL_VIEW - set_interprocedural_view(0); -#endif - - assert(get_irg_phase_state(irg) != phase_building); - - /* Handle graph state */ - free_callee_info(irg); - free_irg_outs(irg); - free_trouts(); - free_loop_information(irg); - set_irg_doms_inconsistent(irg); - - /* A quiet place, where the old obstack can rest in peace, - until it will be cremated. */ - graveyard_obst = irg->obst; - - /* A new obstack, where the reachable nodes will be copied to. */ - rebirth_obst = XMALLOC(struct obstack); - irg->obst = rebirth_obst; - obstack_init(irg->obst); - irg->last_node_idx = 0; - - /* We also need a new value table for CSE */ - del_identities(irg->value_table); - irg->value_table = new_identities(); - - /* Copy the graph from the old to the new obstack */ - copy_graph_env(irg); - - /* Free memory from old unoptimized obstack */ - obstack_free(graveyard_obst, 0); /* First empty the obstack ... */ - xfree(graveyard_obst); /* ... then free it. */ - - /* inform statistics that the run is over */ - hook_dead_node_elim(irg, 0); - - current_ir_graph = rem; -#ifdef INTERPROCEDURAL_VIEW - set_interprocedural_view(rem_ipview); -#endif -} - -ir_graph_pass_t *dead_node_elimination_pass(const char *name) -{ - return def_graph_pass(name ? name : "dce", dead_node_elimination); -} - -/* - __ _ __ __ - (_ __ 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; - (void) irg; - - /* Create a new map before the dead node elimination is performed. */ - if (start) { - sd->new_places = pmap_create_ex(pmap_count(sd->places)); - } else { - /* Patch back all nodes if dead node elimination is over and something is to be done. */ - pmap_destroy(sd->places); - sd->places = sd->new_places; - sd->new_places = NULL; - } -} - -/** - * Hook called when dead node elimination replaces old by nw. - */ -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); - (void) irg; - - /* 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(survive_dce_t); - 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); - xfree(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 = OALLOC(&sd->obst, survive_dce_list_t); - - nw->next = curr; - nw->place = place; - - pmap_insert(sd->places, irn, nw); - } -} - /*--------------------------------------------------------------------*/ /* Functionality for inlining */ /*--------------------------------------------------------------------*/ @@ -455,10 +104,11 @@ void survive_dce_register_irn(survive_dce_t *sd, ir_node **place) */ static void copy_node_inline(ir_node *node, void *env) { - ir_graph *new_irg = (ir_graph*) env; - ir_node *new_node; + ir_graph *new_irg = (ir_graph*) env; + ir_node *new_node = irn_copy_into_irg(node, new_irg); + + set_new_node(node, new_node); - new_node = copy_node(node, new_irg); if (is_Sel(node)) { ir_graph *old_irg = get_irn_irg(node); ir_type *old_frame_type = get_irg_frame_type(old_irg); @@ -479,7 +129,7 @@ static void set_preds_inline(ir_node *node, void *env) { ir_node *new_node; - set_preds(node, env); + irn_rewire_inputs(node); /* move constants into start block */ new_node = get_new_node(node);