new SymConst semantics
[libfirm] / ir / ir / iropt.c
index 8909f6e..c0733b1 100644 (file)
@@ -16,6 +16,7 @@
 
 # include "irnode_t.h"
 # include "irgraph_t.h"
+# include "irmode_t.h"
 # include "iropt_t.h"
 # include "ircons.h"
 # include "irgmod.h"
@@ -24,6 +25,7 @@
 # include "dbginfo_t.h"
 # include "iropt_dbg.h"
 # include "irflag_t.h"
+# include "firmstat.h"
 
 /* Make types visible to allow most efficient access */
 # include "entity_t.h"
@@ -35,7 +37,7 @@
 static INLINE ir_node *
 follow_Id (ir_node *n)
 {
-  while (intern_get_irn_op (n) == op_Id) n = get_Id_pred (n);
+  while (get_irn_op (n) == op_Id) n = get_Id_pred (n);
   return n;
 }
 
@@ -45,7 +47,7 @@ follow_Id (ir_node *n)
 static INLINE tarval *
 value_of (ir_node *n)
 {
-  if ((n != NULL) && (intern_get_irn_op(n) == op_Const))
+  if ((n != NULL) && (get_irn_op(n) == op_Const))
     return get_Const_tarval(n); /* might return tarval_bad */
   else
     return tarval_bad;
@@ -58,9 +60,9 @@ static tarval *computed_value_Const(ir_node *n)
 
 static tarval *computed_value_SymConst(ir_node *n)
 {
-  if ((get_SymConst_kind(n) == size) &&
+  if ((get_SymConst_kind(n) ==symconst_size) &&
       (get_type_state(get_SymConst_type(n))) == layout_fixed)
-    return new_tarval_from_long (get_type_size(get_SymConst_type(n)), mode_Is);
+    return new_tarval_from_long(get_type_size_bytes(get_SymConst_type(n)), mode_Is);
   return tarval_bad;
 }
 
@@ -73,8 +75,8 @@ static tarval *computed_value_Add(ir_node *n)
   tarval *tb = value_of(b);
 
   if ((ta != tarval_bad) && (tb != tarval_bad)
-        && (intern_get_irn_mode(a) == intern_get_irn_mode(b))
-        && !(get_mode_sort(intern_get_irn_mode(a)) == irms_reference)) {
+        && (get_irn_mode(a) == get_irn_mode(b))
+        && !(get_mode_sort(get_irn_mode(a)) == irms_reference)) {
     return tarval_add(ta, tb);
   }
   return tarval_bad;
@@ -89,8 +91,8 @@ static tarval *computed_value_Sub(ir_node *n)
   tarval *tb = value_of(b);
 
   if ((ta != tarval_bad) && (tb != tarval_bad)
-        && (intern_get_irn_mode(a) == intern_get_irn_mode(b))
-        && !(get_mode_sort(intern_get_irn_mode(a)) == irms_reference)) {
+        && (get_irn_mode(a) == get_irn_mode(b))
+        && !(get_mode_sort(get_irn_mode(a)) == irms_reference)) {
     return tarval_sub(ta, tb);
   }
   return tarval_bad;
@@ -101,7 +103,7 @@ static tarval *computed_value_Minus(ir_node *n)
   ir_node *a = get_Minus_op(n);
   tarval *ta = value_of(a);
 
-  if ((ta != tarval_bad) && mode_is_signed(intern_get_irn_mode(a)))
+  if ((ta != tarval_bad) && mode_is_signed(get_irn_mode(a)))
     return tarval_neg(ta);
 
   return tarval_bad;
@@ -115,7 +117,7 @@ static tarval *computed_value_Mul(ir_node *n)
   tarval *ta = value_of(a);
   tarval *tb = value_of(b);
 
-  if ((ta != tarval_bad) && (tb != tarval_bad) && (intern_get_irn_mode(a) == intern_get_irn_mode(b))) {
+  if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
     return tarval_mul(ta, tb);
   } else {
     /* a*0 = 0 or 0*b = 0:
@@ -142,7 +144,7 @@ static tarval *computed_value_Quot(ir_node *n)
   tarval *tb = value_of(b);
 
   /* This was missing in original implementation. Why? */
-  if ((ta != tarval_bad) && (tb != tarval_bad) && (intern_get_irn_mode(a) == intern_get_irn_mode(b))) {
+  if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
     if (tb != get_mode_null(get_tarval_mode(tb)))   /* div by zero: return tarval_bad */
       return tarval_quo(ta, tb);
   }
@@ -158,7 +160,7 @@ static tarval *computed_value_Div(ir_node *n)
   tarval *tb = value_of(b);
 
   /* This was missing in original implementation. Why? */
-  if ((ta != tarval_bad) && (tb != tarval_bad) && (intern_get_irn_mode(a) == intern_get_irn_mode(b))) {
+  if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
     if (tb != get_mode_null(get_tarval_mode(tb)))   /* div by zero: return tarval_bad */
       return tarval_div(ta, tb);
   }
@@ -174,7 +176,7 @@ static tarval *computed_value_Mod(ir_node *n)
   tarval *tb = value_of(b);
 
   /* This was missing in original implementation. Why? */
-  if ((ta != tarval_bad) && (tb != tarval_bad) && (intern_get_irn_mode(a) == intern_get_irn_mode(b))) {
+  if ((ta != tarval_bad) && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
     if (tb != get_mode_null(get_tarval_mode(tb)))   /* div by zero: return tarval_bad */
       return tarval_mod(ta, tb);
   }
@@ -320,7 +322,7 @@ static tarval *computed_value_Conv(ir_node *n)
   tarval *ta = value_of(a);
 
   if (ta != tarval_bad)
-    return tarval_convert_to(ta, intern_get_irn_mode(n));
+    return tarval_convert_to(ta, get_irn_mode(n));
 
   return tarval_bad;
 }
@@ -344,7 +346,7 @@ static tarval *computed_value_Proj(ir_node *n)
      3. The predecessors are Allocs or void* constants.  Allocs never
        return NULL, they raise an exception.   Therefore we can predict
        the Cmp result. */
-  if (intern_get_irn_op(a) == op_Cmp) {
+  if (get_irn_op(a) == op_Cmp) {
     aa = get_Cmp_left(a);
     ab = get_Cmp_right(a);
 
@@ -368,34 +370,34 @@ static tarval *computed_value_Proj(ir_node *n)
        ir_node *aba = skip_nop(skip_Proj(ab));
 
        if (   (   (/* aa is ProjP and aaa is Alloc */
-                      (intern_get_irn_op(aa) == op_Proj)
-                   && (mode_is_reference(intern_get_irn_mode(aa)))
-                   && (intern_get_irn_op(aaa) == op_Alloc))
+                      (get_irn_op(aa) == op_Proj)
+                   && (mode_is_reference(get_irn_mode(aa)))
+                   && (get_irn_op(aaa) == op_Alloc))
                && (   (/* ab is constant void */
-                          (intern_get_irn_op(ab) == op_Const)
-                       && (mode_is_reference(intern_get_irn_mode(ab)))
-                       && (get_Const_tarval(ab) == get_mode_null(intern_get_irn_mode(ab))))
+                          (get_irn_op(ab) == op_Const)
+                       && (mode_is_reference(get_irn_mode(ab)))
+                       && (get_Const_tarval(ab) == get_mode_null(get_irn_mode(ab))))
                    || (/* ab is other Alloc */
-                          (intern_get_irn_op(ab) == op_Proj)
-                       && (mode_is_reference(intern_get_irn_mode(ab)))
-                       && (intern_get_irn_op(aba) == op_Alloc)
+                          (get_irn_op(ab) == op_Proj)
+                       && (mode_is_reference(get_irn_mode(ab)))
+                       && (get_irn_op(aba) == op_Alloc)
                        && (aaa != aba))))
            || (/* aa is void and aba is Alloc */
-                  (intern_get_irn_op(aa) == op_Const)
-               && (mode_is_reference(intern_get_irn_mode(aa)))
-               && (get_Const_tarval(aa) == get_mode_null(intern_get_irn_mode(aa)))
-               && (intern_get_irn_op(ab) == op_Proj)
-               && (mode_is_reference(intern_get_irn_mode(ab)))
-               && (intern_get_irn_op(aba) == op_Alloc)))
+                  (get_irn_op(aa) == op_Const)
+               && (mode_is_reference(get_irn_mode(aa)))
+               && (get_Const_tarval(aa) == get_mode_null(get_irn_mode(aa)))
+               && (get_irn_op(ab) == op_Proj)
+               && (mode_is_reference(get_irn_mode(ab)))
+               && (get_irn_op(aba) == op_Alloc)))
          /* 3.: */
          return new_tarval_from_long (get_Proj_proj(n) & Ne, mode_b);
       }
     }
