identifiers starting with _ are reserved; remove this bad practice
[libfirm] / ir / opt / tailrec.c
index be13961..333613d 100644 (file)
@@ -24,9 +24,7 @@
  * @author  Michael Beck
  * @version $Id$
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include <string.h>
 #include <assert.h>
 #include "irouts.h"
 #include "irhooks.h"
 #include "ircons_t.h"
-#include "xmalloc.h"
+#include "irpass.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg);
 
 /**
  * the environment for collecting data
  */
-typedef struct _collect_t {
+typedef struct collect_t {
        ir_node *proj_X;      /**< initial exec proj */
        ir_node *block;       /**< old first block */
        int     blk_idx;      /**< cfgpred index of the initial exec in block */
@@ -65,7 +63,8 @@ typedef struct _collect_t {
 /**
  * walker for collecting data, fills a collect_t environment
  */
-static void collect_data(ir_node *node, void *env) {
+static void collect_data(ir_node *node, void *env)
+{
        collect_t *data = env;
        ir_node *pred;
        ir_op *op;
@@ -137,7 +136,8 @@ typedef struct tr_env {
  * @param rets          linked list of all rets
  * @param n_tail_calls  number of tail-recursion calls
  */
-static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
+static void do_opt_tail_rec(ir_graph *irg, tr_env *env)
+{
        ir_node *end_block = get_irg_end_block(irg);
        ir_node *block, *jmp, *call, *calls;
        ir_node **in;
@@ -198,7 +198,7 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
                ir_node *block = get_nodes_block(p);
 
                n = get_irn_link(p);
-               in[i++] = new_r_Jmp(irg, block);
+               in[i++] = new_r_Jmp(block);
 
                // exchange(p, new_r_Bad(irg));
 
@@ -209,7 +209,7 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
 
        /* create a new block at start */
        block = new_r_Block(irg, env->n_tail_calls + 1, in);
-       jmp   = new_r_Jmp(irg, block);
+       jmp   = new_r_Jmp(block);
 
        /* the old first block is now the second one */
        set_Block_cfgpred(data.block, data.blk_idx, jmp);
@@ -219,7 +219,7 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
 
        /* build the memory phi */
        i = 0;
-       in[i] = new_r_Proj(irg, get_irg_start_block(irg), get_irg_start(irg), mode_M, pn_Start_M);
+       in[i] = new_r_Proj(get_irg_start(irg), mode_M, pn_Start_M);
        set_irg_initial_mem(irg, in[i]);
        ++i;
 
@@ -229,7 +229,7 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
        }
        assert(i == env->n_tail_calls + 1);
 
-       phis[0] = new_r_Phi(irg, block, env->n_tail_calls + 1, in, mode_M);
+       phis[0] = new_r_Phi(block, env->n_tail_calls + 1, in, mode_M);
 
        /* build the data Phi's */
        if (n_params > 0) {
@@ -251,11 +251,11 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
                for (i = 0; i < n_params; ++i) {
                        ir_mode *mode = get_type_mode(get_method_param_type(method_tp, i));
 
-                       in[0] = new_r_Proj(irg, args_bl, args, mode, i);
+                       in[0] = new_r_Proj(args, mode, i);
                        for (j = 0; j < env->n_tail_calls; ++j)
                                in[j + 1] = call_params[j][i];
 
-                       phis[i + 1] = new_r_Phi(irg, block, env->n_tail_calls + 1, in, mode);
+                       phis[i + 1] = new_r_Phi(block, env->n_tail_calls + 1, in, mode);
                }
        }
 
@@ -307,9 +307,9 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
 
                        modes[i] = mode;
                        if (env->variants[i] == TR_ADD) {
-                               set_value(i, new_Const(mode, get_mode_null(mode)));
+                               set_value(i, new_Const(get_mode_null(mode)));
                        } else if (env->variants[i] == TR_MUL) {
-                               set_value(i, new_Const(mode, get_mode_one(mode)));
+                               set_value(i, new_Const(get_mode_one(mode)));
                        }
                }
                mature_immBlock(start_block);
@@ -349,7 +349,6 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
                        set_Tuple_pred(call, pn_Call_X_regular,        jmp);
                        set_Tuple_pred(call, pn_Call_X_except,         bad);
                        set_Tuple_pred(call, pn_Call_T_result,         tuple);
-                       set_Tuple_pred(call, pn_Call_M_except,         mem);
                        set_Tuple_pred(call, pn_Call_P_value_res_base, bad);
 
                        for (i = 0; i < env->n_ress; ++i) {
@@ -419,31 +418,34 @@ static void do_opt_tail_rec(ir_graph *irg, tr_env *env) {
  *
  * @return non-zero if it's ok to do tail recursion
  */
-static int check_lifetime_of_locals(ir_graph *irg) {
-       ir_node *irg_frame, *irg_val_param_base;
+static int check_lifetime_of_locals(ir_graph *irg)
+{
+       ir_node *irg_frame;
        int i;
+       ir_type *frame_tp = get_irg_frame_type(irg);
 
        irg_frame = get_irg_frame(irg);
        for (i = get_irn_n_outs(irg_frame) - 1; i >= 0; --i) {
                ir_node *succ = get_irn_out(irg_frame, i);
 
-               if (is_Sel(succ) && is_address_taken(succ))
-                       return 0;
-       }
-
-       /* Check if we have compound arguments.
-          For now, we cannot handle them, */
-       irg_val_param_base = get_irg_value_param_base(irg);
-       if (get_irn_n_outs(irg_val_param_base) > 0)
-               return 0;
+               if (is_Sel(succ)) {
+                       /* Check if we have compound arguments.
+                          For now, we cannot handle them, */
+                       if (get_entity_owner(get_Sel_entity(succ)) != frame_tp)
+                               return 0;
 
+                       if (is_address_taken(succ))
+                               return 0;
+               }
+       }
        return 1;
 }
 
 /**
  * Examine irn and detect the recursion variant.
  */
-static tail_rec_variants find_variant(ir_node *irn, ir_node *call) {
+static tail_rec_variants find_variant(ir_node *irn, ir_node *call)
+{
        ir_node           *a, *b;
        tail_rec_variants va, vb, res;
 
@@ -570,7 +572,8 @@ 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) {
+int opt_tail_rec_irg(ir_graph *irg)
+{
        tr_env            env;
        ir_node           *end_block;
        int               i, n_ress, n_tail_calls = 0;
@@ -578,12 +581,13 @@ int opt_tail_rec_irg(ir_graph *irg) {
        ir_type           *mtd_type, *call_type;
        ir_entity         *ent;
 
+       FIRM_DBG_REGISTER(dbg, "firm.opt.tailrec");
+
        assure_irg_outs(irg);
 
        if (! check_lifetime_of_locals(irg))
                return 0;
 
-
        ent      = get_irg_entity(irg);
        mtd_type = get_entity_type(ent);
     n_ress   = get_method_n_ress(mtd_type);
@@ -704,10 +708,16 @@ int opt_tail_rec_irg(ir_graph *irg) {
        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);
+}
+
 /*
  * optimize tail recursion away
  */
-void opt_tail_recursion(void) {
+void opt_tail_recursion(void)
+{
        int i;
        int n_opt_applications = 0;
        ir_graph *irg;
@@ -729,3 +739,8 @@ void opt_tail_recursion(void) {
        DB((dbg, LEVEL_1, "Performed tail recursion for %d of %d graphs\n",
            n_opt_applications, get_irp_n_irgs()));
 }
+
+ir_prog_pass_t *opt_tail_recursion_pass(const char *name)
+{
+       return def_prog_pass(name ? name : "tailrec", opt_tail_recursion);
+}