CVS:
[libfirm] / ir / ir / iropt.c
index aebdb31..742e6a8 100644 (file)
@@ -6,11 +6,18 @@
 ** iropt --- optimizations intertwined with IR construction.
 */
 
-# include "iropt.h"
+# 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"
 
 /* Trivial inlineable routine for copy propagation.
    Does follow Ids, needed to optimize inlined code. */
@@ -21,7 +28,6 @@ follow_Id (ir_node *n)
   return n;
 }
 
-
 static inline tarval *
 value_of (ir_node *n)
 {
@@ -31,9 +37,8 @@ value_of (ir_node *n)
     return NULL;
 }
 
-
 /* if n can be computed, return the value, else NULL. Performs
-   constant Folding. GL: Only if n is arithmetic operator? */
+   constant folding. GL: Only if n is arithmetic operator? */
 tarval *
 computed_value (ir_node *n)
 {
@@ -95,7 +100,7 @@ computed_value (ir_node *n)
   case iro_Abs:
     if (ta)
       res = /*tarval_abs (ta);*/ res;
-    /* allowded or problems with max/min ?? */
+    /* allowed or problems with max/min ?? */
     break;
   case iro_And:
     if (ta && tb) {
@@ -120,12 +125,12 @@ computed_value (ir_node *n)
     }
     break;
   case iro_Eor: if (ta && tb) { res = tarval_eor (ta, tb); } break;
-  case iro_Not: if(ta) { /*res = tarval_not (ta)*/; } break;
+  case iro_Not: if (ta)       { /*res = tarval_not (ta)*/; } break;
   case iro_Shl: if (ta && tb) { res = tarval_shl (ta, tb); } break;
   case iro_Shr: if (ta && tb) { res = tarval_shr (ta, tb); } break;
   case iro_Shrs: if(ta && tb) { /*res = tarval_shrs (ta, tb)*/; } break;
-  case iro_Rot: if(ta && tb) { /*res = tarval_rot (ta, tb)*/; } break;
-  case iro_Conv: if (ta) { res = tarval_convert_to (ta, get_irn_mode (n)); }
+  case iro_Rot: if (ta && tb) { /*res = tarval_rot (ta, tb)*/; } break;
+  case iro_Conv: if(ta)    { res = tarval_convert_to (ta, get_irn_mode (n)); }
     break;
   case iro_Proj:
     {
@@ -244,28 +249,26 @@ equivalent_node (ir_node *n)
     a = get_unop_op(n);
   }
 
-
   /* skip unnecessary nodes. */
   switch (get_irn_opcode (n)) {
   case iro_Block:
     {
-      /* The Block constructor does not call optimize, therefore
-         dead blocks are not removed without an extra optimizing
-         pass through the graph. */
+      /* The Block constructor does not call optimize, but mature_block
+        calls the optimization. */
       assert(get_Block_matured(n));
 
-      /* a single entry Region following a single exit Region 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.   */
       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) {
        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 */
-
        for (i = 0; i < get_Block_n_cfgpreds(n); i++) {
          if (!is_Bad(get_Block_cfgpred(n, i))) break;
        }
@@ -275,18 +278,13 @@ equivalent_node (ir_node *n)
     }
     break;
 
-  case iro_Jmp:  /* GL: ??? Why not same for op_Raise?? */
+  case iro_Jmp:  /* GL: Why not same for op_Raise?? */
     /* unreachable code elimination */
     if (is_Bad(get_nodes_Block(n)))  n = new_Bad();
     break;
-  /* GL: Why isn't there a case that checks whether input ot Cond is
-     constant true or false?  For unreachable code elimination
-     is this done in Proj? It's not here as it generates a new node,
-     a Jmp. It is in transform_node. *
-  case iro_Cond:
-    break;
-  */
-    /* remove stuff as x+0, x*1 x&true ... constant expression evaluation */
+  /* We do not evaluate Cond here as we replace it by a new node, a Jmp.
+     See cases for iro_Cond and iro_Proj in transform_node. */
+  /** remove stuff as x+0, x*1 x&true ... constant expression evaluation **/
   case iro_Or:  if (a == b) {n = a; break;}
   case iro_Add:
   case iro_Eor:
@@ -377,6 +375,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 */
@@ -422,14 +422,14 @@ equivalent_node (ir_node *n)
         /* skip Id's */
         set_Phi_pred(n, i, first_val);
        if (   (first_val != n)                            /* not self pointer */
-            && (get_irn_op(first_val) != op_Bad)      /* value not dead */
+              && (get_irn_op(first_val) != op_Bad)        /* value not dead */
             && !(is_Bad (get_Block_cfgpred(block, i))) ) { /* not dead control flow */
          break;                         /* then found first value. */
        }
       }
 
-      /* A totally Bad or self-referencing Phi */
-      if (i > n_preds) { n = new_Bad();  break; }
+      /* A totally Bad or self-referencing Phi (we didn't break the above loop) */
+      if (i >= n_preds) { n = new_Bad();  break; }
 
       scnd_val = NULL;
 
@@ -448,12 +448,13 @@ 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)
+       while (++i < n_preds) {
          set_Phi_pred(n, i, follow_Id(get_Phi_pred(n, i)));
+       }
       }
     }
     break;
