firmjni does not like two similar enums.
[libfirm] / ir / ir / iropt.c
index 324be19..0f9c641 100644 (file)
@@ -39,6 +39,7 @@
 # include "irhooks.h"
 # include "irarch.h"
 # include "hashptr.h"
+# include "archop.h"
 # include "opt_polymorphy.h"
 
 /* Make types visible to allow most efficient access */
@@ -60,7 +61,7 @@ follow_Id (ir_node *n)
  */
 static tarval *computed_value_Const(ir_node *n)
 {
-    return get_Const_tarval(n);
+  return get_Const_tarval(n);
 }
 
 /**
@@ -104,7 +105,7 @@ static tarval *computed_value_Sub(ir_node *n)
 
   /* a - a */
   if (a == b && !is_Bad(a))
-    return get_tarval_null(get_irn_mode(n));
+    return get_mode_null(get_irn_mode(n));
 
   ta = value_of(a);
   tb = value_of(b);
@@ -302,7 +303,7 @@ static tarval *computed_value_Eor(ir_node *n)
   tarval *ta, *tb;
 
   if (a == b)
-    return get_tarval_null(get_irn_mode(n));
+    return get_mode_null(get_irn_mode(n));
 
   ta = value_of(a);
   tb = value_of(b);
@@ -409,82 +410,132 @@ static tarval *computed_value_Conv(ir_node *n)
   return tarval_bad;
 }
 
