From: Andreas Zwinkau Date: Thu, 27 Oct 2011 08:21:17 +0000 (+0200) Subject: tailrec requires many Returns X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=55a7a1f4a435638bbd93ee9f0d4faa0c1ba6727b;p=libfirm tailrec requires many Returns Extend opt_manage framework with MANY_RETURNS condition. Since normalize_n_returns might introduce unreachable code, the order should be handled in the framework instead of the optimization. Fix opt/gap test. --- diff --git a/include/libfirm/irgraph.h b/include/libfirm/irgraph.h index 68c337f66..148b9e11c 100644 --- a/include/libfirm/irgraph.h +++ b/include/libfirm/irgraph.h @@ -462,6 +462,8 @@ typedef enum { IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE = 1U << 14, /** extended basic blocks have been formed and are up to date */ IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS = 1U << 15, + /** graph contains as many returns as possible */ + IR_GRAPH_STATE_MANY_RETURNS = 1U << 16, } ir_graph_state_t; ENUM_BITSET(ir_graph_state_t) diff --git a/ir/opt/opt_manage.c b/ir/opt/opt_manage.c index 9ae56cab4..ab9dc08c1 100644 --- a/ir/opt/opt_manage.c +++ b/ir/opt/opt_manage.c @@ -25,9 +25,13 @@ void perform_irg_optimization(ir_graph *irg, optdesc_t *opt) ir_graph_state_t required = opt->requirements; const bool dump = get_irp_optimization_dumps(); + /* It does not make sense to require both: */ + assert (!((required & IR_GRAPH_STATE_ONE_RETURN) && (required & IR_GRAPH_STATE_MANY_RETURNS))); + /* assure that all requirements for the optimization are fulfilled */ #define PREPARE(st,func) if (st & (required ^ irg->state)) {func(irg); set_irg_state(irg,st);} PREPARE(IR_GRAPH_STATE_ONE_RETURN, normalize_one_return) + PREPARE(IR_GRAPH_STATE_MANY_RETURNS, normalize_n_returns) PREPARE(IR_GRAPH_STATE_NO_CRITICAL_EDGES, remove_critical_cf_edges) PREPARE(IR_GRAPH_STATE_NO_UNREACHABLE_CODE, remove_unreachable_code) PREPARE(IR_GRAPH_STATE_NO_BADS, remove_bads) @@ -57,6 +61,7 @@ void perform_irg_optimization(ir_graph *irg, optdesc_t *opt) INVALIDATE(IR_GRAPH_STATE_NO_UNREACHABLE_CODE, nop) INVALIDATE(IR_GRAPH_STATE_NO_BADS, nop) INVALIDATE(IR_GRAPH_STATE_ONE_RETURN, nop) + INVALIDATE(IR_GRAPH_STATE_MANY_RETURNS, nop) INVALIDATE(IR_GRAPH_STATE_CONSISTENT_DOMINANCE, nop) INVALIDATE(IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE, nop) INVALIDATE(IR_GRAPH_STATE_CONSISTENT_OUTS, nop) diff --git a/ir/opt/tailrec.c b/ir/opt/tailrec.c index dc6f15983..1f1759a01 100644 --- a/ir/opt/tailrec.c +++ b/ir/opt/tailrec.c @@ -594,12 +594,6 @@ static ir_graph_state_t do_tailrec(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); @@ -661,7 +655,7 @@ static ir_graph_state_t do_tailrec(ir_graph *irg) 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) { @@ -699,9 +693,14 @@ static ir_graph_state_t do_tailrec(ir_graph *irg) return 0; } + +/* + * This tail recursion optimization works best + * if the Returns are normalized. + */ static optdesc_t opt_tailrec = { "tail-recursion", - IR_GRAPH_STATE_NO_BADS | IR_GRAPH_STATE_CONSISTENT_OUTS, + IR_GRAPH_STATE_MANY_RETURNS | IR_GRAPH_STATE_NO_BADS | IR_GRAPH_STATE_CONSISTENT_OUTS, do_tailrec, };