Extended semantics of Cond node. There are two flavors now.
[libfirm] / ir / ir / iropt.c
index 742e6a8..1dd151f 100644 (file)
@@ -6,6 +6,10 @@
 ** iropt --- optimizations intertwined with IR construction.
 */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 # include "irnode_t.h"
 # include "irgraph_t.h"
 # include "iropt_t.h"
@@ -82,14 +86,15 @@ computed_value (ir_node *n)
     break;
   case iro_Minus:
       if (ta && mode_is_float(get_irn_mode(a)))
-        res = /*tarval_minus (ta);*/ res;
+        res = tarval_neg (ta);
     break;
   case iro_Mul:
     if (ta && tb) /* tarval_mul tests for equivalent modes itself */ {
       res = tarval_mul (ta, tb);
     } else {
-      /* calls computed_value recursive and returns the 0 with proper
-         mode.  Why is this an extra case? */
+      /* a*0 = 0 or 0*b = 0:
+        calls computed_value recursive and returns the 0 with proper
+         mode. */
       tarval *v;
       if (   (tarval_classify ((v = computed_value (a))) == 0)
          || (tarval_classify ((v = computed_value (b))) == 0)) {
@@ -97,10 +102,31 @@ computed_value (ir_node *n)
       }
     }
     break;
+  case iro_Quot:
+    /* This was missing in original implementation. Why? */
+    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
+      if (tarval_classify(tb) == 0) {res = NULL; break;}
+      res = tarval_quo(ta, tb);
+    }
+    break;
+  case iro_Div:
+    /* This was missing in original implementation. Why? */
+    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
+      if (tarval_classify(tb) == 0) {res = NULL; break;}
+      res = tarval_div(ta, tb);
+    }
+    break;
+  case iro_Mod:
+    /* This was missing in original implementation. Why? */
+    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
+      if (tarval_classify(tb) == 0) {res = NULL; break;}
+      res = tarval_mod(ta, tb);
+    }
+    break;
+  /* for iro_DivMod see iro_Proj */
   case iro_Abs:
     if (ta)
-      res = /*tarval_abs (ta);*/ res;
-    /* allowed or problems with max/min ?? */
+      res = tarval_abs (ta);
     break;
   case iro_And:
     if (ta && tb) {
@@ -125,14 +151,15 @@ 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_neg (ta); } break;
   case iro_Shl: if (ta && tb) { res = tarval_shl (ta, tb); } break;
+    /* tarval_shr is faulty !! */
   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_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_Conv:if (ta)       { res = tarval_convert_to (ta, get_irn_mode (n)); }
     break;
-  case iro_Proj:
+  case iro_Proj:  /* iro_Cmp */
     {
       ir_node *aa, *ab;
 
@@ -195,6 +222,16 @@ computed_value (ir_node *n)
              res = tarval_from_long (mode_b, get_Proj_proj(n) & irpn_Ne);
          }
        }
+      } else if (get_irn_op(a) == op_DivMod) {
+        ta = value_of(get_DivMod_left(a));
+        tb = value_of(get_DivMod_right(a));
+       if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
+         if (tarval_classify(tb) == 0) {res = NULL; break;}
+         if (get_Proj_proj(n)== 0) /* Div */
+           res = tarval_div(ta, tb);
+         else /* Mod */
+           res = tarval_mod(ta, tb);
+       }
       } else {
         /* printf(" # comp_val: Proj node, not optimized\n"); */
       }
@@ -260,15 +297,18 @@ equivalent_node (ir_node *n)
       /* 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;
        }
@@ -614,7 +654,7 @@ transform_node (ir_node *n)
        set_Tuple_pred(n, 0, jmp);
        set_Tuple_pred(n, 1, new_Bad());
       }
-    } else if (ta && (get_irn_mode(a) == mode_I)) {
+    } else if (ta && (get_irn_mode(a) == mode_I) && (get_Cond_kind(n) == dense)) {
       /* I don't want to allow Tuples smaller than the biggest Proj.
          Also this tuple might get really big...
          I generate the Jmp here, and remember it in link.  Link is used
@@ -658,7 +698,8 @@ transform_node (ir_node *n)
         set_Proj_proj(n, 0);
     } else if (   (get_irn_op(a) == op_Cond)
                && (get_irn_mode(get_Cond_selector(a)) == mode_I)
-               && value_of(a)) {
+              && value_of(a)
+              && (get_Cond_kind(a) == dense)) {
       /* The Cond is a Switch on a Constant */
       if (get_Proj_proj(n) == tv_val_CHIL(value_of(a))) {
         /* The always taken branch, reuse the existing Jmp. */
@@ -709,7 +750,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.                                             */
@@ -761,8 +802,7 @@ vt_cmp (const void *elt, const void *key)
     return (get_irn_symconst_attr(a).num != get_irn_symconst_attr(b).num)
       || (get_irn_symconst_attr(a).tori.typ != get_irn_symconst_attr(b).tori.typ);
   case iro_Call:
-    return (get_irn_call_attr(a)->kind != get_irn_call_attr(b)->kind)
-      || (get_irn_call_attr(a)->arity != get_irn_call_attr(b)->arity);
+    return (get_irn_call_attr(a) != get_irn_call_attr(b));
   case iro_Sel:
     return (get_irn_sel_attr(a).ent->kind != get_irn_sel_attr(b).ent->kind)
       || (get_irn_sel_attr(a).ent->name != get_irn_sel_attr(b).ent->name)
@@ -973,7 +1013,6 @@ optimize (ir_node *n)
 ir_node *
 optimize_in_place (ir_node *n)
 {
-
   tarval *tv;
   ir_node *old_n = n;
 
@@ -1002,7 +1041,7 @@ optimize_in_place (ir_node *n)
   }
 
   /* remove unnecessary nodes */
-  //if (get_opt_constant_folding())
+  /*if (get_opt_constant_folding()) */
   if (get_opt_constant_folding() || get_irn_op(n) == op_Phi)
     n = equivalent_node (n);
 
@@ -1028,12 +1067,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;
 }