+/**
+ * return the value of a Proj(Cmp)
+ *
+ * This performs a first step of unreachable code elimination.
+ * Proj can not be computed, but folding a Cmp above the Proj here is
+ * not as wasteful as folding a Cmp into a Tuple of 16 Consts of which
+ * only 1 is used.
+ * There are several case where we can evaluate a Cmp node, see later.
+ */
+static tarval *computed_value_Proj_Cmp(ir_node *n)
+{
+  ir_node *a   = get_Proj_pred(n);
+  ir_node *aa  = get_Cmp_left(a);
+  ir_node *ab  = get_Cmp_right(a);
+  long proj_nr = get_Proj_proj(n);
+
+  /*
+   * BEWARE: a == a is NOT always True for floating Point values, as
+   * NaN != NaN is defined, so we must check this here.
+   */
+  if (aa == ab && (
+      !mode_is_float(get_irn_mode(aa)) || proj_nr == pn_Cmp_Lt ||  proj_nr == pn_Cmp_Gt)
+      ) { /* 1.: */
+
+    /* This is a trick with the bits used for encoding the Cmp
+       Proj numbers, the following statement is not the same:
+    return new_tarval_from_long (proj_nr == pn_Cmp_Eq, mode_b) */
+    return new_tarval_from_long (proj_nr & pn_Cmp_Eq, mode_b);
+  }
+  else {
+    tarval *taa = value_of(aa);
+    tarval *tab = value_of(ab);
+    ir_mode *mode = get_irn_mode(aa);
+
+    /*
+     * The predecessors of Cmp are target values.  We can evaluate
+     * the Cmp.
+     */
+    if ((taa != tarval_bad) && (tab != tarval_bad)) {
+      /* strange checks... */
+      pn_Cmp flags = tarval_cmp(taa, tab);
+      if (flags != pn_Cmp_False) {
+        return new_tarval_from_long (proj_nr & flags, mode_b);
+      }
+    }
+    /* for integer values, we can check against MIN/MAX */
+    else if (mode_is_int(mode)) {
+      /* MIN <=/> x.  This results in true/false. */
+      if (taa == get_mode_min(mode)) {
+        /* a compare with the MIN value */
+        if (proj_nr == pn_Cmp_Le)
+          return get_tarval_b_true();
+        else if (proj_nr == pn_Cmp_Gt)
+          return get_tarval_b_false();
+      }
+      /* x >=/< MIN.  This results in true/false. */
+      else
+      if (tab == get_mode_min(mode)) {
+        /* a compare with the MIN value */
+        if (proj_nr == pn_Cmp_Ge)
+          return get_tarval_b_true();
+        else if (proj_nr == pn_Cmp_Lt)
+          return get_tarval_b_false();
+      }
+      /* MAX >=/< x.  This results in true/false. */
+      else if (taa == get_mode_max(mode)) {
+        if (proj_nr == pn_Cmp_Ge)
+          return get_tarval_b_true();
+        else if (proj_nr == pn_Cmp_Lt)
+          return get_tarval_b_false();
+      }
+      /* x <=/> MAX.  This results in true/false. */
+      else if (tab == get_mode_max(mode)) {
+        if (proj_nr == pn_Cmp_Le)
+          return get_tarval_b_true();
+        else if (proj_nr == pn_Cmp_Gt)
+          return get_tarval_b_false();
+      }
+    }
+    /*
+     * The predecessors are Allocs or (void*)(0) constants.  Allocs never
+     * return NULL, they raise an exception.   Therefore we can predict
+     * the Cmp result.
+     */
+    else {
+      ir_node *aaa = skip_Id(skip_Proj(aa));
+      ir_node *aba = skip_Id(skip_Proj(ab));
+
+      if (   (   (/* aa is ProjP and aaa is Alloc */
+                     (get_irn_op(aa) == op_Proj)
+                  && (mode_is_reference(get_irn_mode(aa)))
+                  && (get_irn_op(aaa) == op_Alloc))
+              && (   (/* ab is NULL */
+                         (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 */
+                         (get_irn_op(ab) == op_Proj)
+                      && (mode_is_reference(get_irn_mode(ab)))
+                      && (get_irn_op(aba) == op_Alloc)
+                      && (aaa != aba))))
+          || (/* aa is NULL and aba is 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(proj_nr & pn_Cmp_Ne, mode_b);
+    }
+  }
+  return tarval_bad;
+}
+
 /**
  * return the value of a Proj, handle Proj(Cmp), Proj(Div), Proj(Mod), Proj(DivMod)
  */
 static tarval *computed_value_Proj(ir_node *n)
 {
   ir_node *a = get_Proj_pred(n);
-  ir_node *aa, *ab;
   long proj_nr;
 
-  /* Optimize Cmp nodes.
-     This performs a first step of unreachable code elimination.
-     Proj can not be computed, but folding a Cmp above the Proj here is
-     not as wasteful as folding a Cmp into a Tuple of 16 Consts of which
-     only 1 is used.
-     There are several case where we can evaluate a Cmp node:
-     1. The nodes compared are both the same.  If we compare for
-        equal, greater equal, ... this will return true, else it
-        will return false.  This step relies on cse.
-     2. The predecessors of Cmp are target values.  We can evaluate
-        the Cmp.
-     3. The predecessors are Allocs or void* constants.  Allocs never
-        return NULL, they raise an exception.   Therefore we can predict
-        the Cmp result. */
   switch (get_irn_opcode(a)) {
   case iro_Cmp:
-    aa = get_Cmp_left(a);
-    ab = get_Cmp_right(a);
-    proj_nr = get_Proj_proj(n);
-
-    if (aa == ab && (
-        !mode_is_float(get_irn_mode(aa)) || proj_nr == pn_Cmp_Lt ||  proj_nr == pn_Cmp_Gt)
-        ) { /* 1.: */
-      /* BEWARE: a == a is NOT always True for floating Point!!! */
-      /* This is a trick with the bits used for encoding the Cmp
-         Proj numbers, the following statement is not the same:
-      return new_tarval_from_long (proj_nr == pn_Cmp_Eq, mode_b) */
-      return new_tarval_from_long (proj_nr & pn_Cmp_Eq, mode_b);
-    } else {
-      tarval *taa = value_of(aa);
-      tarval *tab = value_of(ab);
-
-      if ((taa != tarval_bad) && (tab != tarval_bad)) { /* 2.: */
-        /* strange checks... */
-        pn_Cmp flags = tarval_cmp (taa, tab);
-        if (flags != pn_Cmp_False) {
-          return new_tarval_from_long (proj_nr & flags, mode_b);
-        }
-      } else {  /* check for 3.: */
-        ir_node *aaa = skip_Id(skip_Proj(aa));
-        ir_node *aba = skip_Id(skip_Proj(ab));
-
-        if (   (   (/* aa is ProjP and aaa is Alloc */
-                       (get_irn_op(aa) == op_Proj)
-                    && (mode_is_reference(get_irn_mode(aa)))
-                    && (get_irn_op(aaa) == op_Alloc))
-                && (   (/* ab is constant void */
-                           (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 */
-                           (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 */
-                   (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 (proj_nr & pn_Cmp_Ne, mode_b);
-      }
-    }
-    break;
+    return computed_value_Proj_Cmp(n);
 
   case iro_DivMod:
     /* compute either the Div or the Mod part */
@@ -603,9 +654,26 @@ different_identity (ir_node *a, ir_node *b)
 }
 #endif
 
+/**
+ * Returns a equivalent block for another block.
+ * If the block has only one predecessor, this is
+ * the equivalent one. If the only predecessor of a block is
+ * the block itself, this is a dead block.
+ *
+ * If both predecessors of a block are the branches of a binary
+ * Cond, the equivalent block is Cond's block.
+ *
+ * If all predecessors of a block are bad or lies in a dead
+ * block, the current block is dead as well.
+ *
+ * Note, that blocks are NEVER turned into Bad's, instead
+ * the dead_block flag is set. So, never test for is_Bad(block),
+ * always use is_dead_Block(block).
+ */
 static ir_node *equivalent_node_Block(ir_node *n)
 {
   ir_node *oldn = n;
+  int n_preds   = get_Block_n_cfgpreds(n);
 
   /* The Block constructor does not call optimize, but mature_immBlock
      calls the optimization. */
@@ -617,8 +685,7 @@ 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) &&
-       (get_irn_op(get_Block_cfgpred(n, 0)) == op_Jmp)) {
+   if ((n_preds == 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. */
@@ -629,7 +696,7 @@ static ir_node *equivalent_node_Block(ir_node *n)
        DBG_OPT_STG(oldn, n);
      }
    }
-   else if ((get_Block_n_cfgpreds(n) == 1) &&
+   else if ((n_preds == 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) {
@@ -638,7 +705,7 @@ static ir_node *equivalent_node_Block(ir_node *n)
        DBG_OPT_DEAD(oldn, n);
      }
    }
-   else if ((get_Block_n_cfgpreds(n) == 2) &&
+   else if ((n_preds == 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. */
@@ -701,7 +768,7 @@ static ir_node *equivalent_node_Jmp(ir_node *n)
 static ir_node *equivalent_node_Cond(ir_node *n)
 {
   /* 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. */
+     See cases for iro_Cond and iro_Proj in transform_node(). */
   return n;
 }
 
@@ -769,9 +836,13 @@ static ir_node *equivalent_node_left_zero(ir_node *n)
 #define equivalent_node_Rot   equivalent_node_left_zero
 
 /**
- * Er, a "symmetic unop", ie op(op(n)) = n.
+ * Optimize an "idempotent unary op", ie op(op(n)) = n.
+ *
+ * @fixme -(-a) == a, but might overflow two times.
+ * We handle it anyway here but the better way would be a
+ * flag. This would be needed for Pascal for instance.
  */
-static ir_node *equivalent_node_symmetric_unop(ir_node *n)
+static ir_node *equivalent_node_idempotent_unop(ir_node *n)
 {
   ir_node *oldn = n;
   ir_node *pred = get_unop_op(n);
@@ -784,12 +855,12 @@ static ir_node *equivalent_node_symmetric_unop(ir_node *n)
   return n;
 }
 
-/* NotNot x == x */
-#define equivalent_node_Not    equivalent_node_symmetric_unop
+/* Not(Not(x)) == x */
+#define equivalent_node_Not    equivalent_node_idempotent_unop
 
 /* --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
+#define equivalent_node_Minus  equivalent_node_idempotent_unop
 
 /**
  * Optimize a * 1 = 1 * a = a.
@@ -901,7 +972,7 @@ static ir_node *equivalent_node_And(ir_node *n)
 }
 
 /**
- * Try to remove useless conv's:
+ * Try to remove useless Conv's:
  */
 static ir_node *equivalent_node_Conv(ir_node *n)
 {
@@ -925,12 +996,12 @@ static ir_node *equivalent_node_Conv(ir_node *n)
     if (n_mode == b_mode) {
       if (n_mode == mode_b) {
         n = b; /* Convb(Conv*(xxxb(...))) == xxxb(...) */
-    DBG_OPT_ALGSIM1(oldn, a, b, n);
+        DBG_OPT_ALGSIM1(oldn, a, b, n);
       }
       else if (mode_is_int(n_mode) || mode_is_character(n_mode)) {
         if (smaller_mode(b_mode, a_mode)){
           n = b;        /* ConvS(ConvL(xxxS(...))) == xxxS(...) */
-      DBG_OPT_ALGSIM1(oldn, a, b, n);
+          DBG_OPT_ALGSIM1(oldn, a, b, n);
         }
       }
     }
@@ -940,7 +1011,7 @@ static ir_node *equivalent_node_Conv(ir_node *n)
 
 /**
  * A Cast may be removed if the type of the previous node
- * is already to type of the Cast.
+ * is already the type of the Cast.
  */
 static ir_node *equivalent_node_Cast(ir_node *n) {
   ir_node *pred = get_Cast_op(n);
@@ -1156,14 +1227,18 @@ static ir_node *equivalent_node_Mux(ir_node *n)
 
 /**
  * Optimize -a CMP -b into b CMP a.
- * This works even for floating point
+ * This works only for for modes where unary Minus
+ * cannot Overflow.
+ * Note that two-complement integers can Overflow
+ * so it will NOT work.
  */
 static ir_node *equivalent_node_Cmp(ir_node *n)
 {
   ir_node *left  = get_Cmp_left(n);
   ir_node *right = get_Cmp_right(n);
 
-  if (get_irn_op(left) == op_Minus && get_irn_op(right) == op_Minus) {
+  if (get_irn_op(left) == op_Minus && get_irn_op(right) == op_Minus &&
+      !mode_overflow_on_unary_Minus(get_irn_mode(left))) {
     left  = get_Minus_op(left);
     right = get_Minus_op(right);
     set_Cmp_left(n, right);
@@ -1329,6 +1404,7 @@ static ir_node *transform_node_AddSub(ir_node *n)
 /**
  * Do the AddSub optimization, then Transform Add(a,a) into Mul(a, 2)
  * if the mode is integer or float.
+ * Transform Add(a,-b) into Sub(a,b).
  * Reassociation might fold this further.
  */
 static ir_node *transform_node_Add(ir_node *n)
@@ -1354,6 +1430,30 @@ static ir_node *transform_node_Add(ir_node *n)
             mode);
       DBG_OPT_ALGSIM0(oldn, n);
     }
+    else {
+      ir_node *b = get_Add_right(n);
+
+      if (get_irn_op(a) == op_Minus) {
+        n = new_rd_Sub(
+            get_irn_dbg_info(n),
+            current_ir_graph,
+            get_nodes_block(n),
+            b,
+            get_Minus_op(a),
+            mode);
+        DBG_OPT_ALGSIM0(oldn, n);
+      }
+      else if (get_irn_op(b) == op_Minus) {
+        n = new_rd_Sub(
+            get_irn_dbg_info(n),
+            current_ir_graph,
+            get_nodes_block(n),
+            a,
+            get_Minus_op(b),
+            mode);
+        DBG_OPT_ALGSIM0(oldn, n);
+      }
+    }
   }
   return n;
 }
@@ -1369,23 +1469,42 @@ static ir_node *transform_node_Sub(ir_node *n)
   n = transform_node_AddSub(n);
 
   mode = get_irn_mode(n);
-  if (mode_is_num(mode)) {
-    if (classify_Const(get_Sub_left(n)) == CNST_NULL) {
-      n = new_rd_Minus(
-            get_irn_dbg_info(n),
-            current_ir_graph,
-            get_nodes_block(n),
-            get_Sub_right(n),
-            mode);
-      DBG_OPT_ALGSIM0(oldn, n);
-    }
+  if (mode_is_num(mode) && (classify_Const(get_Sub_left(n)) == CNST_NULL)) {
+    n = new_rd_Minus(
+          get_irn_dbg_info(n),
+          current_ir_graph,
+          get_nodes_block(n),
+          get_Sub_right(n),
+          mode);
+    DBG_OPT_ALGSIM0(oldn, n);
   }
 
   return n;
 }
 
-/** Do architecture dependend optimizations on Mul nodes */
+/**
+  Transform Mul(a,-1) into -a.
+ * Do architecture dependend optimizations on Mul nodes
+ */
 static ir_node *transform_node_Mul(ir_node *n) {
+  ir_node *oldn = n;
+  ir_mode *mode = get_irn_mode(n);
+
+  if (mode_is_signed(mode)) {
+    ir_node *r = NULL;
+    ir_node *a = get_Mul_left(n);
+    ir_node *b = get_Mul_right(n);
+
+    if (value_of(a) == get_mode_minus_one(mode))
+      r = b;
+    else if (value_of(b) == get_mode_minus_one(mode))
+      r = a;
+    if (r) {
+      n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph, get_nodes_block(n), r, mode);
+      DBG_OPT_ALGSIM1(oldn, a, b, n);
+      return n;
+    }
+  }
   return arch_dep_replace_mul_with_shifts(n);
 }
 
@@ -1404,7 +1523,7 @@ static ir_node *transform_node_Div(ir_node *n)
 
     DBG_OPT_CSTEVAL(n, value);
   }
-  else /* Try architecture dependand optimization */
+  else /* Try architecture dependend optimization */
     value = arch_dep_replace_div_by_const(n);
 
   if (value != n) {
@@ -1434,7 +1553,7 @@ static ir_node *transform_node_Mod(ir_node *n)
 
     DBG_OPT_CSTEVAL(n, value);
   }
-  else /* Try architecture dependand optimization */
+  else /* Try architecture dependend optimization */
     value = arch_dep_replace_mod_by_const(n);
 
   if (value != n) {
@@ -1488,7 +1607,7 @@ static ir_node *transform_node_DivMod(ir_node *n)
       DBG_OPT_CSTEVAL(n, a);
       DBG_OPT_CSTEVAL(n, b);
     }
-    else { /* Try architecture dependand optimization */
+    else { /* Try architecture dependend optimization */
       arch_dep_replace_divmod_by_const(&a, &b, n);
       evaluated = a != NULL;
     }
@@ -1511,6 +1630,119 @@ static ir_node *transform_node_DivMod(ir_node *n)
   return n;
 }
 
+
+/**
+ * Optimize Abs(x) => x if x is Confirmed >= 0
+ * Optimize Abs(x) => -x if x is Confirmed <= 0
+ */
+static ir_node *transform_node_Abs(ir_node *n)
+{
+  ir_node *oldn = n;
+  ir_node *a = get_Abs_op(n);
+  tarval *tv, *c;
+  ir_mode *mode;
+  pn_Cmp cmp, ncmp;
+  int do_minus = 0;
+
+  if (get_irn_op(a) != op_Confirm)
+    return n;
+
+  tv  = value_of(get_Confirm_bound(n));
+  if (tv == tarval_bad)
+    return n;
+
+  mode = get_irn_mode(n);
+
+  /*
+   * We can handle only >=, >, <, <= cases.
+   * We could handle == too, but this should not happen.
+   *
+   * Note that for integer modes we have a slightly better
+   * optimization possibilities, so we handle this
+   * different.
+   */
+  cmp = get_Confirm_cmp(n);
+
+  switch (cmp) {
+  case pn_Cmp_Lt:
+    /*
+     * must be x < c <= 1 to be useful if integer mode and -0 = 0
+     *         x < c <= 0 to be useful else
+     */
+  case pn_Cmp_Le:
+    /*
+     * must be x <= c < 1 to be useful if integer mode and -0 = 0
+     *         x <= c < 0 to be useful else
+     */
+    c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ?
+      get_mode_one(mode) : get_mode_null(mode);
+
+    ncmp = tarval_cmp(tv, c) ^ pn_Cmp_Eq;
+    if (cmp != ncmp)
+      return n;
+
+    /* yep, we can replace by -x */
+    do_minus = 1;
+    break;
+
+  case pn_Cmp_Ge:
+    /*
+     * must be x >= c > -1 to be useful if integer mode
+     *         x >= c >= 0 to be useful else
+     */
+  case pn_Cmp_Gt:
+    /*
+     * must be x > c >= -1 to be useful if integer mode
+     *         x > c >= 0 to be useful else
+     */
+    if (mode_is_int(mode)) {
+      c = get_mode_minus_one(mode);
+
+      ncmp = tarval_cmp(tv, c) ^ pn_Cmp_Eq;
+      if (cmp != ncmp)
+        return n;
+    }
+    else {
+      c = get_mode_minus_one(mode);
+
+      ncmp = tarval_cmp(tv, c);
+
+      if (ncmp != pn_Cmp_Eq && ncmp != pn_Cmp_Gt)
+        return n;
+    }
+
+    /* yep, we can replace by x */
+    do_minus = 0;
+    break;
+
+  default:
+    return n;
+  }
+
+  /*
+   * Ok, when we get here, we can replace the Abs
+   * by either x or -x. In the second case we eve could
+   * add a new Confirm.
+   *
+   * Note that -x would create a new node, so we could
+   * not run it in the equivalent_node() context.
+   */
+  if (do_minus) {
+    ir_node *c;
+
+    n = new_rd_Minus(get_irn_dbg_info(n), current_ir_graph,
+                     get_nodes_block(n), a, mode);
+
+    c  = new_Const(mode, tarval_neg(tv));
+    n = new_r_Confirm(current_ir_graph, get_nodes_block(n), n, c, get_inversed_pnc(cmp));
+  }
+  else {
+    n = a;
+  }
+
+  return n;
+}
+
 /**
  * transform a Cond node
  */
@@ -1574,8 +1806,15 @@ static ir_node *transform_node_Eor(ir_node *n)
   ir_node *oldn = n;
   ir_node *a = get_Eor_left(n);
   ir_node *b = get_Eor_right(n);
+  ir_mode *mode = get_irn_mode(n);
 
-  if ((get_irn_mode(n) == mode_b)
+  if (a == b) {
+    /* a ^ a = 0 */
+    n = new_rd_Const(get_irn_dbg_info(n), current_ir_graph, get_nodes_block(n),
+                     mode, get_mode_null(mode));
+    DBG_OPT_ALGSIM0(oldn, n);
+  }
+  else if ((mode == mode_b)
       && (get_irn_op(a) == op_Proj)
       && (get_irn_mode(a) == mode_b)
       && (classify_tarval (value_of(b)) == TV_CLASSIFY_ONE)
@@ -1586,7 +1825,7 @@ static ir_node *transform_node_Eor(ir_node *n)
 
     DBG_OPT_ALGSIM0(oldn, n);
   }
-  else if ((get_irn_mode(n) == mode_b)
+  else if ((mode == mode_b)
         && (classify_tarval (value_of(b)) == TV_CLASSIFY_ONE)) {
     /* The Eor is a Not. Replace it by a Not. */
     /*   ????!!!Extend to bitfield 1111111. */
@@ -1625,7 +1864,7 @@ static ir_node *transform_node_Not(ir_node *n)
 static ir_node *transform_node_Cast(ir_node *n) {
   ir_node *oldn = n;
   ir_node *pred = get_Cast_op(n);
-  type *tp = get_irn_type(pred);
+  type *tp = get_irn_type(n);
 
   if (get_irn_op(pred) == op_Const && get_Const_type(pred) != tp) {
     n = new_rd_Const_type(NULL, current_ir_graph, get_nodes_block(pred), get_irn_mode(pred),
@@ -1636,212 +1875,253 @@ static ir_node *transform_node_Cast(ir_node *n) {
                  get_SymConst_kind(pred), tp);
     DBG_OPT_CSTEVAL(oldn, n);
   }
+
   return n;
 }
 
 /**
- * Does all optimizations on nodes that must be done on it's Proj's
- * because of creating new nodes.
- *
- * Transform a Div/Mod/DivMod with a non-zero constant.
+ * Transform a Proj(Div) with a non-zero constant.
  * Removes the exceptions and routes the memory to the NoMem node.
- *
- * Optimizes jump tables by removing all impossible cases.
- *
- * Normalizes and optimizes Cmp nodes.
  */
-static ir_node *transform_node_Proj(ir_node *proj)
+static ir_node *transform_node_Proj_Div(ir_node *proj)
 {
   ir_node *n = get_Proj_pred(proj);
   ir_node *b;
   tarval *tb;
   long proj_nr;
 
-  switch (get_irn_opcode(n)) {
-  case iro_Div:
-    b  = get_Div_right(n);
-    tb = value_of(b);
+  b  = get_Div_right(n);
+  tb = value_of(b);
 
-    if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) { /* div(x, c) && c != 0 */
-      proj_nr = get_Proj_proj(proj);
+  if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) {
+    /* div(x, c) && c != 0 */
+    proj_nr = get_Proj_proj(proj);
 
-      /* this node may float */
-      set_irn_pinned(n, op_pin_state_floats);
+    /* this node may float */
+    set_irn_pinned(n, op_pin_state_floats);
 
-      if (proj_nr == pn_Div_X_except) {
-        /* we found an exception handler, remove it */
-        return new_Bad();
-      } else {
-        /* the memory Proj can be removed */
-        ir_node *res = get_Div_mem(n);
-        set_Div_mem(n, get_irg_no_mem(current_ir_graph));
-        if (proj_nr == pn_Div_M)
-          return res;
-      }
+    if (proj_nr == pn_Div_X_except) {
+      /* we found an exception handler, remove it */
+      return new_Bad();
+    } else {
+      /* the memory Proj can be removed */
+      ir_node *res = get_Div_mem(n);
+      set_Div_mem(n, get_irg_no_mem(current_ir_graph));
+      if (proj_nr == pn_Div_M)
+        return res;
     }
-    break;
-  case iro_Mod:
-    b  = get_Mod_right(n);
-    tb = value_of(b);
+  }
+  return proj;
+}
+
+/**
+ * Transform a Proj(Mod) with a non-zero constant.
+ * Removes the exceptions and routes the memory to the NoMem node.
+ */
+static ir_node *transform_node_Proj_Mod(ir_node *proj)
+{
+  ir_node *n = get_Proj_pred(proj);
+  ir_node *b;
+  tarval *tb;
+  long proj_nr;
 
-    if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) { /* mod(x, c) && c != 0 */
-      proj_nr = get_Proj_proj(proj);
+  b  = get_Mod_right(n);
+  tb = value_of(b);
 
-      /* this node may float */
-      set_irn_pinned(n, op_pin_state_floats);
+  if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) {
+    /* mod(x, c) && c != 0 */
+    proj_nr = get_Proj_proj(proj);
 
-      if (proj_nr == pn_Mod_X_except) {
-        /* we found an exception handler, remove it */
-        return new_Bad();
-      } else {
-        /* the memory Proj can be removed */
-        ir_node *res = get_Mod_mem(n);
-        set_Mod_mem(n, get_irg_no_mem(current_ir_graph));
-        if (proj_nr == pn_Mod_M)
-          return res;
-      }
+    /* this node may float */
+    set_irn_pinned(n, op_pin_state_floats);
+
+    if (proj_nr == pn_Mod_X_except) {
+      /* we found an exception handler, remove it */
+      return new_Bad();
+    } else {
+      /* the memory Proj can be removed */
+      ir_node *res = get_Mod_mem(n);
+      set_Mod_mem(n, get_irg_no_mem(current_ir_graph));
+      if (proj_nr == pn_Mod_M)
+        return res;
     }
-    break;
-  case iro_DivMod:
-    b  = get_DivMod_right(n);
-    tb = value_of(b);
+  }
+  return proj;
+}
+
+/**
+ * Transform a Proj(DivMod) with a non-zero constant.
+ * Removes the exceptions and routes the memory to the NoMem node.
+ */
+static ir_node *transform_node_Proj_DivMod(ir_node *proj)
+{
+  ir_node *n = get_Proj_pred(proj);
+  ir_node *b;
+  tarval *tb;
+  long proj_nr;
 
-    if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) { /* DivMod(x, c) && c != 0 */
-      proj_nr = get_Proj_proj(proj);
+  b  = get_DivMod_right(n);
+  tb = value_of(b);
 
-      /* this node may float */
-      set_irn_pinned(n, op_pin_state_floats);
+  if (tb != tarval_bad && classify_tarval(tb) != TV_CLASSIFY_NULL) {
+    /* DivMod(x, c) && c != 0 */
+    proj_nr = get_Proj_proj(proj);
 
-      if (proj_nr == pn_DivMod_X_except) {
-        /* we found an exception handler, remove it */
-        return new_Bad();
-      }
-      else {
-        /* the memory Proj can be removed */
-        ir_node *res = get_DivMod_mem(n);
-        set_DivMod_mem(n, get_irg_no_mem(current_ir_graph));
-        if (proj_nr == pn_DivMod_M)
-          return res;
-      }
+    /* this node may float */
+    set_irn_pinned(n, op_pin_state_floats);
+
+    if (proj_nr == pn_DivMod_X_except) {
+      /* we found an exception handler, remove it */
+      return new_Bad();
     }
-    break;
+    else {
+      /* the memory Proj can be removed */
+      ir_node *res = get_DivMod_mem(n);
+      set_DivMod_mem(n, get_irg_no_mem(current_ir_graph));
+      if (proj_nr == pn_DivMod_M)
+        return res;
+    }
+  }
+  return proj;
+}
 
-  case iro_Cond:
-    if (get_opt_unreachable_code()) {
-      b = get_Cond_selector(n);
-      tb = value_of(b);
-
-      if (tb != tarval_bad && mode_is_int(get_tarval_mode(tb))) {
-        /* we have a constant switch */
-        long num = get_Proj_proj(proj);
-
-        if (num != get_Cond_defaultProj(n)) { /* we cannot optimize default Proj's yet */
-          if (get_tarval_long(tb) == num) {
-            /* Do NOT create a jump here, or we will have 2 control flow ops
-             * in a block. This case is optimized away in optimize_cf(). */
-            return proj;
-          }
-          else
-            return new_Bad();
+/**
+ * Optimizes jump tables (CondIs or CondIu) by removing all impossible cases.
+ */
+static ir_node *transform_node_Proj_Cond(ir_node *proj)
+{
+  if (get_opt_unreachable_code()) {
+    ir_node *n = get_Proj_pred(proj);
+    ir_node *b = get_Cond_selector(n);
+    tarval *tb = value_of(b);
+
+    if (tb != tarval_bad && mode_is_int(get_tarval_mode(tb))) {
+      /* we have a constant switch */
+      long num = get_Proj_proj(proj);
+
+      if (num != get_Cond_defaultProj(n)) { /* we cannot optimize default Proj's yet */
+        if (get_tarval_long(tb) == num) {
+          /* Do NOT create a jump here, or we will have 2 control flow ops
+           * in a block. This case is optimized away in optimize_cf(). */
+          return proj;
+        }
+        else {
+          /* this case will NEVER be taken, kill it */
+          return new_Bad();
         }
       }
     }
-    return proj;
+  }
+  return proj;
+}
 
-  case iro_Cmp:
-    if (0 && get_opt_reassociation()) {
-      ir_node *left  = get_Cmp_left(n);
-      ir_node *right = get_Cmp_right(n);
-      ir_node *c     = NULL;
-      tarval *tv     = NULL;
-      int changed    = 0;
-      ir_mode *mode  = NULL;
+/**
+ * Normalizes and optimizes Cmp nodes.
+ */
+static ir_node *transform_node_Proj_Cmp(ir_node *proj)
+{
+  if (get_opt_reassociation()) {
+    ir_node *n     = get_Proj_pred(proj);
+    ir_node *left  = get_Cmp_left(n);
+    ir_node *right = get_Cmp_right(n);
+    ir_node *c     = NULL;
+    tarval *tv     = NULL;
+    int changed    = 0;
+    ir_mode *mode  = NULL;
+    long proj_nr   = get_Proj_proj(proj);
 
-      proj_nr = get_Proj_proj(proj);
+    /*
+     * First step: normalize the compare op
+     * by placing the constant on the right site
+     * or moving the lower address node to the left.
+     * We ignore the case that both are constants
+     * this case should be optimized away.
+     */
+    if (get_irn_op(right) == op_Const)
+      c = right;
+    else if (get_irn_op(left) == op_Const) {
+      c     = left;
+      left  = right;
+      right = c;
+
+      proj_nr = get_inversed_pnc(proj_nr);
+      changed |= 1;
+    }
+    else if (left > right) {
+      ir_node *t = left;
 
-      /*
-       * First step: normalize the compare op
-       * by placing the constant on the right site
-       * or moving the lower address node to the left.
-       * We ignore the case that both are constants, then
-       * this compare should be optimized away.
-       */
-      if (get_irn_op(right) == op_Const)
-        c = right;
-      else if (get_irn_op(left) == op_Const) {
-        c     = left;
-        left  = right;
-        right = c;
-
-        proj_nr = get_swapped_pnc(proj_nr);
-        changed |= 1;
-      }
-      else if (left > right) {
-        ir_node *t = left;
+      left  = right;
+      right = t;
 
-        left  = right;
-        right = t;
+      proj_nr = get_inversed_pnc(proj_nr);
+      changed |= 1;
+    }
 
-        proj_nr = get_swapped_pnc(proj_nr);
-        changed |= 1;
-      }
+    /*
+     * Second step: Try to reduce the magnitude
+     * of a constant. This may help to generate better code
+     * later and may help to normalize more compares.
+     * Of course this is only possible for integer values.
+     */
+    if (c) {
+      mode = get_irn_mode(c);
+      tv = get_Const_tarval(c);
+
+      if (tv != tarval_bad) {
+        /* the following optimization is possible on modes without Overflow
+         * on Unary Minus or on == and !=:
+         * -a CMP c  ==>  a swap(CMP) -c
+         *
+         * Beware: for two-complement Overflow may occur, so only == and != can
+         * be optimized, see this:
+         * -MININT < 0 =/=> MININT > 0 !!!
+         */
+        if (get_opt_constant_folding() && get_irn_op(left) == op_Minus &&
+            (!mode_overflow_on_unary_Minus(mode) ||
+             (mode_is_int(mode) && (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg)))) {
+          left = get_Minus_op(left);
+          tv = tarval_sub(get_mode_null(mode), tv);
+
+          proj_nr = get_inversed_pnc(proj_nr);
+          changed |= 2;
+        }
 
-      /*
-       * Second step: Try to reduce the magnitude
-       * of a constant. This may help to generate better code
-       * later and may help to normalize more compares.
-       * Of course this is only possible for integer values.
-       */
-      if (c) {
-        mode = get_irn_mode(c);
-        tv = get_Const_tarval(c);
-
-        if (tv != tarval_bad) {
-          /* the following optimization is possibe on non-int values either:
-           * -a CMP c  ==>  a swap(CMP) -c */
-          if (get_opt_constant_folding() && get_irn_op(left) == op_Minus) {
-            left = get_Minus_op(left);
-            tv = tarval_sub(get_tarval_one(mode), tv);
-
-            proj_nr = get_swapped_pnc(proj_nr);
-            changed |= 2;
+        /* for integer modes, we have more */
+        if (mode_is_int(mode)) {
+          /* Ne includes Unordered which is not possible on integers.
+           * However, frontends often use this wrong, so fix it here */
+          if (proj_nr == pn_Cmp_Ne) {
+            proj_nr = pn_Cmp_Lg;
+            set_Proj_proj(proj, proj_nr);
           }
 
-          /* for integer modes, we have more */
-          if (mode_is_int(mode)) {
-            /* Ne includes Unordered which is not possible on integers.
-             * However, frontends often use this wrong, so fix it here */
-            if (proj_nr == pn_Cmp_Ne)
-              proj_nr = pn_Cmp_Lg;
-
-            /* c > 0 : a < c  ==>  a <= (c-1)    a >= c  ==>  a > (c-1) */
-            if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Ge) &&
-                tarval_cmp(tv, get_tarval_null(mode)) == pn_Cmp_Gt) {
-              tv = tarval_sub(tv, get_tarval_one(mode));
+          /* c > 0 : a < c  ==>  a <= (c-1)    a >= c  ==>  a > (c-1) */
+          if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Ge) &&
+              tarval_cmp(tv, get_mode_null(mode)) == pn_Cmp_Gt) {
+            tv = tarval_sub(tv, get_mode_one(mode));
 
-              proj_nr ^= pn_Cmp_Eq;
-              changed |= 2;
-            }
-            /* c < 0 : a > c  ==>  a >= (c+1)    a <= c  ==>  a < (c+1) */
-            else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Le) &&
-                tarval_cmp(tv, get_tarval_null(mode)) == pn_Cmp_Lt) {
-              tv = tarval_add(tv, get_tarval_one(mode));
+            proj_nr ^= pn_Cmp_Eq;
+            changed |= 2;
+          }
+          /* c < 0 : a > c  ==>  a >= (c+1)    a <= c  ==>  a < (c+1) */
+          else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Le) &&
+              tarval_cmp(tv, get_mode_null(mode)) == pn_Cmp_Lt) {
+            tv = tarval_add(tv, get_mode_one(mode));
 
-              proj_nr ^= pn_Cmp_Eq;
-              changed |= 2;
-            }
+            proj_nr ^= pn_Cmp_Eq;
+            changed |= 2;
+          }
 
-            /* the following reassociations work only for == and != */
+          /* the following reassociations work only for == and != */
+          if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) {
 
             /* a-b == 0  ==>  a == b,  a-b != 0  ==>  a != b */
             if (classify_tarval(tv) == TV_CLASSIFY_NULL && get_irn_op(left) == op_Sub) {
-              if (proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) {
-                right = get_Sub_right(left);
-                left  = get_Sub_left(left);
+              right = get_Sub_right(left);
+              left  = get_Sub_left(left);
 
-                tv = value_of(right);
-                changed = 1;
-              }
+              tv = value_of(right);
+              changed = 1;
             }
 
             if (tv != tarval_bad) {
@@ -1858,7 +2138,7 @@ static ir_node *transform_node_Proj(ir_node *proj)
                   if (tv2 != tarval_bad) {
                     left    = get_Sub_left(left);
                     tv      = tv2;
-                    changed = 2;
+                    changed |= 2;
                   }
                 }
               }
@@ -1884,42 +2164,85 @@ static ir_node *transform_node_Proj(ir_node *proj)
                   if (tv2 != tarval_bad) {
                     left    = a;
                     tv      = tv2;
-                    changed = 2;
+                    changed |= 2;
                   }
                 }
               }
+              /* -a == c ==> a == -c, -a != c ==> a != -c */
+              else if (op == op_Minus) {
+                tarval *tv2 = tarval_sub(get_mode_null(mode), tv);
+
+                if (tv2 != tarval_bad) {
+                  left    = get_Minus_op(left);
+                  tv      = tv2;
+                  changed |= 2;
+                }
+              }
+            }
+          } /* == or != */
+          /* the following reassociations work only for <= */
+          else if (proj_nr == pn_Cmp_Le || proj_nr == pn_Cmp_Lt) {
+            if (tv != tarval_bad) {
+              ir_op *op = get_irn_op(left);
+
+              /* c >= 0 : Abs(a) <= c  ==>  (unsigned)(a + c) <= 2*c */
+              if (op == op_Abs) {
+              }
             }
           }
-        }
+        } /* mode_is_int */
       }
+    }
 
-      if (changed) {
-        ir_node *block = get_nodes_block(n);
+    if (changed) {
+      ir_node *block = get_nodes_block(n);
 
-        if (changed & 2)      /* need a new Const */
-          right = new_Const(mode, tv);
+      if (changed & 2)      /* need a new Const */
+        right = new_Const(mode, tv);
 
-        /* create a new compare */
-        n = new_rd_Cmp(get_irn_dbg_info(n), current_ir_graph, block,
-              left, right);
+      /* create a new compare */
+      n = new_rd_Cmp(get_irn_dbg_info(n), current_ir_graph, block,
+            left, right);
 
-        set_Proj_pred(proj, n);
-        set_Proj_proj(proj, proj_nr);
-      }
+      set_Proj_pred(proj, n);
+      set_Proj_proj(proj, proj_nr);
     }
-    return proj;
+  }
+  return proj;
+}
+
+/**
+ * Does all optimizations on nodes that must be done on it's Proj's
+ * because of creating new nodes.
+ */
+static ir_node *transform_node_Proj(ir_node *proj)
+{
+  ir_node *n = get_Proj_pred(proj);
+
+  switch (get_irn_opcode(n)) {
+  case iro_Div:
+    return transform_node_Proj_Div(proj);
+
+  case iro_Mod:
+    return transform_node_Proj_Mod(proj);
+
+  case iro_DivMod:
+    return transform_node_Proj_DivMod(proj);
+
+  case iro_Cond:
+    return transform_node_Proj_Cond(proj);
+
+  case iro_Cmp:
+    return transform_node_Proj_Cmp(proj);
 
   case iro_Tuple:
     /* should not happen, but if it does will be optimized away */
-    break;
+    return equivalent_node_Proj(proj);
 
   default:
     /* do nothing */
     return proj;
   }
-
-  /* we have added a Tuple, optimize it for the current Proj away */
-  return equivalent_node_Proj(proj);
 }
 
 /**
@@ -2225,7 +2548,7 @@ static ir_node *transform_node_End(ir_node *n) {
 }
 
 /**
- * Optimize a Mux into some simplier cases
+ * Optimize a Mux into some simplier cases.
  */
 static ir_node *transform_node_Mux(ir_node *n)
 {
@@ -2259,7 +2582,8 @@ static ir_node *transform_node_Mux(ir_node *n)
                 current_ir_graph,
                 block,
                 t, mode);
-          DBG_OPT_ALGSIM0(oldn, n);
+          DBG_OPT_ALGSIM1(oldn, cmp, sel, n);
+          return n;
         }
         else if (proj_nr == pn_Cmp_Le || proj_nr == pn_Cmp_Lt) {
           /* Mux(a <=/< 0, -a, a)  ==>  Minus(Abs(a)) */
@@ -2272,7 +2596,8 @@ static ir_node *transform_node_Mux(ir_node *n)
                 block,
                 n, mode);
 
-          DBG_OPT_ALGSIM0(oldn, n);
+          DBG_OPT_ALGSIM1(oldn, cmp, sel, n);
+          return n;
         }
       }
       else if (get_irn_op(t) == op_Minus &&
@@ -2285,7 +2610,8 @@ static ir_node *transform_node_Mux(ir_node *n)
                 current_ir_graph,
                 block,
                 f, mode);
-          DBG_OPT_ALGSIM0(oldn, n);
+          DBG_OPT_ALGSIM1(oldn, cmp, sel, n);
+          return n;
         }
         else if (proj_nr == pn_Cmp_Ge || proj_nr == pn_Cmp_Gt) {
           /* Mux(a >=/> 0, a, -a)  ==>  Minus(Abs(a)) */
@@ -2298,50 +2624,61 @@ static ir_node *transform_node_Mux(ir_node *n)
                 block,
                 n, mode);
 
-          DBG_OPT_ALGSIM0(oldn, n);
+          DBG_OPT_ALGSIM1(oldn, cmp, sel, n);
+          return n;
         }
       }
 
       if (mode_is_int(mode) && mode_is_signed(mode) &&
           get_mode_arithmetic(mode) == irma_twos_complement) {
+        ir_node *x = get_Cmp_left(cmp);
+
         /* the following optimization works only with signed integer two-complement mode */
 
-        if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Le) &&
-            classify_Const(t) == CNST_ALL_ONE &&
-            classify_Const(f) == CNST_NULL) {
-          /*
-           * Mux(x:T </<= 0, 0, -1) -> Shrs(x, sizeof_bits(T) - 1)
-           * Conditions:
-           * T must be signed.
-           */
-          n = new_rd_Shrs(get_irn_dbg_info(n),
-                current_ir_graph, block, get_Cmp_left(cmp),
-                new_r_Const_long(current_ir_graph, block, mode_Iu,
-                  get_mode_size_bits(mode) - 1),
-                mode);
-          DBG_OPT_ALGSIM0(oldn, n);
-        }
-        else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Ge) &&
-                 classify_Const(t) == CNST_ONE &&
-                 classify_Const(f) == CNST_NULL) {
+        if (mode == get_irn_mode(x)) {
           /*
-           * Mux(x:T >/>= 0, 0, 1) -> Shr(-x, sizeof_bits(T) - 1)
-           * Conditions:
-           * T must be signed.
+           * FIXME: this restriction is two rigid, as it would still
+           * work if mode(x) = Hs and mode == Is, but at least it removes
+           * all wrong cases.
            */
-          n = new_rd_Shr(get_irn_dbg_info(n),
-                current_ir_graph, block,
-                new_r_Minus(current_ir_graph, block,
-                  get_Cmp_left(cmp), mode),
-                new_r_Const_long(current_ir_graph, block, mode_Iu,
-                  get_mode_size_bits(mode) - 1),
-                mode);
-          DBG_OPT_ALGSIM0(oldn, n);
+          if ((proj_nr == pn_Cmp_Lt || proj_nr == pn_Cmp_Le) &&
+              classify_Const(t) == CNST_ALL_ONE &&
+              classify_Const(f) == CNST_NULL) {
+            /*
+             * Mux(x:T </<= 0, 0, -1) -> Shrs(x, sizeof_bits(T) - 1)
+             * Conditions:
+             * T must be signed.
+             */
+            n = new_rd_Shrs(get_irn_dbg_info(n),
+                  current_ir_graph, block, x,
+                  new_r_Const_long(current_ir_graph, block, mode_Iu,
+                    get_mode_size_bits(mode) - 1),
+                  mode);
+            DBG_OPT_ALGSIM1(oldn, cmp, sel, n);
+            return n;
+          }
+          else if ((proj_nr == pn_Cmp_Gt || proj_nr == pn_Cmp_Ge) &&
+                   classify_Const(t) == CNST_ONE &&
+                   classify_Const(f) == CNST_NULL) {
+            /*
+             * Mux(x:T >/>= 0, 0, 1) -> Shr(-x, sizeof_bits(T) - 1)
+             * Conditions:
+             * T must be signed.
+             */
+            n = new_rd_Shr(get_irn_dbg_info(n),
+                  current_ir_graph, block,
+                  new_r_Minus(current_ir_graph, block, x, mode),
+                  new_r_Const_long(current_ir_graph, block, mode_Iu,
+                    get_mode_size_bits(mode) - 1),
+                  mode);
+            DBG_OPT_ALGSIM1(oldn, cmp, sel, n);
+            return n;
+          }
         }
       }
     }
   }
-  return n;
+  return arch_transform_node_Mux(n);
 }
 
 /**
@@ -2374,6 +2711,7 @@ static ir_op *firm_set_default_transform_node(ir_op *op)
   CASE(Div);
   CASE(Mod);
   CASE(DivMod);
+  CASE(Abs);
   CASE(Cond);
   CASE(Eor);
   CASE(Not);
@@ -2387,7 +2725,7 @@ static ir_op *firm_set_default_transform_node(ir_op *op)
   CASE(End);
   CASE(Mux);
   default:
-    op->transform_node  = NULL;
+    op->transform_node = NULL;
   }
 
   return op;
@@ -2831,7 +3169,7 @@ optimize_node (ir_node *n)
        /** common subexpression elimination **/
        /* Checks whether n is already available. */
        /* The block input is used to distinguish different subexpressions. Right
-                now all nodes are op_pin_state_pinned to blocks, i.e., the cse only finds common
+                now all nodes are op_pin_state_pinned to blocks, i.e., the CSE only finds common
                 subexpressions within a block. */
        if (get_opt_cse())
                n = identify_cons (current_ir_graph->value_table, n);