* @brief Tail-recursion call optimization.
* @date 08.06.2004
* @author Michael Beck
- * @version $Id$
*/
#include "config.h"
#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
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);
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);
}
/* 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);
/* 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));
/*
* 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;
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);
/* 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;
/* 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));
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);
}
/*
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)