X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fopt_inline.c;h=0fd832886b7ce0a875238f4a9830b2f4b37587ff;hb=bbc6291b6a4ed4fe5bd8d1c2ddd57f4e6a0c8a74;hp=006192bc2ce099f968e98612119761d2b23ebac3;hpb=cf2036b10f0c70b05889ba6b880dc233e0652407;p=libfirm diff --git a/ir/opt/opt_inline.c b/ir/opt/opt_inline.c index 006192bc2..0fd832886 100644 --- a/ir/opt/opt_inline.c +++ b/ir/opt/opt_inline.c @@ -50,6 +50,7 @@ #include "irouts.h" #include "irloop_t.h" #include "irbackedge_t.h" +#include "opt_inline_t.h" #include "cgana.h" #include "trouts.h" #include "error.h" @@ -60,6 +61,7 @@ #include "irhooks.h" #include "irtools.h" +DEBUG_ONLY(static firm_dbg_module_t *dbg;) /*------------------------------------------------------------------*/ /* Routines for dead node elimination / copying garbage collection */ @@ -1212,9 +1214,6 @@ void inline_small_irgs(ir_graph *irg, int size) { ir_graph *rem = current_ir_graph; inline_env_t env; call_entry *entry; - DEBUG_ONLY(firm_dbg_module_t *dbg;) - - FIRM_DBG_REGISTER(dbg, "firm.opt.inline"); current_ir_graph = irg; /* Handle graph state */ @@ -1231,15 +1230,23 @@ void inline_small_irgs(ir_graph *irg, int size) { irg_walk_graph(irg, NULL, collect_calls, &env); if (env.head != NULL) { + int did_inline = 0; + /* There are calls to inline */ collect_phiprojs(irg); for (entry = env.head; entry != NULL; entry = entry->next) { ir_graph *callee = entry->callee; if (((_obstack_memory_used(callee->obst) - (int)obstack_room(callee->obst)) < size) || (get_irg_inline_property(callee) >= irg_inline_forced)) { - inline_method(entry->call, callee); + did_inline |= inline_method(entry->call, callee); } } + if (did_inline != 0) { + /* this irg got calls inlined */ + set_irg_outs_inconsistent(irg); + set_irg_doms_inconsistent(irg); + set_irg_loopinfo_inconsistent(irg); + } } obstack_free(&env.obst, NULL); current_ir_graph = rem; @@ -1258,7 +1265,8 @@ typedef struct { int n_call_nodes_orig; /**< for statistics */ int n_callers; /**< Number of known graphs that call this graphs. */ int n_callers_orig; /**< for statistics */ - int got_inline; /**< Set, if at least one call inside this graph was inlined. */ + unsigned got_inline:1; /**< Set, if at least one call inside this graph was inlined. */ + unsigned local_vars:1; /**< Set, if a inlined function gets the address of an inlined variable. */ unsigned *local_weights; /**< Once allocated, the beneficial weight for transmitting local addresses. */ } inline_irg_env; @@ -1277,6 +1285,7 @@ static inline_irg_env *alloc_inline_irg_env(void) { env->n_callers = 0; env->n_callers_orig = 0; env->got_inline = 0; + env->local_vars = 0; env->local_weights = NULL; return env; } @@ -1404,9 +1413,7 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run const call_entry *centry; pmap *copied_graphs; pmap_entry *pm_entry; - DEBUG_ONLY(firm_dbg_module_t *dbg;) - FIRM_DBG_REGISTER(dbg, "firm.opt.inline"); rem = current_ir_graph; obstack_init(&temp_obst); @@ -1604,6 +1611,7 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run /* this irg got calls inlined */ set_irg_outs_inconsistent(irg); set_irg_doms_inconsistent(irg); + set_irg_loopinfo_inconsistent(irg); optimize_graph_df(irg); optimize_cf(irg); @@ -1630,14 +1638,11 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run current_ir_graph = rem; } -static char v; -static void *VISITED = &v; - /** * Calculate the parameter weights for transmitting the address of a local variable. */ static unsigned calc_method_local_weight(ir_node *arg) { - int i, j; + int i, j, k; unsigned v, weight = 0; for (i = get_irn_n_outs(arg) - 1; i >= 0; --i) { @@ -1664,6 +1669,30 @@ static unsigned calc_method_local_weight(ir_node *arg) { /* we can kill one Sel with constant indexes, this is cheap */ weight += v + 1; break; + case iro_Id: + /* when looking backward we might find Id nodes */ + weight += calc_method_local_weight(succ); + break; + case iro_Tuple: + /* unoptimized tuple */ + for (j = get_Tuple_n_preds(succ) - 1; j >= 0; --j) { + ir_node *pred = get_Tuple_pred(succ, j); + if (pred == arg) { + /* look for Proj(j) */ + for (k = get_irn_n_outs(succ) - 1; k >= 0; --k) { + ir_node *succ_succ = get_irn_out(succ, k); + if (is_Proj(succ_succ)) { + if (get_Proj_proj(succ_succ) == j) { + /* found */ + weight += calc_method_local_weight(succ_succ); + } + } else { + /* this should NOT happen */ + return 0; + } + } + } + } default: /* any other node: unsupported yet or bad. */ return 0; @@ -1696,7 +1725,7 @@ static void analyze_irg_local_weights(inline_irg_env *env, ir_graph *irg) { for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) { arg = get_irn_out(irg_args, i); proj_nr = get_Proj_proj(arg); - ent->attr.mtd_attr.param_weight[proj_nr] = calc_method_local_weight(arg); + env->local_weights[proj_nr] = calc_method_local_weight(arg); } } @@ -1724,13 +1753,13 @@ static unsigned get_method_local_adress_weight(ir_graph *callee, int pos) { /** * calculate a benefice value for inlining the given call. */ -static int calc_inline_benefice(ir_node *call, ir_graph *callee) { +static int calc_inline_benefice(ir_node *call, ir_graph *callee, unsigned *local_adr) { ir_entity *ent = get_irg_entity(callee); ir_node *frame_ptr; ir_type *mtp; int weight = 0; int i, n_params; - unsigned cc; + unsigned cc, v; inline_irg_env *curr_env, *callee_env; @@ -1769,7 +1798,10 @@ static int calc_inline_benefice(ir_node *call, ir_graph *callee) { * scalar_replacement might be able to remove the local variable, * so honor this. */ - weight += get_method_local_adress_weight(callee, i); + v = get_method_local_adress_weight(callee, i); + weight += v; + if (v > 0) + *local_adr = 1; } } @@ -1808,14 +1840,11 @@ void inline_functions(int inline_threshold) { wenv_t wenv; call_entry *entry, *tail; const call_entry *centry; - struct obstack obst; pmap *copied_graphs; pmap_entry *pm_entry; - DEBUG_ONLY(firm_dbg_module_t *dbg;) - FIRM_DBG_REGISTER(dbg, "firm.opt.inline"); rem = current_ir_graph; - obstack_init(&obst); + obstack_init(&temp_obst); /* a map for the copied graphs, used to inline recursive calls */ copied_graphs = pmap_create(); @@ -1852,12 +1881,14 @@ void inline_functions(int inline_threshold) { ir_graph *callee; pmap_entry *e; int benefice; + unsigned local_adr; call = entry->call; callee = entry->callee; /* calculate the benifice on the original call to prevent excessive inlining */ - benefice = calc_inline_benefice(call, callee); + local_adr = 0; + benefice = calc_inline_benefice(call, callee, &local_adr); DB((dbg, SET_LEVEL_2, "In %+F Call %+F has benefice %d\n", current_ir_graph, callee, benefice)); e = pmap_find(copied_graphs, callee); @@ -1926,6 +1957,8 @@ void inline_functions(int inline_threshold) { /* callee was inline. Append it's call list. */ env->got_inline = 1; + if (local_adr) + env->local_vars = 1; --env->n_call_nodes; append_call_list(env, callee_env->call_head); env->n_call_nodes += callee_env->n_call_nodes; @@ -1960,7 +1993,10 @@ void inline_functions(int inline_threshold) { /* this irg got calls inlined */ set_irg_outs_inconsistent(irg); set_irg_doms_inconsistent(irg); + set_irg_loopinfo_inconsistent(irg); + if (env->local_vars) + scalar_replacement_opt(irg); optimize_graph_df(irg); optimize_cf(irg); } @@ -1982,6 +2018,10 @@ void inline_functions(int inline_threshold) { } pmap_destroy(copied_graphs); - obstack_free(&obst, NULL); + obstack_free(&temp_obst, NULL); current_ir_graph = rem; } + +void firm_init_inline(void) { + FIRM_DBG_REGISTER(dbg, "firm.opt.inline"); +}