remove Cast node
[libfirm] / ir / opt / tailrec.c
index 35cfa01..e1945ea 100644 (file)
@@ -22,7 +22,6 @@
  * @brief   Tail-recursion call optimization.
  * @date    08.06.2004
  * @author  Michael Beck
- * @version $Id$
  */
 #include "config.h"
 
@@ -47,7 +46,7 @@
 #include "ircons_t.h"
 #include "irpass.h"
 
-DEBUG_ONLY(static firm_dbg_module_t *dbg);
+DEBUG_ONLY(static firm_dbg_module_t *dbg;)
 
 /**
  * the environment for collecting data
@@ -73,7 +72,7 @@ static void collect_data(ir_node *node, void *env)
        case iro_Proj:
                pred = get_Proj_pred(node);
 
-               opcode = get_irn_opcode(pred);
+               opcode = (ir_opcode)get_irn_opcode(pred);
                if (opcode == iro_Proj) {
                        ir_node *start = get_Proj_pred(pred);
 
@@ -152,11 +151,7 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env)
        assert(env->n_tail_calls > 0);
 
        /* we add new blocks and change the control flow */
-       set_irg_doms_inconsistent(irg);
-       set_irg_extblk_inconsistent(irg);
-
-       /* calls are removed */
-       set_trouts_inconsistent();
+       clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
 
        /* we must build some new nodes WITHOUT CSE */
        set_optimize(0);
@@ -265,10 +260,8 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env)
        }
 
        /* tail recursion was done, all info is invalid */
-       set_irg_doms_inconsistent(irg);
-       set_irg_extblk_inconsistent(irg);
-       set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
-       set_trouts_inconsistent();
+       clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE
+                          | IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO);
        set_irg_callee_info_state(irg, irg_callee_info_inconsistent);
 
        set_optimize(rem);
@@ -311,15 +304,13 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env)
                /* no: we can kill all returns */
                for (p = env->rets; p; p = n) {
                        ir_node *block = get_nodes_block(p);
-                       ir_node *call, *mem, *jmp, *tuple;
+                       ir_node *jmp, *tuple;
 
                        set_r_cur_block(irg, block);
                        n = (ir_node*)get_irn_link(p);
 
-                       call = skip_Proj(get_Return_mem(p));
-                       assert(is_Call(call));
-
-                       mem = get_Call_mem(call);
+                       ir_node *const call = skip_Proj(get_Return_mem(p));
+                       ir_node *const mem  = get_Call_mem(call);
 
                        /* create a new jump, free of CSE */
                        set_optimize(0);
@@ -337,7 +328,7 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env)
                        /* create a new tuple for the return values */
                        tuple = new_r_Tuple(block, env->n_ress, in);
 
-                       turn_into_tuple(call, pn_Call_max);
+                       turn_into_tuple(call, pn_Call_max+1);
                        set_Tuple_pred(call, pn_Call_M,         mem);
                        set_Tuple_pred(call, pn_Call_X_regular, jmp);
                        set_Tuple_pred(call, pn_Call_X_except,  new_r_Bad(irg, mode_X));
@@ -565,22 +556,27 @@ static tail_rec_variants find_variant(ir_node *irn, ir_node *call)
 /*
  * convert simple tail-calls into loops
  */
-int opt_tail_rec_irg(ir_graph *irg)
+void opt_tail_rec_irg(ir_graph *irg)
 {
-       tr_env            env;
-       ir_node           *end_block;
-       int               i, n_ress, n_tail_calls = 0;
-       ir_node           *rets = NULL;
-       ir_type           *mtd_type, *call_type;
-       ir_entity         *ent;
-       ir_graph          *rem;
+       tr_env    env;
+       ir_node   *end_block;
+       int       i, n_ress, n_tail_calls = 0;
+       ir_node   *rets = NULL;
+       ir_type   *mtd_type, *call_type;
+       ir_entity *ent;
+       ir_graph  *rem;
+
+       assure_irg_properties(irg,
+               IR_GRAPH_PROPERTY_MANY_RETURNS
+               | IR_GRAPH_PROPERTY_NO_BADS
+               | IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
 
        FIRM_DBG_REGISTER(dbg, "firm.opt.tailrec");
 
-       assure_irg_outs(irg);
-
-       if (! check_lifetime_of_locals(irg))
-               return 0;
+       if (! check_lifetime_of_locals(irg)) {
+               confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_ALL);
+               return;
+       }
 
        rem = current_ir_graph;
        current_ir_graph = irg;
@@ -599,12 +595,6 @@ int opt_tail_rec_irg(ir_graph *irg)
                        env.variants[i] = TR_DIRECT;
        }
 
-       /*
-        * This tail recursion optimization works best
-        * if the Returns are normalized.
-        */
-       normalize_n_returns(irg);
-
        ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
 
        end_block = get_irg_end_block(irg);
@@ -632,10 +622,10 @@ int opt_tail_rec_irg(ir_graph *irg)
                /* check if it's a recursive call */
                call_ptr = get_Call_ptr(call);
 
-               if (! is_Global(call_ptr))
+               if (! is_SymConst_addr_ent(call_ptr))
                        continue;
 
-               ent = get_Global_entity(call_ptr);
+               ent = get_SymConst_entity(call_ptr);
                if (!ent || get_entity_irg(ent) != irg)
                        continue;
 
@@ -665,10 +655,11 @@ int opt_tail_rec_irg(ir_graph *irg)
                                /* cannot be transformed */
                                break;
                        }
-                       if (var == TR_DIRECT)
+                       if (var == TR_DIRECT) {
                                var = env.variants[j];
-                       else if (env.variants[j] == TR_DIRECT)
+                       } else if (env.variants[j] == TR_DIRECT) {
                                env.variants[j] = var;
+                       }
                        if (env.variants[j] != var) {
                                /* not compatible */
                                DB((dbg, LEVEL_3, "  tail recursion fails for %d return value of %+F\n", j, ret));
@@ -698,15 +689,17 @@ int opt_tail_rec_irg(ir_graph *irg)
                env.n_tail_calls = n_tail_calls;
                env.rets         = rets;
                do_opt_tail_rec(irg, &env);
+               confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_NONE);
+       } else {
+               confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_ALL);
        }
        ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
        current_ir_graph = rem;
-       return n_tail_calls;
 }
 
 ir_graph_pass_t *opt_tail_rec_irg_pass(const char *name)
 {
-       return def_graph_pass_ret(name ? name : "tailrec", opt_tail_rec_irg);
+       return def_graph_pass(name ? name : "tailrec", opt_tail_rec_irg);
 }
 
 /*
@@ -715,20 +708,14 @@ ir_graph_pass_t *opt_tail_rec_irg_pass(const char *name)
 void opt_tail_recursion(void)
 {
        size_t i, n;
-       size_t n_opt_applications = 0;
 
        FIRM_DBG_REGISTER(dbg, "firm.opt.tailrec");
 
        DB((dbg, LEVEL_1, "Performing tail recursion ...\n"));
        for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
                ir_graph *irg = get_irp_irg(i);
-
-               if (opt_tail_rec_irg(irg))
-                       ++n_opt_applications;
+               opt_tail_rec_irg(irg);
        }
-
-       DB((dbg, LEVEL_1, "Done for %zu of %zu graphs.\n",
-           n_opt_applications, get_irp_n_irgs()));
 }
 
 ir_prog_pass_t *opt_tail_recursion_pass(const char *name)