@@ -507,7 +508,7 @@ equivalent_node (ir_node *n)
        if ( get_Proj_proj(n) <= get_Tuple_n_preds(a) ) {
          n = get_Tuple_pred(a, get_Proj_proj(n));
        } else {
-          assert(0); /* This should not happen?! (GL added this assert) */
+          assert(0); /* This should not happen! (GL added this assert) */
          n = new_Bad();
        }
       } else if (get_irn_mode(n) == mode_X &&
@@ -529,7 +530,6 @@ equivalent_node (ir_node *n)
 } /* end equivalent_node() */
 
 
-#if 0
 /* tries several [inplace] [optimizing] transformations and returns a
    equivalent node.  The difference to equivalent_node is that these
    transformations _do_ generate new nodes, and thus the old node must
@@ -538,16 +538,18 @@ static ir_node *
 transform_node (ir_node *n)
 {
 
-  ir_node *a, *b;
+  ir_node *a = NULL, *b;
   tarval *ta, *tb;
 
   switch (get_irn_opcode(n)) {
   case iro_DivMod: {
+
     int evaluated = 0;
-    ir_mode *mode = get_irn_mode(a);
+    ir_mode *mode;
 
     a = get_DivMod_left(n);
     b = get_DivMod_right(n);
+    mode = get_irn_mode(a);
 
     if (!(   mode_is_int(get_irn_mode(a))
          && mode_is_int(get_irn_mode(b))))
@@ -585,9 +587,10 @@ transform_node (ir_node *n)
       ir_node *mem = get_DivMod_mem(n);
       turn_into_tuple(n, 4);
       set_Tuple_pred(n, 0, mem);
-      set_Tuple_pred(n, 1, new_Bad());
+      set_Tuple_pred(n, 1, new_Bad());  /* no exception */
       set_Tuple_pred(n, 2, a);
       set_Tuple_pred(n, 3, b);
+      assert(get_nodes_Block(n));
     }
   }
   break;
@@ -596,7 +599,6 @@ transform_node (ir_node *n)
     /* Replace the Cond by a Jmp if it branches on a constant
        condition. */
     ir_node *jmp;
-
     a = get_Cond_selector(n);
     ta = value_of(a);
 
@@ -618,14 +620,19 @@ transform_node (ir_node *n)
          I generate the Jmp here, and remember it in link.  Link is used
          when optimizing Proj. */
       set_irn_link(n, new_r_Jmp(current_ir_graph, get_nodes_Block(n)));
-    } else if (   ((get_irn_op(get_Cond_selector(n)) == op_Eor)
-                   /* || (get_irn_op(get_Cond_selector(a)) == op_Not)*/)
+    } else if (   (get_irn_op(get_Cond_selector(n)) == op_Eor)
                && (get_irn_mode(get_Cond_selector(n)) == mode_b)
                && (tarval_classify(computed_value(get_Eor_right(a))) == 1)) {
       /* The Eor is a negate.  Generate a new Cond without the negate,
          simulate the negate by exchanging the results. */
       set_irn_link(n, new_r_Cond(current_ir_graph, get_nodes_Block(n),
                                 get_Eor_left(a)));
+    } else if (   (get_irn_op(get_Cond_selector(n)) == op_Not)
+               && (get_irn_mode(get_Cond_selector(n)) == mode_b)) {
+      /* A Not before the Cond.  Generate a new Cond without the Not,
+         simulate the Not by exchanging the results. */
+      set_irn_link(n, new_r_Cond(current_ir_graph, get_nodes_Block(n),
+                                get_Not_op(a)));
     }
   }
   break;
