* @brief Tail-recursion call optimization.
* @date 08.06.2004
* @author Michael Beck
- * @version $Id$
*/
#include "config.h"
#include "irhooks.h"
#include "ircons_t.h"
#include "irpass.h"
+#include "opt_manage.h"
-DEBUG_ONLY(static firm_dbg_module_t *dbg);
+DEBUG_ONLY(static firm_dbg_module_t *dbg;)
/**
* the environment for collecting data
assert(env->n_tail_calls > 0);
- /* we add new nodes, so the outs are inconsistent */
- set_irg_outs_inconsistent(irg);
-
/* we add new blocks and change the control flow */
- set_irg_doms_inconsistent(irg);
- set_irg_extblk_inconsistent(irg);
-
- /* we add a new loop */
- set_irg_loopinfo_inconsistent(irg);
-
- /* calls are removed */
- set_trouts_inconsistent();
+ clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE
+ | IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS);
/* we must build some new nodes WITHOUT CSE */
set_optimize(0);
if (n_params > 0) {
ir_node *calls;
ir_node *args;
- ir_node *args_bl;
NEW_ARR_A(ir_node **, call_params, env->n_tail_calls);
/* build new Proj's and Phi's */
args = get_irg_args(irg);
- args_bl = get_nodes_block(args);
for (i = 0; i < n_params; ++i) {
ir_mode *mode = get_type_mode(get_method_param_type(method_tp, i));
}
/* tail recursion was done, all info is invalid */
- set_irg_doms_inconsistent(irg);
- set_irg_outs_inconsistent(irg);
- set_irg_extblk_inconsistent(irg);
- set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
- set_trouts_inconsistent();
+ clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE
+ | IR_GRAPH_STATE_CONSISTENT_LOOPINFO
+ | IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS);
set_irg_callee_info_state(irg, irg_callee_info_inconsistent);
set_optimize(rem);
}
if (n_locs > 0) {
- ir_node *bad, *start_block;
+ ir_node *start_block;
ir_node **in;
ir_mode **modes;
mature_immBlock(start_block);
/* no: we can kill all returns */
- bad = get_irg_bad(irg);
-
for (p = env->rets; p; p = n) {
ir_node *block = get_nodes_block(p);
ir_node *call, *mem, *jmp, *tuple;
set_optimize(rem);
for (i = 0; i < env->n_ress; ++i) {
+ ir_mode *mode = modes[i];
if (env->variants[i] != TR_DIRECT) {
- in[i] = get_r_value(irg, i, modes[i]);
+ in[i] = get_r_value(irg, i, mode);
} else {
- in[i] = bad;
+ in[i] = new_r_Bad(irg, mode);
}
}
/* create a new tuple for the return values */
tuple = new_r_Tuple(block, env->n_ress, in);
- turn_into_tuple(call, pn_Call_max);
- 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, bad);
- set_Tuple_pred(call, pn_Call_T_result, tuple);
+ 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));
+ set_Tuple_pred(call, pn_Call_T_result, tuple);
for (i = 0; i < env->n_ress; ++i) {
ir_node *res = get_Return_res(p, i);
}
}
- exchange(p, bad);
+ exchange(p, new_r_Bad(irg, mode_X));
}
/* finally fix all other returns */
}
ssa_cons_finish(irg);
} else {
- ir_node *bad = get_irg_bad(irg);
+ ir_node *bad = new_r_Bad(irg, mode_X);
/* no: we can kill all returns */
for (p = env->rets; p; p = n) {
/*
* convert simple tail-calls into loops
*/
-int opt_tail_rec_irg(ir_graph *irg)
+static ir_graph_state_t do_tailrec(ir_graph *irg)
{
tr_env env;
ir_node *end_block;
FIRM_DBG_REGISTER(dbg, "firm.opt.tailrec");
- assure_irg_outs(irg);
-
if (! check_lifetime_of_locals(irg))
return 0;
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;
break;
}
if (var == TR_DIRECT)
- var = env.variants[j];
+ var = env.variants[j];
else if (env.variants[j] == TR_DIRECT)
env.variants[j] = var;
if (env.variants[j] != var) {
}
ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
current_ir_graph = rem;
- return n_tail_calls;
+ return 0;
+}
+
+
+/*
+ * This tail recursion optimization works best
+ * if the Returns are normalized.
+ */
+static optdesc_t opt_tailrec = {
+ "tail-recursion",
+ IR_GRAPH_STATE_MANY_RETURNS | IR_GRAPH_STATE_NO_BADS | IR_GRAPH_STATE_CONSISTENT_OUTS,
+ do_tailrec,
+};
+
+int opt_tail_rec_irg(ir_graph *irg) {
+ perform_irg_optimization(irg, &opt_tailrec);
+ return 1; /* conservatively report changes */
}
ir_graph_pass_t *opt_tail_rec_irg_pass(const char *name)