#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"
#include "irhooks.h"
#include "irtools.h"
+DEBUG_ONLY(static firm_dbg_module_t *dbg;)
/*------------------------------------------------------------------*/
/* Routines for dead node elimination / copying garbage collection */
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 */
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;
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;
env->n_callers = 0;
env->n_callers_orig = 0;
env->got_inline = 0;
+ env->local_vars = 0;
env->local_weights = NULL;
return env;
}
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);
/* 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);
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) {
/* 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;
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);
}
}
/**
* 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;
* 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;
}
}
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();
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);
/* 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;
/* 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);
}
}
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");
+}