@@ -638,8 +645,8 @@ transform_node (ir_node *n)
         && get_irn_op(get_irn_link(a)) == op_Cond) {
     /* Use the better Cond if the Proj projs from a Cond which get's
        its result from an Eor/Not. */
-      assert (   ((get_irn_op(get_Cond_selector(a)) == op_Eor)
-                  /* || (get_irn_op(get_Cond_selector(a)) == op_Not)*/)
+      assert (   (   (get_irn_op(get_Cond_selector(a)) == op_Eor)
+                    || (get_irn_op(get_Cond_selector(a)) == op_Not))
               && (get_irn_mode(get_Cond_selector(a)) == mode_b)
              && (get_irn_op(get_irn_link(a)) == op_Cond)
               && (get_Cond_selector(get_irn_link(a)) ==
@@ -666,7 +673,7 @@ transform_node (ir_node *n)
     }
   }
   break;
-  case iro_Eor: {
+  case iro_Eor: { /* @@@ not tested as boolean Eor not allowed any more. */
     a = get_Eor_left(n);
     b = get_Eor_right(n);
 
@@ -674,7 +681,7 @@ transform_node (ir_node *n)
        && (get_irn_op(a) == op_Proj)
         && (get_irn_mode(a) == mode_b)
        && (tarval_classify (computed_value (b)) == 1)
-       && (get_irn_op(get_Proj_pred(a)) == iro_Cmp))
+       && (get_irn_op(get_Proj_pred(a)) == op_Cmp))
       /* The Eor negates a Cmp. The Cmp has the negated result anyways! */
       n = new_r_Proj(current_ir_graph, get_nodes_Block(n), get_Proj_pred(a),
                      mode_b, get_negated_pnc(get_Proj_proj(a)));
@@ -691,7 +698,7 @@ transform_node (ir_node *n)
     if (   (get_irn_mode(n) == mode_b)
        && (get_irn_op(a) == op_Proj)
         && (get_irn_mode(a) == mode_b)
-       && (get_irn_op(get_Proj_pred(a)) == iro_Cmp))
+       && (get_irn_op(get_Proj_pred(a)) == op_Cmp))
       /* We negate a Cmp. The Cmp has the negated result anyways! */
       n = new_r_Proj(current_ir_graph, get_nodes_Block(n), get_Proj_pred(a),
                      mode_b, get_negated_pnc(get_Proj_proj(a)));
@@ -699,8 +706,8 @@ transform_node (ir_node *n)
   break;
   default: ;
   }
+  return n;
 }
-#endif
 
 /***************** Common Subexpression Elimination *****************/
 
@@ -868,11 +875,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;
 }
 
@@ -886,6 +902,9 @@ optimize (ir_node *n)
   tarval *tv;
   ir_node *old_n = n;
 
+  /* Allways optimize Phi nodes: part of the construction. */
+  if ((!get_optimize()) && (get_irn_op(n) != op_Phi)) return n;
+
   /* if not optimize return n */
   if (n == NULL) {
     printf(" attention: empty node!!! \n");
@@ -902,10 +921,10 @@ optimize (ir_node *n)
         /* evaluation was succesful -- replace the node. */
        obstack_free (current_ir_graph->obst, n);
        return new_Const (get_tv_mode (tv), tv);
-        /* xprintf("* optimize: computed node %I\n", n->op->name); */
       }
     }
   }
+
   /* remove unnecessary nodes */
   if (get_opt_constant_folding() || get_irn_op(n) == op_Phi)
     n = equivalent_node (n);
@@ -915,31 +934,26 @@ optimize (ir_node *n)
   /* The block input is used to distinguish different subexpressions. Right
      now all nodes are pinned to blocks, i.e., the cse only finds common
      subexpressions within a block. */
-
   if (get_opt_cse())
     n = identify (current_ir_graph->value_table, n);
-
   /* identify found a cse, so deallocate the old node. */
   if (n != old_n) {
     obstack_free (current_ir_graph->obst, old_n);
     /* The AmRoq fiasco returns n here.  Martin's version doesn't. */
   }
 
-#if 0
-  /* Some more constant expression evaluation. */
+  /* Some more constant expression evaluation that does not allow to
+     free the node. */
   if (get_opt_constant_folding())
     n = transform_node (n);
-#endif
 
   /* Remove nodes with dead (Bad) input. */
   n = gigo (n);
   /* Now we can verify the node, as it has no dead inputs any more. */
-  ir_vrfy(n);
+  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. */
     n = identify_remember (current_ir_graph->value_table, n);
   }
 
@@ -949,7 +963,6 @@ optimize (ir_node *n)
     pdeq_putr (current_ir_graph->keep.living, n);
   }
 #endif
-
   return n;
 }
 
@@ -964,6 +977,8 @@ 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? */
@@ -978,12 +993,16 @@ 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)
     n = equivalent_node (n);
 
@@ -992,7 +1011,6 @@ optimize_in_place (ir_node *n)
   /* The block input is used to distinguish different subexpressions.  Right
      now all nodes are pinned to blocks, i.e., the cse only finds common
      subexpressions within a block. */
-
   if (get_opt_cse())
     n = identify (current_ir_graph->value_table, n);
 
@@ -1001,16 +1019,14 @@ optimize_in_place (ir_node *n)
     /* The AmRoq fiasco returns n here.  Martin's version doesn't. */
   }
 
-#if 0
   /* Some more constant expression evaluation. */
   if (get_opt_constant_folding())
     n = transform_node (n);
-#endif
 
   /* Remove nodes with dead (Bad) input. */
   n = gigo (n);
   /* Now we can verify the node, as it has no dead inputs any more. */
-  ir_vrfy(n);
+  irn_vrfy(n);
 
   /* Now we have a legal, useful node. Enter it in hash table for cse */
   if (get_opt_cse()) {