introduce opt_manage framework
authorAndreas Zwinkau <zwinkau@kit.edu>
Wed, 7 Sep 2011 12:59:03 +0000 (14:59 +0200)
committerAndreas Zwinkau <zwinkau@kit.edu>
Wed, 14 Sep 2011 10:42:06 +0000 (12:42 +0200)
This is a basic implementation of http://libfirm.org/PhaseManagement

Introduces remove_unreachable_blocks as an extra API function,
which does a subset of optimize_graph_df.

include/libfirm/irgraph.h
ir/ir/unreachable.c
ir/opt/opt_manage.c [new file with mode: 0644]
ir/opt/opt_manage.h [new file with mode: 0644]

index 03a916e..39375ed 100644 (file)
@@ -514,6 +514,19 @@ typedef enum {
         * Set IMPLICIT_BITFIELD_MASKING, if the lowering phase must insert masking operations.
         */
        IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING  = 1U << 5,
+
+       IR_GRAPH_STATE_NO_CRITICAL_EDGES        = 1U << 6,
+       IR_GRAPH_STATE_NO_BAD_BLOCKS            = 1U << 7, // TODO must be inverse of IR_GRAPH_STATE_BAD_BLOCK
+       IR_GRAPH_STATE_NO_UNREACHABLE_BLOCKS    = 1U << 8,
+       IR_GRAPH_STATE_ONE_RETURN               = 1U << 9,
+       IR_GRAPH_STATE_CONSISTENT_DOMINANCE     = 1U << 10,
+       IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE = 1U << 11,
+       IR_GRAPH_STATE_CONSISTENT_OUT_EDGES     = 1U << 12,
+       IR_GRAPH_STATE_CONSISTENT_OUTS          = 1U << 13,
+       IR_GRAPH_STATE_CONSISTENT_LOOPINFO      = 1U << 14,
+       IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE  = 1U << 15,
+       IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS    = 1U << 16,
+       IR_GRAPH_STATE_BROKEN_FOR_VERIFIER      = 1U << 17,
 } ir_graph_state_t;
 ENUM_BITSET(ir_graph_state_t)
 
index 780ac54..15692ec 100644 (file)
@@ -66,5 +66,7 @@ void remove_unreachable_blocks(ir_graph *irg)
        if (changed) {
                edges_deactivate(irg);
                set_irg_outs_inconsistent(irg);
+               clear_irg_state(irg, IR_GRAPH_STATE_NO_BAD_BLOCKS);
        }
+       set_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_BLOCKS);
 }