-  } else if (intern_get_irn_op(a) == op_DivMod) {
+  } else if (get_irn_op(a) == op_DivMod) {
     tarval *tb = value_of(b = get_DivMod_right(a));
     tarval *ta = value_of(a = get_DivMod_left(a));
 
-    if ((ta != tarval_bad)  && (tb != tarval_bad) && (intern_get_irn_mode(a) == intern_get_irn_mode(b))) {
+    if ((ta != tarval_bad)  && (tb != tarval_bad) && (get_irn_mode(a) == get_irn_mode(b))) {
       if (tb == get_mode_null(get_tarval_mode(tb)))  /* div by zero: return tarval_bad */
        return tarval_bad;
       if (get_Proj_proj(n)== 0) /* Div */
@@ -410,8 +412,6 @@ static tarval *computed_value_Proj(ir_node *n)
 /**
  * If the parameter n can be computed, return its value, else tarval_bad.
  * Performs constant folding.
- *
- * GL: Only if n is arithmetic operator?
  */
 tarval *computed_value(ir_node *n)
 {
@@ -467,11 +467,11 @@ different_identity (ir_node *a, ir_node *b)
   assert (mode_is_reference(get_irn_mode (a))
           && mode_is_reference(get_irn_mode (b)));
 
-  if (intern_get_irn_op (a) == op_Proj && intern_get_irn_op(b) == op_Proj) {
+  if (get_irn_op (a) == op_Proj && get_irn_op(b) == op_Proj) {
     ir_node *a1 = get_Proj_pred (a);
     ir_node *b1 = get_Proj_pred (b);
-    if (a1 != b1 && intern_get_irn_op (a1) == op_Alloc
-               && intern_get_irn_op (b1) == op_Alloc)
+    if (a1 != b1 && get_irn_op (a1) == op_Alloc
+               && get_irn_op (b1) == op_Alloc)
       return 1;
   }
   return 0;
@@ -492,23 +492,36 @@ static ir_node *equivalent_node_Block(ir_node *n)
      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?
      Remaining Phi nodes are just Ids. */
-  if ((get_Block_n_cfgpreds(n) == 1) &&
-      (intern_get_irn_op(get_Block_cfgpred(n, 0)) == op_Jmp) &&
-      (get_opt_control_flow_straightening())) {
-    n = get_nodes_Block(get_Block_cfgpred(n, 0));                     DBG_OPT_STG;
-
-  } else if ((get_Block_n_cfgpreds(n) == 2) &&
-            (get_opt_control_flow_weak_simplification())) {
+   if ((get_Block_n_cfgpreds(n) == 1) &&
+       (get_irn_op(get_Block_cfgpred(n, 0)) == op_Jmp)) {
+     ir_node *predblock = get_nodes_Block(get_Block_cfgpred(n, 0));
+     if (predblock == oldn) {
+       /* Jmp jumps into the block it is in -- deal self cycle. */
+       n = new_Bad();                                      DBG_OPT_DEAD;
+     } else if (get_opt_control_flow_straightening()) {
+       n = predblock;                                      DBG_OPT_STG;
+     }
+   }
+   else if ((get_Block_n_cfgpreds(n) == 1) &&
+           (get_irn_op(skip_Proj(get_Block_cfgpred(n, 0))) == op_Cond)) {
+     ir_node *predblock = get_nodes_Block(get_Block_cfgpred(n, 0));
+     if (predblock == oldn) {
+       /* Jmp jumps into the block it is in -- deal self cycle. */
+       n = new_Bad();                                      DBG_OPT_DEAD;
+     }
+   }
+   else if ((get_Block_n_cfgpreds(n) == 2) &&
+           (get_opt_control_flow_weak_simplification())) {
     /* Test whether Cond jumps twice to this block
        @@@ we could do this also with two loops finding two preds from several ones. */
     ir_node *a = get_Block_cfgpred(n, 0);
     ir_node *b = get_Block_cfgpred(n, 1);
 
-    if ((intern_get_irn_op(a) == op_Proj) &&
-       (intern_get_irn_op(b) == op_Proj) &&
+    if ((get_irn_op(a) == op_Proj) &&
+       (get_irn_op(b) == op_Proj) &&
        (get_Proj_pred(a) == get_Proj_pred(b)) &&
-       (intern_get_irn_op(get_Proj_pred(a)) == op_Cond) &&
-       (intern_get_irn_mode(get_Cond_selector(get_Proj_pred(a))) == mode_b)) {
+       (get_irn_op(get_Proj_pred(a)) == op_Cond) &&
+       (get_irn_mode(get_Cond_selector(get_Proj_pred(a))) == mode_b)) {
       /* Also a single entry Block following a single exit Block.  Phis have
         twice the same operand and will be optimized away. */
       n = get_nodes_Block(a);                                         DBG_OPT_IFSIM;
@@ -530,6 +543,10 @@ static ir_node *equivalent_node_Block(ir_node *n)
   return n;
 }
 
+/**
+ * Returns a equivalent node for a Jmp, a Bad :-)
+ * Of course this only happens if the Block of the Jmp is Bad.
+ */
 static ir_node *equivalent_node_Jmp(ir_node *n)
 {
   /* GL: Why not same for op_Raise?? */
@@ -547,18 +564,28 @@ static ir_node *equivalent_node_Cond(ir_node *n)
   return n;
 }
 
+/**
+ * Use algebraic simplification a v a = a.
+ */
 static ir_node *equivalent_node_Or(ir_node *n)
 {
+  ir_node *oldn = n;
+
   ir_node *a = get_Or_left(n);
   ir_node *b = get_Or_right(n);
 
   /* remove a v a */
-  if (a == b)
-    n = a;
+  if (a == b) {
+    n = a;                                                             DBG_OPT_ALGSIM1;
+  }
 
   return n;
 }
 
+/**
+ * optimize operations that are commutative and have neutral 0,
+ * so a op 0 = 0 op a = a.
+ */
 static ir_node *equivalent_node_neutral_zero(ir_node *n)
 {
   ir_node *oldn = n;
@@ -571,9 +598,9 @@ static ir_node *equivalent_node_neutral_zero(ir_node *n)
 
   /* After running compute_node there is only one constant predecessor.
      Find this predecessors value and remember the other node: */
-  if ((tv = computed_value (a)) != tarval_bad) {
+  if ((tv = computed_value(a)) != tarval_bad) {
     on = b;
-  } else if ((tv = computed_value (b)) != tarval_bad) {
+  } else if ((tv = computed_value(b)) != tarval_bad) {
     on = a;
   } else
     return n;
@@ -587,16 +614,13 @@ static ir_node *equivalent_node_neutral_zero(ir_node *n)
   return n;
 }
 
-static ir_node *equivalent_node_Add(ir_node *n)
-{
-  return equivalent_node_neutral_zero(n);
-}
-
-static ir_node *equivalent_node_Eor(ir_node *n)
-{
-  return equivalent_node_neutral_zero(n);
-}
+#define equivalent_node_Add  equivalent_node_neutral_zero
+#define equivalent_node_Eor  equivalent_node_neutral_zero
 
+/**
+ * optimize operations that are not commutative but have neutral 0 on left,
+ * so a op 0 = a.
+ */
 static ir_node *equivalent_node_left_zero(ir_node *n)
 {
   ir_node *oldn = n;
@@ -604,63 +628,43 @@ static ir_node *equivalent_node_left_zero(ir_node *n)
   ir_node *a = get_binop_left(n);
   ir_node *b = get_binop_right(n);
 
-  /* optimize operations that are not commutative but have neutral 0 on left. Test only one predecessor. */
-  if (tarval_classify (computed_value (b)) == TV_CLASSIFY_NULL) {
+  if (tarval_classify(computed_value(b)) == TV_CLASSIFY_NULL) {
     n = a;                                                              DBG_OPT_ALGSIM1;
   }
 
   return n;
 }
 
-static ir_node *equivalent_node_Sub(ir_node *n)
-{
-  return equivalent_node_left_zero(n);
-}
-
-static ir_node *equivalent_node_Shl(ir_node *n)
-{
-  return equivalent_node_left_zero(n);
-}
-
-static ir_node *equivalent_node_Shr(ir_node *n)
-{
-  return equivalent_node_left_zero(n);
-}
-
-static ir_node *equivalent_node_Shrs(ir_node *n)
-{
-  return equivalent_node_left_zero(n);
-}
-
-static ir_node *equivalent_node_Rot(ir_node *n)
-{
-  return equivalent_node_left_zero(n);
-}
+#define equivalent_node_Sub   equivalent_node_left_zero
+#define equivalent_node_Shl   equivalent_node_left_zero
+#define equivalent_node_Shr   equivalent_node_left_zero
+#define equivalent_node_Shrs  equivalent_node_left_zero
+#define equivalent_node_Rot   equivalent_node_left_zero
 
+/**
+ * Er, a "symmetic unop", ie op(op(n)) = n.
+ */
 static ir_node *equivalent_node_symmetric_unop(ir_node *n)
 {
   ir_node *oldn = n;
 
   /* optimize symmetric unop */
-  if (intern_get_irn_op(get_unop_op(n)) == intern_get_irn_op(n)) {
+  if (get_irn_op(get_unop_op(n)) == get_irn_op(n)) {
     n = get_unop_op(get_unop_op(n));                                    DBG_OPT_ALGSIM2;
   }
   return n;
 }
 
-static ir_node *equivalent_node_Not(ir_node *n)
-{
-  /* NotNot x == x */
-  return equivalent_node_symmetric_unop(n);
-}
+/* NotNot x == x */
+#define equivalent_node_Not    equivalent_node_symmetric_unop
 
-static ir_node *equivalent_node_Minus(ir_node *n)
-{
-  /* --x == x */  /* ??? Is this possible or can --x raise an
-                        out of bounds exception if min =! max? */
-  return equivalent_node_symmetric_unop(n);
-}
+/* --x == x */  /* ??? Is this possible or can --x raise an
+                      out of bounds exception if min =! max? */
+#define equivalent_node_Minus  equivalent_node_symmetric_unop
 
+/**
+ * Optimize a * 1 = 1 * a = a.
+ */
 static ir_node *equivalent_node_Mul(ir_node *n)
 {
   ir_node *oldn = n;
@@ -677,23 +681,29 @@ static ir_node *equivalent_node_Mul(ir_node *n)
   return n;
 }
 
+/**
+ * Optimize a / 1 = a.
+ */
 static ir_node *equivalent_node_Div(ir_node *n)
 {
   ir_node *a = get_Div_left(n);
   ir_node *b = get_Div_right(n);
 
   /* Div is not commutative. */
-  if (tarval_classify (computed_value (b)) == TV_CLASSIFY_ONE) { /* div(x, 1) == x */
+  if (tarval_classify(computed_value(b)) == TV_CLASSIFY_ONE) { /* div(x, 1) == x */
     /* Turn Div into a tuple (mem, bad, a) */
     ir_node *mem = get_Div_mem(n);
     turn_into_tuple(n, 3);
-    set_Tuple_pred(n, 0, mem);
-    set_Tuple_pred(n, 1, new_Bad());
-    set_Tuple_pred(n, 2, a);
+    set_Tuple_pred(n, pn_Div_M,        mem);
+    set_Tuple_pred(n, pn_Div_X_except, new_Bad());     /* no exception */
+    set_Tuple_pred(n, pn_Div_res,      a);
   }
   return n;
 }
 
+/**
+ * Optimize a & 0b1...1 = 0b1...1 & a =  a & a = a.
+ */
 static ir_node *equivalent_node_And(ir_node *n)
 {
   ir_node *oldn = n;
@@ -703,32 +713,35 @@ static ir_node *equivalent_node_And(ir_node *n)
 
   if (a == b) {
     n = a;    /* And has it's own neutral element */
-  } else if (tarval_classify (computed_value (a)) == TV_CLASSIFY_ALL_ONE) {
+  } else if (tarval_classify(computed_value(a)) == TV_CLASSIFY_ALL_ONE) {
     n = b;
-  } else if (tarval_classify (computed_value (b)) == TV_CLASSIFY_ALL_ONE) {
+  } else if (tarval_classify(computed_value(b)) == TV_CLASSIFY_ALL_ONE) {
     n = a;
   }
   if (n != oldn)                                                        DBG_OPT_ALGSIM1;
   return n;
 }
 
+/**
+ * Try to remove useless conv's:
+ */
 static ir_node *equivalent_node_Conv(ir_node *n)
 {
   ir_node *oldn = n;
   ir_node *a = get_Conv_op(n);
   ir_node *b;
 
-  ir_mode *n_mode = intern_get_irn_mode(n);
-  ir_mode *a_mode = intern_get_irn_mode(a);
+  ir_mode *n_mode = get_irn_mode(n);
+  ir_mode *a_mode = get_irn_mode(a);
 
   if (n_mode == a_mode) { /* No Conv necessary */
     n = a;                                                              DBG_OPT_ALGSIM3;
-  } else if (intern_get_irn_op(a) == op_Conv) { /* Conv(Conv(b)) */
+  } else if (get_irn_op(a) == op_Conv) { /* Conv(Conv(b)) */
     ir_mode *b_mode;
 
     b = get_Conv_op(a);
-    n_mode = intern_get_irn_mode(n);
-    b_mode = intern_get_irn_mode(b);
+    n_mode = get_irn_mode(n);
+    b_mode = get_irn_mode(b);
 
     if (n_mode == b_mode) {
       if (n_mode == mode_b) {
@@ -763,7 +776,7 @@ static ir_node *equivalent_node_Phi(ir_node *n)
 
   n_preds = get_Phi_n_preds(n);
 
-  block = get_nodes_Block(n);
+  block = get_nodes_block(n);
   /* @@@ fliegt 'raus, sollte aber doch immer wahr sein!!!
      assert(get_irn_arity(block) == n_preds && "phi in wrong block!"); */
   if ((is_Bad(block)) ||                         /* Control dead */
@@ -778,27 +791,32 @@ static ir_node *equivalent_node_Phi(ir_node *n)
      value that is known at a certain point.  This is useful for
      dataflow analysis. */
   if (n_preds == 2) {
-    ir_node *a = follow_Id (get_Phi_pred(n, 0));
-    ir_node *b = follow_Id (get_Phi_pred(n, 1));
-    if (   (intern_get_irn_op(a) == op_Confirm)
-       && (intern_get_irn_op(b) == op_Confirm)
-       && follow_Id (intern_get_irn_n(a, 0) == intern_get_irn_n(b, 0))
-       && (intern_get_irn_n(a, 1) == intern_get_irn_n (b, 1))
+    ir_node *a = get_Phi_pred(n, 0);
+    ir_node *b = get_Phi_pred(n, 1);
+    if (   (get_irn_op(a) == op_Confirm)
+       && (get_irn_op(b) == op_Confirm)
+       && follow_Id (get_irn_n(a, 0) == get_irn_n(b, 0))
+       && (get_irn_n(a, 1) == get_irn_n (b, 1))
        && (a->data.num == (~b->data.num & irpn_True) )) {
-      return intern_get_irn_n(a, 0);
+      return get_irn_n(a, 0);
     }
   }
 #endif
 
+  /* If the Block has a Bad pred, we also have one. */
+  for (i = 0;  i < n_preds;  ++i)
+    if (is_Bad (get_Block_cfgpred(block, i)))
+      set_Phi_pred(n, i, new_Bad());
+
   /* Find first non-self-referencing input */
   for (i = 0;  i < n_preds;  ++i) {
-    first_val = follow_Id(get_Phi_pred(n, i));
-    /* skip Id's */
-    set_Phi_pred(n, i, first_val);
+    first_val = get_Phi_pred(n, i);
     if (   (first_val != n)                            /* not self pointer */
-       && (intern_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. */
+#if 1
+       && (get_irn_op(first_val) != op_Bad)
+#endif
+          ) {        /* value not dead */
+      break;          /* then found first value. */
     }
   }
 
@@ -810,13 +828,13 @@ static ir_node *equivalent_node_Phi(ir_node *n)
   /* follow_Id () for rest of inputs, determine if any of these
      are non-self-referencing */
   while (++i < n_preds) {
-    scnd_val = follow_Id(get_Phi_pred(n, i));
-    /* skip Id's */
-    set_Phi_pred(n, i, scnd_val);
+    scnd_val = get_Phi_pred(n, i);
     if (   (scnd_val != n)
        && (scnd_val != first_val)
-       && (intern_get_irn_op(scnd_val) != op_Bad)
-       && !(is_Bad (get_Block_cfgpred(block, i))) ) {
+#if 1
+       && (get_irn_op(scnd_val) != op_Bad)
+#endif
+          ) {
       break;
     }
   }
@@ -825,10 +843,9 @@ static ir_node *equivalent_node_Phi(ir_node *n)
   if (i >= n_preds) {
     n = first_val;                                     DBG_OPT_PHI;
   } else {
-    /* skip the remaining Ids. */
-    while (++i < n_preds) {
-      set_Phi_pred(n, i, follow_Id(get_Phi_pred(n, i)));
-    }
+    /* skip the remaining Ids (done in get_Phi_pred). */
+    /* superfluous, since we walk all to propagate Block's Bads.
+       while (++i < n_preds) get_Phi_pred(n, i);     */
   }
   return n;
 }
@@ -840,7 +857,7 @@ static ir_node *equivalent_node_Load(ir_node *n)
  ir_node *a = skip_Proj(get_Load_mem(n));
  ir_node *b = get_Load_ptr(n);
 
- if (intern_get_irn_op(a) == op_Store) {
+ if (get_irn_op(a) == op_Store) {
    if ( different_identity (b, get_Store_ptr(a))) {
         /* load and store use different pointers, therefore load
                needs not take store's memory but the state before. */
@@ -852,6 +869,11 @@ static ir_node *equivalent_node_Load(ir_node *n)
  return n;
 }
 
+/**
+ * Optimize store after store and load atfter store.
+ *
+ * @todo FAILS for volatile entities
+ */
 static ir_node *equivalent_node_Store(ir_node *n)
 {
   ir_node *oldn = n;
@@ -861,20 +883,20 @@ static ir_node *equivalent_node_Store(ir_node *n)
   ir_node *b = get_Store_ptr(n);
   ir_node *c = skip_Proj(get_Store_value(n));
 
-  if (intern_get_irn_op(a) == op_Store
+  if (get_irn_op(a) == op_Store
       && get_Store_ptr(a) == b
       && skip_Proj(get_Store_value(a)) == c) {
     /* We have twice exactly the same store -- a write after write. */
     n = a;                                                         DBG_OPT_WAW;
-  } else if (intern_get_irn_op(c) == op_Load
+  } else if (get_irn_op(c) == op_Load
             && (a == c || skip_Proj(get_Load_mem(c)) == a)
             && get_Load_ptr(c) == b ) {
     /* We just loaded the value from the same memory, i.e., the store
        doesn't change the memory -- a write after read. */
     a = get_Store_mem(n);
     turn_into_tuple(n, 2);
-    set_Tuple_pred(n, 0, a);
-    set_Tuple_pred(n, 1, new_Bad());                               DBG_OPT_WAR;
+    set_Tuple_pred(n, pn_Store_M,        a);
+    set_Tuple_pred(n, pn_Store_X_except, new_Bad());               DBG_OPT_WAR;
   }
   return n;
 }
@@ -885,7 +907,7 @@ static ir_node *equivalent_node_Proj(ir_node *n)
 
   ir_node *a = get_Proj_pred(n);
 
-  if ( intern_get_irn_op(a) == op_Tuple) {
+  if ( get_irn_op(a) == op_Tuple) {
     /* Remove the Tuple/Proj combination. */
     if ( get_Proj_proj(n) <= get_Tuple_n_preds(a) ) {
       n = get_Tuple_pred(a, get_Proj_proj(n));                     DBG_OPT_TUPLE;
@@ -893,7 +915,7 @@ static ir_node *equivalent_node_Proj(ir_node *n)
       assert(0); /* This should not happen! */
       n = new_Bad();
     }
-  } else if (intern_get_irn_mode(n) == mode_X &&
+  } else if (get_irn_mode(n) == mode_X &&
             is_Bad(get_nodes_Block(n))) {
     /* Remove dead control flow -- early gigo. */
     n = new_Bad();
@@ -901,11 +923,14 @@ static ir_node *equivalent_node_Proj(ir_node *n)
   return n;
 }
 
+/**
+ * Remove Id's.
+ */
 static ir_node *equivalent_node_Id(ir_node *n)
 {
   ir_node *oldn = n;
 
-  n = follow_Id (n);                                                 DBG_OPT_ID;
+  n = follow_Id(n);                                                 DBG_OPT_ID;
   return n;
 }
 
@@ -923,7 +948,7 @@ case iro_Mod, Quot, DivMod
  * in array fits, we transform n into a tuple (e.g., Div).
  */
 ir_node *
-equivalent_node (ir_node *n)
+equivalent_node(ir_node *n)
 {
   if (n->op->equivalent_node)
     return n->op->equivalent_node(n);
@@ -959,8 +984,8 @@ static ir_op *firm_set_default_equivalent_node(ir_op *op)
   CASE(And);
   CASE(Conv);
   CASE(Phi);
-  CASE(Load);
-  CASE(Store);
+  CASE(Load);          /* dangerous */
+  CASE(Store);         /* dangerous, see todo */
   CASE(Proj);
   CASE(Id);
   default:
@@ -986,15 +1011,15 @@ optimize_preds(ir_node *n) {
     a = get_unop_op(n);
   }
 
-  switch (intern_get_irn_opcode(n)) {
+  switch (get_irn_opcode(n)) {
 
   case iro_Cmp:
     /* We don't want Cast as input to Cmp. */
-    if (intern_get_irn_op(a) == op_Cast) {
+    if (get_irn_op(a) == op_Cast) {
       a = get_Cast_op(a);
       set_Cmp_left(n, a);
     }
-    if (intern_get_irn_op(b) == op_Cast) {
+    if (get_irn_op(b) == op_Cast) {
       b = get_Cast_op(b);
       set_Cmp_right(n, b);
     }
@@ -1006,31 +1031,35 @@ optimize_preds(ir_node *n) {
 
 static ir_node *transform_node_Div(ir_node *n)
 {
-  tarval *ta = computed_value(n);
+  tarval *tv = computed_value(n);
+
+  /* BEWARE: it is NOT possible to optimize a/a to 1, as this may cause a exception */
 
-  if (ta != tarval_bad) {
+  if (tv != tarval_bad) {
     /* Turn Div into a tuple (mem, bad, value) */
     ir_node *mem = get_Div_mem(n);
 
     turn_into_tuple(n, 3);
-    set_Tuple_pred(n, 0, mem);
-    set_Tuple_pred(n, 1, new_Bad());
-    set_Tuple_pred(n, 2, new_Const(get_tarval_mode(ta), ta));
+    set_Tuple_pred(n, pn_Div_M, mem);
+    set_Tuple_pred(n, pn_Div_X_except, new_Bad());
+    set_Tuple_pred(n, pn_Div_res, new_Const(get_tarval_mode(tv), tv));
   }
   return n;
 }
 
 static ir_node *transform_node_Mod(ir_node *n)
 {
-  tarval *ta = computed_value(n);
+  tarval *tv = computed_value(n);
 
-  if (ta != tarval_bad) {
+  /* BEWARE: it is NOT possible to optimize a%a to 0, as this may cause a exception */
+
+  if (tv != tarval_bad) {
     /* Turn Mod into a tuple (mem, bad, value) */
     ir_node *mem = get_Mod_mem(n);
     turn_into_tuple(n, 3);
-    set_Tuple_pred(n, 0, mem);
-    set_Tuple_pred(n, 1, new_Bad());
-    set_Tuple_pred(n, 2, new_Const(get_tarval_mode(ta), ta));
+    set_Tuple_pred(n, pn_Mod_M, mem);
+    set_Tuple_pred(n, pn_Mod_X_except, new_Bad());
+    set_Tuple_pred(n, pn_Mod_res, new_Const(get_tarval_mode(tv), tv));
   }
   return n;
 }
@@ -1041,46 +1070,41 @@ static ir_node *transform_node_DivMod(ir_node *n)
 
   ir_node *a = get_DivMod_left(n);
   ir_node *b = get_DivMod_right(n);
-  ir_mode *mode = intern_get_irn_mode(a);
+  ir_mode *mode = get_irn_mode(a);
+  tarval *ta = value_of(a);
+  tarval *tb = value_of(b);
 
-  if (!(mode_is_int(mode) && mode_is_int(intern_get_irn_mode(b))))
+  if (!(mode_is_int(mode) && mode_is_int(get_irn_mode(b))))
     return n;
 
-  if (a == b) {
-    a = new_Const(mode, get_mode_one(mode));
-    b = new_Const(mode, get_mode_null(mode));
-    evaluated = 1;
-  } else {
-    tarval *ta = value_of(a);
-    tarval *tb = value_of(b);
-
-    if (tb != tarval_bad) {
-      if (tb == get_mode_one(get_tarval_mode(tb))) {
-       b = new_Const (mode, get_mode_null(mode));
-       evaluated = 1;
-      } else if (ta != tarval_bad) {
-       tarval *resa, *resb;
-       resa = tarval_div (ta, tb);
-       if (resa == tarval_bad) return n; /* Causes exception!!! Model by replacing through
-                                         Jmp for X result!? */
-       resb = tarval_mod (ta, tb);
-       if (resb == tarval_bad) return n; /* Causes exception! */
-       a = new_Const (mode, resa);
-       b = new_Const (mode, resb);
-       evaluated = 1;
-      }
-    } else if (ta == get_mode_null(get_tarval_mode(ta))) {
-      b = a;
+  /* BEWARE: it is NOT possible to optimize a/a to 1, as this may cause a exception */
+
+  if (tb != tarval_bad) {
+    if (tb == get_mode_one(get_tarval_mode(tb))) {
+      b = new_Const (mode, get_mode_null(mode));
+      evaluated = 1;
+    } else if (ta != tarval_bad) {
+      tarval *resa, *resb;
+      resa = tarval_div (ta, tb);
+      if (resa == tarval_bad) return n; /* Causes exception!!! Model by replacing through
+                                       Jmp for X result!? */
+      resb = tarval_mod (ta, tb);
+      if (resb == tarval_bad) return n; /* Causes exception! */
+      a = new_Const (mode, resa);
+      b = new_Const (mode, resb);
       evaluated = 1;
     }
+  } else if (ta == get_mode_null(mode)) {
+    b = a;
+    evaluated = 1;
   }
   if (evaluated) { /* replace by tuple */
     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());  /* no exception */
-    set_Tuple_pred(n, 2, a);
-    set_Tuple_pred(n, 3, b);
+    set_Tuple_pred(n, pn_DivMod_M,        mem);
+    set_Tuple_pred(n, pn_DivMod_X_except, new_Bad());  /* no exception */
+    set_Tuple_pred(n, pn_DivMod_res_div,  a);
+    set_Tuple_pred(n, pn_DivMod_res_mod,  b);
     assert(get_nodes_Block(n));
   }
 
@@ -1096,23 +1120,23 @@ static ir_node *transform_node_Cond(ir_node *n)
   tarval *ta = value_of(a);
 
   if ((ta != tarval_bad) &&
-      (intern_get_irn_mode(a) == mode_b) &&
+      (get_irn_mode(a) == mode_b) &&
       (get_opt_unreachable_code())) {
     /* It's a boolean Cond, branching on a boolean constant.
               Replace it by a tuple (Bad, Jmp) or (Jmp, Bad) */
     jmp = new_r_Jmp(current_ir_graph, get_nodes_Block(n));
     turn_into_tuple(n, 2);
     if (ta == tarval_b_true) {
-      set_Tuple_pred(n, 0, new_Bad());
-      set_Tuple_pred(n, 1, jmp);
+      set_Tuple_pred(n, pn_Cond_false, new_Bad());
+      set_Tuple_pred(n, pn_Cond_true, jmp);
     } else {
-      set_Tuple_pred(n, 0, jmp);
-      set_Tuple_pred(n, 1, new_Bad());
+      set_Tuple_pred(n, pn_Cond_false, jmp);
+      set_Tuple_pred(n, pn_Cond_true, new_Bad());
     }
     /* We might generate an endless loop, so keep it alive. */
     add_End_keepalive(get_irg_end(current_ir_graph), get_nodes_Block(n));
   } else if ((ta != tarval_bad) &&
-            (intern_get_irn_mode(a) == mode_Iu) &&
+            (get_irn_mode(a) == mode_Iu) &&
             (get_Cond_kind(n) == dense) &&
             (get_opt_unreachable_code())) {
     /* I don't want to allow Tuples smaller than the biggest Proj.
@@ -1122,15 +1146,15 @@ static ir_node *transform_node_Cond(ir_node *n)
     set_irn_link(n, new_r_Jmp(current_ir_graph, get_nodes_Block(n)));
     /* We might generate an endless loop, so keep it alive. */
     add_End_keepalive(get_irg_end(current_ir_graph), get_nodes_Block(n));
-  } else if ((intern_get_irn_op(a) == op_Eor)
-            && (intern_get_irn_mode(a) == mode_b)
+  } else if ((get_irn_op(a) == op_Eor)
+            && (get_irn_mode(a) == mode_b)
             && (tarval_classify(computed_value(get_Eor_right(a))) == TV_CLASSIFY_ONE)) {
     /* 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 ((intern_get_irn_op(a) == op_Not)
-            && (intern_get_irn_mode(a) == mode_b)) {
+  } else if ((get_irn_op(a) == op_Not)
+            && (get_irn_mode(a) == 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),
@@ -1144,15 +1168,15 @@ static ir_node *transform_node_Eor(ir_node *n)
   ir_node *a = get_Eor_left(n);
   ir_node *b = get_Eor_right(n);
 
-  if ((intern_get_irn_mode(n) == mode_b)
-      && (intern_get_irn_op(a) == op_Proj)
-      && (intern_get_irn_mode(a) == mode_b)
+  if ((get_irn_mode(n) == mode_b)
+      && (get_irn_op(a) == op_Proj)
+      && (get_irn_mode(a) == mode_b)
       && (tarval_classify (computed_value (b)) == TV_CLASSIFY_ONE)
-      && (intern_get_irn_op(get_Proj_pred(a)) == op_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)));
-  else if ((intern_get_irn_mode(n) == mode_b)
+  else if ((get_irn_mode(n) == mode_b)
           && (tarval_classify (computed_value (b)) == TV_CLASSIFY_ONE))
     /* The Eor is a Not. Replace it by a Not. */
     /*   ????!!!Extend to bitfield 1111111. */
@@ -1161,14 +1185,17 @@ static ir_node *transform_node_Eor(ir_node *n)
   return n;
 }
 
+/**
+ * Transfor a boolean Not.
+ */
 static ir_node *transform_node_Not(ir_node *n)
 {
   ir_node *a = get_Not_op(n);
 
-  if (   (intern_get_irn_mode(n) == mode_b)
-      && (intern_get_irn_op(a) == op_Proj)
-      && (intern_get_irn_mode(a) == mode_b)
-      && (intern_get_irn_op(get_Proj_pred(a)) == op_Cmp))
+  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)) == 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)));
@@ -1176,6 +1203,102 @@ static ir_node *transform_node_Not(ir_node *n)
   return n;
 }
 
+/**
+ * Transform a Div/Mod/DivMod with a non-zero constant. Must be
+ * done here to avoid that this optimization runs more than once...
+ */
+static ir_node *transform_node_Proj(ir_node *proj)
+{
+  ir_node *n = get_Proj_pred(proj);
+  ir_node *b;
+  tarval *tb;
+
+  switch (get_irn_opcode(n)) {
+  case iro_Div:
+    b = get_Div_right(n);
+    tb = computed_value(b);
+
+    if (tb != tarval_bad && tarval_classify(tb) != TV_CLASSIFY_NULL) { /* div(x, c) && c != 0 */
+      ir_node *div, *proj;
+      ir_node *a = get_Div_left(n);
+      ir_node *mem = get_Div_mem(n);
+      int rem = get_optimize();
+
+      set_optimize(0);
+      {
+        div = new_rd_Div(get_irn_dbg_info(n), current_ir_graph,
+         get_nodes_Block(n), get_irg_initial_mem(current_ir_graph), a, b);
+
+        proj = new_r_Proj(current_ir_graph, get_nodes_Block(n), div, get_irn_mode(a), pn_Div_res);
+      }
+      set_optimize(rem);
+
+      turn_into_tuple(n, 3);
+      set_Tuple_pred(n, pn_Mod_M, mem);
+      set_Tuple_pred(n, pn_Mod_X_except, new_Bad());
+      set_Tuple_pred(n, pn_Mod_res, proj);
+    }
+    break;
+  case iro_Mod:
+    b = get_Mod_right(n);
+    tb = computed_value(b);
+
+    if (tb != tarval_bad && tarval_classify(tb) != TV_CLASSIFY_NULL) { /* mod(x, c) && c != 0 */
+      ir_node *mod, *proj;
+      ir_node *a = get_Mod_left(n);
+      ir_node *mem = get_Mod_mem(n);
+      int rem = get_optimize();
+
+      set_optimize(0);
+      {
+        mod = new_rd_Mod(get_irn_dbg_info(n), current_ir_graph,
+         get_nodes_Block(n), get_irg_initial_mem(current_ir_graph), a, b);
+
+        proj = new_r_Proj(current_ir_graph, get_nodes_Block(n), mod, get_irn_mode(a), pn_Mod_res);
+      }
+      set_optimize(rem);
+
+      turn_into_tuple(n, 3);
+      set_Tuple_pred(n, pn_Mod_M, mem);
+      set_Tuple_pred(n, pn_Mod_X_except, new_Bad());
+      set_Tuple_pred(n, pn_Mod_res, proj);
+    }
+    break;
+  case iro_DivMod:
+    b = get_DivMod_right(n);
+    tb = computed_value(b);
+
+    if (tb != tarval_bad && tarval_classify(tb) != TV_CLASSIFY_NULL) { /* DivMod(x, c) && c != 0 */
+      ir_node *div_mod, *proj_div, *proj_mod;
+      ir_node *a = get_Mod_left(n);
+      ir_node *mem = get_Mod_mem(n);
+      int rem = get_optimize();
+
+      set_optimize(0);
+      {
+        div_mod = new_rd_DivMod(get_irn_dbg_info(n), current_ir_graph,
+         get_nodes_Block(n), get_irg_initial_mem(current_ir_graph), a, b);
+
+        proj_div = new_r_Proj(current_ir_graph, get_nodes_Block(n), div_mod, get_irn_mode(a), pn_DivMod_res_div);
+        proj_mod = new_r_Proj(current_ir_graph, get_nodes_Block(n), div_mod, get_irn_mode(a), pn_DivMod_res_mod);
+      }
+      set_optimize(rem);
+
+      turn_into_tuple(n, 4);
+      set_Tuple_pred(n, pn_DivMod_M, mem);
+      set_Tuple_pred(n, pn_DivMod_X_except, new_Bad());
+      set_Tuple_pred(n, pn_DivMod_res_div, proj_div);
+      set_Tuple_pred(n, pn_DivMod_res_mod, proj_mod);
+    }
+    break;
+  default:
+    /* do nothing */
+    return proj;
+  }
+
+  /* we have added a Tuple, optimize it for the current Proj away */
+  return equivalent_node_Proj(proj);
+}
 
 /**
  * Tries several [inplace] [optimizing] transformations and returns an
@@ -1207,6 +1330,7 @@ static ir_op *firm_set_default_transform_node(ir_op *op)
   CASE(Cond);
   CASE(Eor);
   CASE(Not);
+  CASE(Proj);
   default:
     op->transform_node  = NULL;
   }
@@ -1252,7 +1376,7 @@ static int node_cmp_attr_Free(ir_node *a, ir_node *b)
 static int node_cmp_attr_SymConst(ir_node *a, ir_node *b)
 {
     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);
+      || (get_irn_symconst_attr(a).sym.type_p != get_irn_symconst_attr(b).sym.type_p);
 }
 
 static int node_cmp_attr_Call(ir_node *a, ir_node *b)
@@ -1329,23 +1453,23 @@ vt_cmp (const void *elt, const void *key)
 
   if (a == b) return 0;
 
-  if ((intern_get_irn_op(a) != intern_get_irn_op(b)) ||
-      (intern_get_irn_mode(a) != intern_get_irn_mode(b))) return 1;
+  if ((get_irn_op(a) != get_irn_op(b)) ||
+      (get_irn_mode(a) != get_irn_mode(b))) return 1;
 
   /* compare if a's in and b's in are equal */
-  irn_arity_a = intern_get_irn_arity (a);
-  if (irn_arity_a != intern_get_irn_arity(b))
+  irn_arity_a = get_irn_arity (a);
+  if (irn_arity_a != get_irn_arity(b))
     return 1;
 
   /* for block-local cse and pinned nodes: */
-  if (!get_opt_global_cse() || (get_op_pinned(intern_get_irn_op(a)) == pinned)) {
-    if (intern_get_irn_n(a, -1) != intern_get_irn_n(b, -1))
+  if (!get_opt_global_cse() || (get_op_pinned(get_irn_op(a)) == pinned)) {
+    if (get_irn_n(a, -1) != get_irn_n(b, -1))
       return 1;
   }
 
   /* compare a->in[0..ins] with b->in[0..ins] */
   for (i = 0; i < irn_arity_a; i++)
-    if (intern_get_irn_n(a, i) != intern_get_irn_n(b, i))
+    if (get_irn_n(a, i) != get_irn_n(b, i))
       return 1;
 
   /*
@@ -1358,27 +1482,35 @@ vt_cmp (const void *elt, const void *key)
   return 0;
 }
 
-/**
+/*
  * Calculate a hash value of a node.
  */
-static unsigned
+unsigned
 ir_node_hash (ir_node *node)
 {
   unsigned h;
   int i, irn_arity;
 
-  /* hash table value = 9*(9*(9*(9*(9*arity+in[0])+in[1])+ ...)+mode)+code */
-  h = irn_arity = intern_get_irn_arity(node);
+  if (node->op == op_Const) {
+    /* special value for const, as they only differ in their tarval. */
+    /* @@@ What about SymConst? */
+    h = ((unsigned) node->attr.con.tv)>>3 ;
+    h = 9*h + (unsigned)get_irn_mode(node);
+  } else {
 
-  /* consider all in nodes... except the block. */
-  for (i = 0;  i < irn_arity;  i++) {
-    h = 9*h + (unsigned long)intern_get_irn_n(node, i);
-  }
+    /* hash table value = 9*(9*(9*(9*(9*arity+in[0])+in[1])+ ...)+mode)+code */
+    h = irn_arity = get_irn_arity(node);
 
-  /* ...mode,... */
-  h = 9*h + (unsigned long) intern_get_irn_mode (node);
-  /* ...and code */
-  h = 9*h + (unsigned long) intern_get_irn_op (node);
+    /* consider all in nodes... except the block. */
+    for (i = 0;  i < irn_arity;  i++) {
+      h = 9*h + (unsigned)get_irn_n(node, i);
+    }
+
+    /* ...mode,... */
+    h = 9*h + (unsigned) get_irn_mode (node);
+    /* ...and code */
+    h = 9*h + (unsigned) get_irn_op (node);
+  }
 
   return h;
 }
@@ -1398,6 +1530,10 @@ del_identities (pset *value_table)
 /**
  * Return the canonical node computing the same value as n.
  * Looks up the node in a hash table.
+ *
+ * For Const nodes this is performed in the constructor, too.  Const
+ * nodes are extremely time critical because of their frequent use in
+ * constant string arrays.
  */
 static INLINE ir_node *
 identify (pset *value_table, ir_node *n)
@@ -1408,7 +1544,7 @@ identify (pset *value_table, ir_node *n)
 
   /* TODO: use a generic commutative attribute */
   if (get_opt_reassociation()) {
-    if (is_op_commutative(intern_get_irn_op(n))) {
+    if (is_op_commutative(get_irn_op(n))) {
       /* for commutative operators perform  a OP b == b OP a */
       if (get_binop_left(n) > get_binop_right(n)) {
        ir_node *h = get_binop_left(n);
@@ -1426,14 +1562,14 @@ identify (pset *value_table, ir_node *n)
 
 /**
  * During construction we set the pinned flag in the graph right when the
- * optimizatin is performed.  The flag turning on procedure global cse could
+ * optimization is performed.  The flag turning on procedure global cse could
  * be changed between two allocations.  This way we are safe.
  */
 static INLINE ir_node *
 identify_cons (pset *value_table, ir_node *n) {
   ir_node *old = n;
   n = identify(value_table, n);
-  if (intern_get_irn_n(old, -1) != intern_get_irn_n(n, -1))
+  if (get_irn_n(old, -1) != get_irn_n(n, -1))
     set_irg_pinned(current_ir_graph, floats);
   return n;
 }
@@ -1471,17 +1607,17 @@ static INLINE ir_node *
 gigo (ir_node *node)
 {
   int i, irn_arity;
-  ir_op* op = intern_get_irn_op(node);
+  ir_op* op = get_irn_op(node);
 
   /* remove garbage blocks by looking at control flow that leaves the block
      and replacing the control flow by Bad. */
-  if (intern_get_irn_mode(node) == mode_X) {
+  if (get_irn_mode(node) == mode_X) {
     ir_node *block = get_nodes_block(node);
     if (op == op_End) return node;     /* Don't optimize End, may have Bads. */
-    if (intern_get_irn_op(block) == op_Block && get_Block_matured(block)) {
-      irn_arity = intern_get_irn_arity(block);
+    if (get_irn_op(block) == op_Block && get_Block_matured(block)) {
+      irn_arity = get_irn_arity(block);
       for (i = 0; i < irn_arity; i++) {
-       if (!is_Bad(intern_get_irn_n(block, i))) break;
+       if (!is_Bad(get_irn_n(block, i))) break;
       }
       if (i == irn_arity) return new_Bad();
     }
@@ -1490,9 +1626,9 @@ gigo (ir_node *node)
   /* Blocks, Phis and Tuples may have dead inputs, e.g., if one of the
      blocks predecessors is dead. */
   if ( op != op_Block && op != op_Phi && op != op_Tuple) {
-    irn_arity = intern_get_irn_arity(node);
+    irn_arity = get_irn_arity(node);
     for (i = -1; i < irn_arity; i++) {
-      if (is_Bad(intern_get_irn_n(node, i))) {
+      if (is_Bad(get_irn_n(node, i))) {
         return new_Bad();
       }
     }
@@ -1503,9 +1639,9 @@ gigo (ir_node *node)
   /* If Block has only Bads as predecessors it's garbage. */
   /* If Phi has only Bads as predecessors it's garbage. */
   if ((op == op_Block && get_Block_matured(node)) || op == op_Phi)  {
-    irn_arity = intern_get_irn_arity(node);
+    irn_arity = get_irn_arity(node);
     for (i = 0; i < irn_arity; i++) {
-      if (!is_Bad(intern_get_irn_n(node, i))) break;
+      if (!is_Bad(get_irn_n(node, i))) break;
     }
     if (i == irn_arity) node = new_Bad();
   }
@@ -1523,8 +1659,8 @@ ir_node *
 optimize_node (ir_node *n)
 {
   tarval *tv;
-  ir_node *old_n = n;
-  opcode iro = intern_get_irn_opcode(n);
+  ir_node *oldn = n;
+  opcode iro = get_irn_opcode(n);
 
   /* Allways optimize Phi nodes: part of the construction. */
   if ((!get_opt_optimize()) && (iro != iro_Phi)) return n;
@@ -1532,13 +1668,25 @@ optimize_node (ir_node *n)
   /* constant expression evaluation / constant folding */
   if (get_opt_constant_folding()) {
     /* constants can not be evaluated */
-    if  (intern_get_irn_op(n) != op_Const) {
+    if (iro != iro_Const) {
       /* try to evaluate */
       tv = computed_value (n);
-      if ((intern_get_irn_mode(n) != mode_T) && (tv != tarval_bad)) {
-        /* evaluation was succesful -- replace the node. */
+      if ((get_irn_mode(n) != mode_T) && (tv != tarval_bad)) {
+       /*
+        * we MUST copy the node here temparary, because it's still needed
+        * for DBG_OPT_ALGSIM0
+        */
+       int node_size = offsetof(ir_node, attr) +  n->op->attr_size;
+       ir_node *x = alloca(node_size);
+
+       memcpy(x, n, node_size);
+       oldn = x;
+
+        /* evaluation was successful -- replace the node. */
        obstack_free (current_ir_graph->obst, n);
-       return new_Const (get_tarval_mode (tv), tv);
+       n = new_Const (get_tarval_mode (tv), tv);
+                                                       DBG_OPT_ALGSIM0;
+       return n;
       }
     }
   }
@@ -1561,14 +1709,16 @@ optimize_node (ir_node *n)
   if (get_opt_cse())
     n = identify_cons (current_ir_graph->value_table, n);
 
-  if (n != old_n) {
+  if (n != oldn) {
     /* We found an existing, better node, so we can deallocate the old node. */
-    obstack_free (current_ir_graph->obst, old_n);
+    obstack_free (current_ir_graph->obst, oldn);
+
+    return n;
   }
 
   /* Some more constant expression evaluation that does not allow to
      free the node. */
-  iro = intern_get_irn_opcode(n);
+  iro = get_irn_opcode(n);
   if (get_opt_constant_folding() ||
       (iro == iro_Cond) ||
       (iro == iro_Proj))     /* Flags tested local. */
@@ -1579,7 +1729,7 @@ optimize_node (ir_node *n)
   n = gigo (n);
 
   /* Now we have a legal, useful node. Enter it in hash table for cse */
-  if (get_opt_cse() && (intern_get_irn_opcode(n) != iro_Block)) {
+  if (get_opt_cse() && (get_irn_opcode(n) != iro_Block)) {
     n = identify_remember (current_ir_graph->value_table, n);
   }
 
@@ -1596,10 +1746,10 @@ ir_node *
 optimize_in_place_2 (ir_node *n)
 {
   tarval *tv;
-  ir_node *old_n = n;
-  opcode iro = intern_get_irn_opcode(n);
+  ir_node *oldn = n;
+  opcode iro = get_irn_opcode(n);
 
-  if (!get_opt_optimize() && (intern_get_irn_op(n) != op_Phi)) return n;
+  if (!get_opt_optimize() && (get_irn_op(n) != op_Phi)) return n;
 
   /* if not optimize return n */
   if (n == NULL) {
@@ -1615,10 +1765,10 @@ optimize_in_place_2 (ir_node *n)
     if (iro != iro_Const) {
       /* try to evaluate */
       tv = computed_value (n);
-      if ((intern_get_irn_mode(n) != mode_T) && (tv != tarval_bad)) {
-        /* evaluation was succesful -- replace the node. */
+      if ((get_irn_mode(n) != mode_T) && (tv != tarval_bad)) {
+        /* evaluation was successful -- replace the node. */
        n = new_Const (get_tarval_mode (tv), tv);
-       __dbg_info_merge_pair(n, old_n, dbg_const_eval);
+                                               DBG_OPT_ALGSIM0;
        return n;
       }
     }
@@ -1645,7 +1795,7 @@ optimize_in_place_2 (ir_node *n)
   }
 
   /* Some more constant expression evaluation. */
-  iro = intern_get_irn_opcode(n);
+  iro = get_irn_opcode(n);
   if (get_opt_constant_folding() ||
       (iro == iro_Cond) ||
       (iro == iro_Proj))     /* Flags tested local. */
@@ -1661,7 +1811,7 @@ optimize_in_place_2 (ir_node *n)
   /* 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() && (intern_get_irn_opcode(n) != iro_Block))
+  if (get_opt_cse() && (get_irn_opcode(n) != iro_Block))
     n = identify_remember (current_ir_graph->value_table, n);
 
   return n;