X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Ftailrec.c;h=15932a5a9551770c0100894dc488b3b04948af55;hb=6b124543aff56817fcfe6d5b5ff181ac5c790e73;hp=61ea98b32e46fb33f3a4f5b722420c7699c1e7ee;hpb=4b734653b3f11a3182963369bb58980e4d5a62cb;p=libfirm diff --git a/ir/opt/tailrec.c b/ir/opt/tailrec.c index 61ea98b32..15932a5a9 100644 --- a/ir/opt/tailrec.c +++ b/ir/opt/tailrec.c @@ -45,6 +45,7 @@ #include "irouts.h" #include "irhooks.h" #include "ircons_t.h" +#include "irpass.h" DEBUG_ONLY(static firm_dbg_module_t *dbg); @@ -195,7 +196,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)); @@ -206,7 +207,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); @@ -216,7 +217,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_block(irg), get_irg_start(irg), mode_M, pn_Start_M); set_irg_initial_mem(irg, in[i]); ++i; @@ -226,7 +227,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) { @@ -248,11 +249,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_bl, 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); } } @@ -346,7 +347,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) { @@ -417,23 +417,24 @@ 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; + 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; } @@ -701,6 +702,11 @@ 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 */ @@ -726,3 +732,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); +}