X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firgopt.c;h=ad794eb1b000ff54a65d439d349916dc21ab42c8;hb=8f355cb9b3d20c10f71d1b1e17cbf59a51ced83b;hp=1f552d94ebd512963fb4e1ce7e74571940953ece;hpb=b3ac2cd834ac9dfcff661f821063ebfa8c36eb84;p=libfirm diff --git a/ir/ir/irgopt.c b/ir/ir/irgopt.c index 1f552d94e..ad794eb1b 100644 --- a/ir/ir/irgopt.c +++ b/ir/ir/irgopt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -52,7 +52,7 @@ #include "irbackedge_t.h" #include "cgana.h" #include "trouts.h" - +#include "error.h" #include "irflag_t.h" #include "irhooks.h" @@ -182,15 +182,13 @@ static void opt_walker(ir_node *n, void *env) { /* Applies local optimizations to all nodes in the graph until fixpoint. */ void optimize_graph_df(ir_graph *irg) { pdeq *waitq = new_pdeq(); - int state = edges_activated(irg); ir_graph *rem = current_ir_graph; ir_node *end; - int i; + int i, state; current_ir_graph = irg; - if (! state) - edges_activate(irg); + state = edges_assure(irg); if (get_opt_global_cse()) set_irg_pinned(current_ir_graph, op_pin_state_floats); @@ -312,6 +310,7 @@ static void copy_node(ir_node *n, void *env) { ir_node *nn, *block; int new_arity; ir_op *op = get_irn_op(n); + (void) env; /* 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 @@ -340,9 +339,13 @@ static void copy_node(ir_node *n, void *env) { get_irn_mode(n), new_arity, get_irn_in(n) + 1); - /* Copy the attributes. These might point to additional data. If this - was allocated on the old obstack the pointers now are dangling. This - frees e.g. the memory of the graph_arr allocated in new_immBlock. */ + /* Copy the attributes. These might point to additional data. If this + was allocated on the old obstack the pointers now are dangling. This + frees e.g. the memory of the graph_arr allocated in new_immBlock. */ + if (op == op_Block) { + /* we cannot allow blocks WITHOUT macroblock input */ + set_irn_n(nn, -1, get_irn_n(n, -1)); + } copy_node_attr(n, nn); #ifdef DEBUG_libfirm @@ -379,7 +382,9 @@ static void copy_preds(ir_node *n, void *env) { set_irn_n(nn, -1, nn); } else { /* get the macro block header */ - set_irn_n(nn, -1, get_new_node(mbh)); + ir_node *nmbh = get_new_node(mbh); + assert(nmbh != NULL); + set_irn_n(nn, -1, nmbh); } /* Don't copy Bad nodes. */ @@ -412,7 +417,7 @@ static void copy_preds(ir_node *n, void *env) { exchange(nn, old); } } - } else if (is_Phi(n)) { + } else if (is_Phi(n) && get_irn_arity(n) > 0) { /* Don't copy node if corresponding predecessor in block is Bad. The Block itself should not be Bad. */ block = get_nodes_block(n); @@ -611,62 +616,65 @@ copy_graph_env(int copy_node_nr) { * 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) { - if (get_opt_optimize() && get_opt_dead_node_elimination()) { - ir_graph *rem; - int rem_ipview = get_interprocedural_view(); - struct obstack *graveyard_obst = NULL; - struct obstack *rebirth_obst = NULL; - 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); - - /* Remember external state of current_ir_graph. */ - rem = current_ir_graph; - current_ir_graph = irg; - set_interprocedural_view(0); +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; + assert(! edges_activated(irg) && "dead node elimination requires disabled edges"); - assert(get_irg_phase_state(irg) != phase_building); + /* inform statistics that we started a dead-node elimination run */ + hook_dead_node_elim(irg, 1); - /* Handle graph state */ - free_callee_info(irg); - free_irg_outs(irg); - free_trouts(); + /* Remember external state of current_ir_graph. */ + rem = current_ir_graph; + current_ir_graph = irg; +#ifdef INTERPROCEDURAL_VIEW + set_interprocedural_view(0); +#endif - /* @@@ so far we loose loops when copying */ - free_loop_information(irg); + assert(get_irg_phase_state(irg) != phase_building); - set_irg_doms_inconsistent(irg); + /* Handle graph state */ + free_callee_info(irg); + free_irg_outs(irg); + free_trouts(); + + /* @@@ so far we loose loops when copying */ + 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 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(sizeof(*rebirth_obst)); - irg->obst = rebirth_obst; - obstack_init(irg->obst); - irg->last_node_idx = 0; + /* A new obstack, where the reachable nodes will be copied to. */ + rebirth_obst = xmalloc(sizeof(*rebirth_obst)); + 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(); + /* 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(/*copy_node_nr=*/1); + /* Copy the graph from the old to the new obstack */ + copy_graph_env(/*copy_node_nr=*/1); - /* Free memory from old unoptimized obstack */ - obstack_free(graveyard_obst, 0); /* First empty the obstack ... */ - xfree(graveyard_obst); /* ... then free it. */ + /* 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); + /* inform statistics that the run is over */ + hook_dead_node_elim(irg, 0); - current_ir_graph = rem; - set_interprocedural_view(rem_ipview); - } + current_ir_graph = rem; +#ifdef INTERPROCEDURAL_VIEW + set_interprocedural_view(rem_ipview); +#endif } /** @@ -769,6 +777,7 @@ static void relink_bad_predecessors(ir_node *n, void *env) { * changes). */ void remove_bad_predecessors(ir_graph *irg) { + panic("Fix backedge handling first"); irg_walk_graph(irg, firm_clear_link, relink_bad_predecessors, NULL); } @@ -988,8 +997,8 @@ int inline_method(ir_node *call, ir_graph *called_graph) { ir_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 0; + if ( (prop < irg_inline_forced) || (prop == irg_inline_forbidden)) + return 0; /* Do not inline variadic functions. */ if (get_method_variadicity(get_entity_type(get_irg_entity(called_graph))) == variadicity_variadic) @@ -1337,7 +1346,7 @@ static ir_graph *get_call_called_irg(ir_node *call) { ir_graph *called_irg = NULL; addr = get_Call_ptr(call); - if (is_SymConst(addr) && get_SymConst_kind(addr) == symconst_addr_ent) { + if (is_SymConst_addr_ent(addr)) { called_irg = get_entity_irg(get_SymConst_entity(addr)); } @@ -1381,8 +1390,6 @@ void inline_small_irgs(ir_graph *irg, int size) { call_entry *entry; DEBUG_ONLY(firm_dbg_module_t *dbg;) - if (!(get_opt_optimize() && get_opt_inline())) return; - FIRM_DBG_REGISTER(dbg, "firm.opt.inline"); current_ir_graph = irg; @@ -1508,7 +1515,7 @@ static void collect_calls2(ir_node *call, void *ctx) { } /** - * Returns TRUE if the number of callers in 0 in the irg's environment, + * Returns TRUE if the number of callers is 0 in the irg's environment, * hence this irg is a leave. */ INLINE static int is_leave(ir_graph *irg) { @@ -1517,7 +1524,8 @@ INLINE static int is_leave(ir_graph *irg) { } /** - * Returns TRUE if the number of callers is smaller size in the irg's environment. + * Returns TRUE if the number of nodes in the callee is + * smaller then size in the irg's environment. */ INLINE static int is_smaller(ir_graph *callee, int size) { inline_irg_env *env = get_irg_link(callee); @@ -1563,8 +1571,6 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run struct obstack obst; DEBUG_ONLY(firm_dbg_module_t *dbg;) - if (!(get_opt_optimize() && get_opt_inline())) return; - FIRM_DBG_REGISTER(dbg, "firm.opt.inline"); rem = current_ir_graph; obstack_init(&obst); @@ -1704,11 +1710,12 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run optimize_graph_df(irg); optimize_cf(irg); } - if (env->got_inline || (env->n_callers_orig != env->n_callers)) + if (env->got_inline || (env->n_callers_orig != env->n_callers)) { DB((dbg, SET_LEVEL_1, "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(irg)))); + } } obstack_free(&obst, NULL); @@ -1964,9 +1971,7 @@ static ir_node *calc_dca(ir_node *dca, ir_node *block) { */ static ir_node *consumer_dom_dca(ir_node *dca, ir_node *consumer, ir_node *producer) { - ir_node *block = NULL; - - /* Compute the latest block into which we can place a node so that it is + /* Compute the last block into which we can place a node so that it is before consumer. */ if (is_Phi(consumer)) { /* our consumer is a Phi-node, the effective use is in all those @@ -1976,23 +1981,18 @@ static ir_node *consumer_dom_dca(ir_node *dca, ir_node *consumer, ir_node *produ int i; for (i = 0; i < arity; i++) { - if (get_irn_n(consumer, i) == producer) { - ir_node *new_block = get_nodes_block(get_Block_cfgpred(phi_block, i)); + if (get_Phi_pred(consumer, i) == producer) { + ir_node *new_block = get_Block_cfgpred_block(phi_block, i); if (!is_Block_unreachable(new_block)) - block = calc_dca(block, new_block); + dca = calc_dca(dca, new_block); } } - - if (!block) - block = get_nodes_block(producer); } else { - assert(!is_Block(consumer)); - block = get_nodes_block(consumer); + dca = calc_dca(dca, get_nodes_block(consumer)); } - /* Compute the deepest common ancestor of block and dca. */ - return calc_dca(dca, block); + return dca; } /* FIXME: the name clashes here with the function from ana/field_temperature.c @@ -2202,7 +2202,7 @@ void place_code(ir_graph *irg) { if (1 || get_irg_loopinfo_state(irg) != loopinfo_consistent) { free_loop_information(irg); - construct_backedges(irg); + construct_cf_backedges(irg); } /* Place all floating nodes as early as possible. This guarantees @@ -2224,7 +2224,8 @@ void place_code(ir_graph *irg) { } typedef struct cf_env { - char changed; /**< flag indicates that the cf graphs has changed. */ + char ignore_exc_edges; /**< set if exception edges should be ignored. */ + char changed; /**< flag indicates that the cf graphs has changed. */ } cf_env; /** @@ -2252,14 +2253,18 @@ static void walk_critical_cf_edges(ir_node *n, void *env) { const ir_op *cfop; pre = get_irn_n(n, i); - cfop = get_irn_op(skip_Proj(pre)); + /* don't count Bad's */ + if (is_Bad(pre)) + continue; + cfop = get_irn_op(skip_Proj(pre)); if (is_op_fragile(cfop)) { - if (cfop != op_Raise) - goto insert; - continue; + if (cenv->ignore_exc_edges && get_Proj_proj(pre) == pn_Generic_X_except) + continue; + goto insert; } - if (is_op_forking(cfop)) { + /* we don't want place nodes in the start block, so handle it like forking */ + if (is_op_forking(cfop) || cfop == op_Start) { /* Predecessor has multiple successors. Insert new control flow edge edges. */ insert: /* set predecessor of new block */ @@ -2277,7 +2282,8 @@ insert: void remove_critical_cf_edges(ir_graph *irg) { cf_env env; - env.changed = 0; + env.ignore_exc_edges = 1; + env.changed = 0; irg_block_walk_graph(irg, NULL, walk_critical_cf_edges, &env); if (env.changed) {