X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fopt_inline.c;h=b12e7ef9f6fb746bc9c6875fa930f79f2e25978a;hb=c7dc950ac0cdd7d24acffb798b5867d0db5dd7c8;hp=e33e3f7b3d233a7c18bf1dfe009c296b6bc01881;hpb=3079cf3bac053a6aeb315bf73a02791720ddfbe6;p=libfirm diff --git a/ir/opt/opt_inline.c b/ir/opt/opt_inline.c index e33e3f7b3..b12e7ef9f 100644 --- a/ir/opt/opt_inline.c +++ b/ir/opt/opt_inline.c @@ -1303,6 +1303,7 @@ typedef struct { int n_callers_orig; /**< for statistics */ 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 recursive:1; /**< Set, if this function is self recursive. */ call_entry *call_head; /**< The head of the list of all call nodes in this graph. */ call_entry *call_tail; /**< The tail of the list of all call nodes in this graph .*/ unsigned *local_weights; /**< Once allocated, the beneficial weight for transmitting local addresses. */ @@ -1324,6 +1325,7 @@ static inline_irg_env *alloc_inline_irg_env(void) { env->n_callers_orig = 0; env->got_inline = 0; env->local_vars = 0; + env->recursive = 0; env->local_weights = NULL; return env; } @@ -1382,6 +1384,8 @@ static void collect_calls2(ir_node *call, void *ctx) { ++callee_env->n_callers; ++callee_env->n_callers_orig; } + if (callee == current_ir_graph) + x->recursive = 1; /* link it in the list of possible inlinable entries */ entry = obstack_alloc(&temp_obst, sizeof(*entry)); @@ -1530,6 +1534,7 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run assert(get_irg_phase_state(irg) != phase_building); free_callee_info(irg); + assure_cf_loop(irg); wenv.x = get_irg_link(irg); irg_walk_graph(irg, NULL, collect_calls2, &wenv); } @@ -1642,6 +1647,7 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run callee_env = alloc_inline_irg_env(); set_irg_link(copy, callee_env); + assure_cf_loop(copy); wenv.x = callee_env; wenv.ignore_callers = 1; irg_walk_graph(copy, NULL, collect_calls2, &wenv); @@ -1850,7 +1856,7 @@ static int calc_inline_benefice(ir_node *call, ir_graph *callee, unsigned *local ir_node *frame_ptr; ir_type *mtp; int weight = 0; - int i, n_params; + int i, n_params, all_const; unsigned cc, v; inline_irg_env *curr_env, *callee_env; @@ -1879,21 +1885,27 @@ static int calc_inline_benefice(ir_node *call, ir_graph *callee, unsigned *local /* constant parameters improve the benefice */ frame_ptr = get_irg_frame(current_ir_graph); + all_const = 1; for (i = 0; i < n_params; ++i) { ir_node *param = get_Call_param(call, i); - if (is_Const(param) || is_SymConst(param)) + if (is_Const(param)) weight += get_method_param_weight(ent, i); - else if (is_Sel(param) && get_Sel_ptr(param) == frame_ptr) { - /* - * An address of a local variable is transmitted. After inlining, - * scalar_replacement might be able to remove the local variable, - * so honor this. - */ - v = get_method_local_adress_weight(callee, i); - weight += v; - if (v > 0) - *local_adr = 1; + else { + all_const = 0; + if (is_SymConst(param)) + weight += get_method_param_weight(ent, i); + else if (is_Sel(param) && get_Sel_ptr(param) == frame_ptr) { + /* + * An address of a local variable is transmitted. After inlining, + * scalar_replacement might be able to remove the local variable, + * so honor this. + */ + v = get_method_local_adress_weight(callee, i); + weight += v; + if (v > 0) + *local_adr = 1; + } } } @@ -1910,17 +1922,39 @@ static int calc_inline_benefice(ir_node *call, ir_graph *callee, unsigned *local /* reduce the benefice if the current function is already big */ curr_env = get_irg_link(current_ir_graph); - weight -= curr_env->n_nodes / 100; + weight -= curr_env->n_nodes / 50; /* give a bonus for functions with one block */ if (callee_env->n_blocks == 1) weight = weight * 3 / 2; + /* and one for small non-recursive functions: we want them to be inlined in mostly every case */ + else if (callee_env->n_nodes < 20 && !callee_env->recursive) + weight += 5000; + + /* and finally for leaves: they do not increase the register pressure + because of callee safe registers */ + else if (callee_env->n_call_nodes == 0) + weight += 25; + + /* + * Reduce the weight for recursive function IFF not all arguments are const. + * inlining recursive functions is rarely good. + */ + if (callee_env->recursive && !all_const) + weight -= 500; + + /* + * All arguments constant is probably a good sign, give an extra bonus + */ + if (all_const) + weight += 100; + return weight; } /** - * Heuristic inliner. Calculates a benifice value for every call and inlines + * Heuristic inliner. Calculates a benefice value for every call and inlines * those calls with a value higher than the threshold. */ void inline_functions(int maxsize, int inline_threshold) {