diff --git a/ir/opt/opt_manage.c b/ir/opt/opt_manage.c
new file mode 100644 (file)
index 0000000..8e256c8
--- /dev/null
@@ -0,0 +1,97 @@
+#include "config.h"
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include "irgraph_t.h"
+
+#include "iroptimize.h"
+#include "irgopt.h"
+#include "irdom.h"
+#include "iredges.h"
+#include "irouts.h"
+#include "irverify.h"
+#include "irdump.h"
+#include "opt_manage.h"
+
+// TODO some API to enable dumping
+static const bool dump_opts = false;
+
+static void deactivate_entity_usage(ir_graph *irg)
+{
+       set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
+}
+
+static void nop(ir_graph *irg) {
+       (void)irg;
+}
+
+void perform_irg_optimization(ir_graph *irg, optdesc_t *opt)
+{
+       ir_graph_state_t new_irg_state;
+       ir_graph_state_t required = opt->requirements;
+       const bool dump = get_irp_optimization_dumps();
+
+       /* no bad block requires no unreachable code */
+       if (required & IR_GRAPH_STATE_NO_BAD_BLOCKS)
+               required |= IR_GRAPH_STATE_NO_UNREACHABLE_BLOCKS;
+
+       /** Some workarounds because information is currently duplicated */
+       // FIXME should not be necessary!
+       if (dom_inconsistent == get_irg_dom_state(irg))
+               clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE);
+       if (outs_inconsistent == get_irg_outs_state(irg))
+               clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS);
+       if (loopinfo_inconsistent == get_irg_loopinfo_state(irg))
+               clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_LOOPINFO);
+       if (is_irg_state(irg, IR_GRAPH_STATE_BAD_BLOCK))
+               clear_irg_state(irg, IR_GRAPH_STATE_NO_BAD_BLOCKS);
+       if (ir_entity_usage_not_computed == get_irg_entity_usage_state(irg))
+               clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE);
+       clear_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_BLOCKS); // FIXME seems to incorrect sometimes
+
+       /* 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_NO_CRITICAL_EDGES,        remove_critical_cf_edges)
+       PREPARE(IR_GRAPH_STATE_NO_UNREACHABLE_BLOCKS,    remove_unreachable_blocks)
+       PREPARE(IR_GRAPH_STATE_NO_BAD_BLOCKS,            remove_bads)
+       PREPARE(IR_GRAPH_STATE_CONSISTENT_DOMINANCE,     assure_doms)
+       PREPARE(IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE, assure_postdoms)
+       PREPARE(IR_GRAPH_STATE_CONSISTENT_OUT_EDGES,     edges_assure)
+       PREPARE(IR_GRAPH_STATE_CONSISTENT_OUTS,          assure_irg_outs)
+       PREPARE(IR_GRAPH_STATE_CONSISTENT_LOOPINFO,      assure_cf_loop)
+       PREPARE(IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE,  assure_irg_entity_usage_computed)
+       PREPARE(IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS,    compute_extbb)
+
+       /* now all the requirements for the optimization are fulfilled */
+       if (dump_opts)
+               dump_ir_graph(irg, opt->name);
+
+       new_irg_state = opt->optimization(irg);
+
+       if (dump_opts)
+               dump_ir_graph(irg, opt->name);
+
+       /* unless the optimization returned that some state is retained,
+        * we disable the corresponding irg state.
+        * Since we currently duplicate information, sometimes another func must be called too.
+        */
+#define INVALIDATE(state,func) if (!(state & new_irg_state)) {clear_irg_state(irg,state); func(irg);}
+       INVALIDATE(IR_GRAPH_STATE_NO_CRITICAL_EDGES,        nop)
+       INVALIDATE(IR_GRAPH_STATE_NO_UNREACHABLE_BLOCKS,    nop)
+       INVALIDATE(IR_GRAPH_STATE_NO_BAD_BLOCKS,            nop)
+       INVALIDATE(IR_GRAPH_STATE_ONE_RETURN,               nop)
+       INVALIDATE(IR_GRAPH_STATE_CONSISTENT_DOMINANCE,     set_irg_doms_inconsistent)
+       INVALIDATE(IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE, set_irg_postdoms_inconsistent)
+       INVALIDATE(IR_GRAPH_STATE_CONSISTENT_OUTS,          set_irg_outs_inconsistent)
+       INVALIDATE(IR_GRAPH_STATE_CONSISTENT_OUT_EDGES,     edges_deactivate)
+       INVALIDATE(IR_GRAPH_STATE_CONSISTENT_LOOPINFO,      set_irg_loopinfo_inconsistent)
+       INVALIDATE(IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE,  deactivate_entity_usage)
+       INVALIDATE(IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS,    set_irg_extblk_inconsistent)
+
+       if (!(new_irg_state & IR_GRAPH_STATE_BROKEN_FOR_VERIFIER)) {
+               irg_verify(irg, VERIFY_ENFORCE_SSA);
+       }
+
+}
diff --git a/ir/opt/opt_manage.h b/ir/opt/opt_manage.h
new file mode 100644 (file)
index 0000000..21e1864
--- /dev/null
@@ -0,0 +1,28 @@
+#include "config.h"
+
+#include <stdbool.h>
+
+#include "irgraph_t.h"
+
+typedef struct optdesc_t {
+       /**
+        * The short name of the optimization
+        *
+        * Should not contain spaces, since it is used for the dumper filenames.
+        */
+       const char * const name;
+
+       /**
+        * required irg_state for this optimization
+        */
+       ir_graph_state_t requirements;
+
+       /**
+        * The optimization function itself
+        *
+        * @returns  zero by default; set some flags, if you guarantee some irg_state properties
+        **/
+       ir_graph_state_t (*const optimization)(ir_graph *irg);
+} optdesc_t;
+
+void perform_irg_optimization(ir_graph *irg, optdesc_t *opt);