tailrec requires many Returns
authorAndreas Zwinkau <zwinkau@kit.edu>
Thu, 27 Oct 2011 08:21:17 +0000 (10:21 +0200)
committerAndreas Zwinkau <zwinkau@kit.edu>
Thu, 27 Oct 2011 08:38:03 +0000 (10:38 +0200)
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.

include/libfirm/irgraph.h
ir/opt/opt_manage.c
ir/opt/tailrec.c

index 68c337f..148b9e1 100644 (file)
@@ -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)
 
index 9ae56ca..ab9dc08 100644 (file)
@@ -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)
index dc6f159..1f1759a 100644 (file)
@@ -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,
 };