end block can not be optimized away any more.
[libfirm] / ir / ir / iropt.c
index 54494a6..6a42358 100644 (file)
@@ -6,11 +6,19 @@
 ** iropt --- optimizations intertwined with IR construction.
 */
 
-# include "iropt.h"
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+# include "irnode_t.h"
+# include "irgraph_t.h"
+# include "iropt_t.h"
 # include "ircons.h"
 # include "irgmod.h"
 # include "irvrfy.h"
 # include "tv.h"
+# include "tune.h"
+# include "debinfo.h"
 
 /* Make types visible to allow most efficient access */
 # include "entity_t.h"
@@ -253,17 +261,21 @@ equivalent_node (ir_node *n)
         calls the optimization. */
       assert(get_Block_matured(n));
 
-      /* a single entry Block following a single exit Block can be merged */
+      /* A single entry Block following a single exit Block can be merged,
+         if it is not the Start block. */
       /* !!! Beware, all Phi-nodes of n must have been optimized away.
-        This is true, as the block is matured before optimize is called.   */
+        This should be true, as the block is matured before optimize is called.
+         But what about Phi-cycles with the Phi0/Id that could not be resolved? */
       if (get_Block_n_cfgpreds(n) == 1
          && get_irn_op(get_Block_cfgpred(n, 0)) == op_Jmp) {
        n = get_nodes_Block(get_Block_cfgpred(n, 0));
 
-      } else if (n != current_ir_graph->start_block) {
+      } else if ((n != current_ir_graph->start_block) &&
+                (n != current_ir_graph->end_block)     ) {
        int i;
        /* If all inputs are dead, this block is dead too, except if it is
-           the start block.  This is a step of unreachable code elimination */
+           the start or end block.  This is a step of unreachable code
+          elimination */
        for (i = 0; i < get_Block_n_cfgpreds(n); i++) {
          if (!is_Bad(get_Block_cfgpred(n, i))) break;
        }
@@ -370,6 +382,8 @@ equivalent_node (ir_node *n)
            themselves.
       */
       int i, n_preds;
+
+
       ir_node *block = NULL;     /* to shutup gcc */
       ir_node *first_val = NULL; /* to shutup gcc */
       ir_node *scnd_val = NULL;  /* to shutup gcc */
@@ -408,6 +422,7 @@ equivalent_node (ir_node *n)
        }
       }
 #endif
+
       /* Find first non-self-referencing input */
       for (i = 0;  i < n_preds;  ++i) {
         first_val = follow_Id(get_Phi_pred(n, i));
@@ -421,7 +436,7 @@ equivalent_node (ir_node *n)
       }
 
       /* A totally Bad or self-referencing Phi (we didn't break the above loop) */
-      if (i > n_preds) { n = new_Bad();  break; }
+      if (i >= n_preds) { n = new_Bad();  break; }
 
       scnd_val = NULL;
 
@@ -440,8 +455,8 @@ equivalent_node (ir_node *n)
       }
 
       /* Fold, if no multiple distinct non-self-referencing inputs */
-      if (i > n_preds) {
-       n = a;
+      if (i >= n_preds) {
+       n = first_val;
       } else {
       /* skip the remaining Ids. */
        while (++i < n_preds) {
@@ -701,7 +716,7 @@ transform_node (ir_node *n)
   return n;
 }
 
-/***************** Common Subexpression Elimination *****************/
+/* **************** Common Subexpression Elimination **************** */
 
 /* Compare function for two nodes in the hash table.   Gets two     */
 /* nodes as parameters.                                             */
@@ -867,11 +882,20 @@ gigo (ir_node *node)
   if ( op != op_Block && op != op_Phi && op != op_Tuple) {
     for (i = -1; i < get_irn_arity(node); i++) {
       if (is_Bad(get_irn_n(node, i))) {
-        node = new_Bad();
-        break;
+        return new_Bad();
       }
     }
   }
+#if 0
+  /* If Block has only Bads as predecessors it's garbage. */
+  /* If Phi has only Bads as predecessors it's garbage. */
+  if (op == op_Block || op == op_Phi)  {
+    for (i = 0; i < get_irn_arity(node); i++) {
+      if (!is_Bad(get_irn_n(node, i))) break;
+    }
+    if (i = get_irn_arity(node)) node = new_Bad();
+  }
+#endif
   return node;
 }
 
@@ -956,10 +980,11 @@ optimize (ir_node *n)
 ir_node *
 optimize_in_place (ir_node *n)
 {
-
   tarval *tv;
   ir_node *old_n = n;
 
+  if (!get_optimize()) return n;
+
   /* if not optimize return n */
   if (n == NULL) {
     /* Here this is possible.  Why? */
@@ -974,15 +999,17 @@ optimize_in_place (ir_node *n)
       tv = computed_value (n);
       if (tv != NULL) {
         /* evaluation was succesful -- replace the node. */
-       return new_Const (get_tv_mode (tv), tv);
+       n = new_Const (get_tv_mode (tv), tv);
+       deb_info_copy(n, old_n, id_from_str("const_eval", 10));
+       return n;
         /* xprintf("* optimize: computed node %I\n", n->op->name);*/
       }
     }
   }
 
   /* remove unnecessary nodes */
-  if (get_opt_constant_folding())
-    //  if (get_opt_constant_folding() || get_irn_op(n) == op_Phi)
+  /*if (get_opt_constant_folding()) */
+  if (get_opt_constant_folding() || get_irn_op(n) == op_Phi)
     n = equivalent_node (n);
 
   /** common subexpression elimination **/
@@ -1007,12 +1034,11 @@ optimize_in_place (ir_node *n)
   /* Now we can verify the node, as it has no dead inputs any more. */
   irn_vrfy(n);
 
-  /* Now we have a legal, useful node. Enter it in hash table for cse */
-  if (get_opt_cse()) {
-    /* aborts ??! set/pset can not handle several hash tables??!
-       No, suddenly it works. */
+  /* Now we have a legal, useful node. Enter it in hash table for cse.
+     Blocks should be unique anyways.  (Except the successor of start:
+     is cse with the start block!) */
+  if (get_opt_cse() && (get_irn_opcode(n) != iro_Block))
     n = identify_remember (current_ir_graph->value_table, n);
-  }
 
   return n;
 }