switch scalar replacement to new style debug output
[libfirm] / ir / opt / opt_inline.c
index ed76d7d..0fd8328 100644 (file)
@@ -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);
@@ -1634,7 +1642,7 @@ void inline_leave_functions(int maxsize, int leavesize, int size, int ignore_run
  * 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) {
@@ -1661,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;
@@ -1693,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);
        }
 }
 
@@ -1721,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;
 
@@ -1766,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;
                }
        }
 
@@ -1807,9 +1842,7 @@ void inline_functions(int inline_threshold) {
        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);
 
@@ -1848,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);
@@ -1922,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;
@@ -1956,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);
                }
@@ -1981,3 +2021,7 @@ void inline_functions(int inline_threshold) {
        obstack_free(&temp_obst, NULL);
        current_ir_graph = rem;
 }
+
+void firm_init_inline(void) {
+       FIRM_DBG_REGISTER(dbg, "firm.opt.inline");
+}