workaround for dead CF: restart the optimization
[libfirm] / ir / opt / cfopt.c
index b504e6f..ddb8e53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -27,6 +27,8 @@
 # include "config.h"
 #endif
 
+#include "iroptimize.h"
+
 #include <assert.h>
 
 #include "plist.h"
@@ -51,7 +53,6 @@
 #include "irflag_t.h"
 #include "firmstat.h"
 
-#include "cfopt.h"
 #include "iropt_dbg.h"
 
 /*------------------------------------------------------------------*/
@@ -61,6 +62,8 @@
 /* is empty if it contains only a Jmp node.                         */
 /* Blocks can only be removed if they are not needed for the        */
 /* semantics of Phi nodes.                                          */
+/* Further, we NEVER remove labeled blocks (even if we could move   */
+/* the label.                                                       */
 /*------------------------------------------------------------------*/
 
 /**
@@ -184,7 +187,6 @@ static void merge_blocks(ir_node *node, void *ctx) {
        }
 }
 
-
 /**
  * Block walker removing control flow from dead block by
  * inspecting dominance info.
@@ -225,10 +227,14 @@ static void collect_nodes(ir_node *n, void *ctx) {
        ir_op *op = get_irn_op(n);
        merge_env *env = ctx;
 
-       if (op != op_Block) {
+       if (op == op_Block) {
+               /* mark the block as non-empty if it is labeled */
+               if (has_Block_label(n))
+                       mark_Block_block_visited(n);
+       } else {
                ir_node *b  = get_nodes_block(n);
 
-               if (op == op_Phi) {
+               if (op == op_Phi && get_irn_arity(n) > 0) {
                        /* Collect Phi nodes to compact ins along with block's ins. */
                        set_irn_link(n, get_irn_link(b));
                        set_irn_link(b, n);
@@ -307,7 +313,7 @@ static int test_whether_dispensable(ir_node *b, int pos) {
                }
 
                /* Seems to be empty. At least we detected this in collect_nodes. */
-               if (!get_irn_link(b)) {
+               if (get_irn_link(b) == NULL) {
                        /* There are no Phi nodes ==> all predecessors are dispensable. */
                        n_preds = get_Block_n_cfgpreds(pred);
                } else {
@@ -701,6 +707,7 @@ void optimize_cf(ir_graph *irg) {
        /* FIXME: is this still needed? */
        edges_deactivate(irg);
 
+restart:
        env.changed    = 0;
        env.phis_moved = 0;
 
@@ -756,11 +763,11 @@ void optimize_cf(ir_graph *irg) {
                set_irg_doms_inconsistent(irg);
                set_irg_extblk_inconsistent(irg);
                set_irg_loopinfo_inconsistent(irg);
+               goto restart;
        }
 
        /* Optimize the standard code. */
        env.changed = 0;
-       assure_doms(irg);
        irg_block_walk(get_irg_end_block(irg), optimize_blocks, remove_simple_blocks, &env);
 
        /* Walk all keep alives, optimize them if block, add to new in-array
@@ -771,7 +778,7 @@ void optimize_cf(ir_graph *irg) {
 
        /* in rare cases a node may be kept alive more than once, use the visited flag to detect this */
        inc_irg_visited(irg);
-       set_using_visited(irg);
+       set_using_irn_visited(irg);
 
        /* fix the keep alive */
        for (i = j = 0; i < n; i++) {
@@ -804,7 +811,7 @@ void optimize_cf(ir_graph *irg) {
                env.changed = 1;
        }
 
-       clear_using_visited(irg);
+       clear_using_irn_visited(irg);
 
        if (env.phis_moved) {
                /* Bad: when we moved Phi's, we might produce dead Phi nodes