OSDN Git Service

* config/darwin-c.c (add_framework): Copy the directory name as it
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index 7f6b549..74377b6 100644 (file)
@@ -50,6 +50,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0))
 
 static rtx neg_const_int (enum machine_mode, rtx);
  ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0))
 
 static rtx neg_const_int (enum machine_mode, rtx);
+static bool mode_signbit_p (enum machine_mode, rtx);
 static int simplify_plus_minus_op_data_cmp (const void *, const void *);
 static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx,
                                rtx, int);
 static int simplify_plus_minus_op_data_cmp (const void *, const void *);
 static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx,
                                rtx, int);
@@ -57,6 +58,8 @@ static rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode,
                                  unsigned int);
 static rtx simplify_associative_operation (enum rtx_code, enum machine_mode,
                                           rtx, rtx);
                                  unsigned int);
 static rtx simplify_associative_operation (enum rtx_code, enum machine_mode,
                                           rtx, rtx);
+static rtx simplify_relational_operation_1 (enum rtx_code, enum machine_mode,
+                                           enum machine_mode, rtx, rtx);
 \f
 /* Negate a CONST_INT rtx, truncating (because a conversion from a
    maximally negative number can overflow).  */
 \f
 /* Negate a CONST_INT rtx, truncating (because a conversion from a
    maximally negative number can overflow).  */
@@ -66,6 +69,39 @@ neg_const_int (enum machine_mode mode, rtx i)
   return gen_int_mode (- INTVAL (i), mode);
 }
 
   return gen_int_mode (- INTVAL (i), mode);
 }
 
+/* Test whether expression, X, is an immediate constant that represents
+   the most significant bit of machine mode MODE.  */
+
+static bool
+mode_signbit_p (enum machine_mode mode, rtx x)
+{
+  unsigned HOST_WIDE_INT val;
+  unsigned int width;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT)
+    return false;
+
+  width = GET_MODE_BITSIZE (mode);
+  if (width == 0)
+    return false;
+  
+  if (width <= HOST_BITS_PER_WIDE_INT
+      && GET_CODE (x) == CONST_INT)
+    val = INTVAL (x);
+  else if (width <= 2 * HOST_BITS_PER_WIDE_INT
+          && GET_CODE (x) == CONST_DOUBLE
+          && CONST_DOUBLE_LOW (x) == 0)
+    {
+      val = CONST_DOUBLE_HIGH (x);
+      width -= HOST_BITS_PER_WIDE_INT;
+    }
+  else
+    return false;
+
+  if (width < HOST_BITS_PER_WIDE_INT)
+    val &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
+  return val == ((unsigned HOST_WIDE_INT) 1 << (width - 1));
+}
 \f
 /* Make a binary operation by properly ordering the operands and
    seeing if the expression folds.  */
 \f
 /* Make a binary operation by properly ordering the operands and
    seeing if the expression folds.  */
@@ -77,7 +113,7 @@ simplify_gen_binary (enum rtx_code code, enum machine_mode mode, rtx op0,
   rtx tem;
 
   /* Put complex operands first and constants second if commutative.  */
   rtx tem;
 
   /* Put complex operands first and constants second if commutative.  */
-  if (GET_RTX_CLASS (code) == 'c'
+  if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
       && swap_commutative_operands_p (op0, op1))
     tem = op0, op0 = op1, op1 = tem;
 
       && swap_commutative_operands_p (op0, op1))
     tem = op0, op0 = op1, op1 = tem;
 
@@ -132,7 +168,7 @@ avoid_constant_pool_reference (rtx x)
   addr = XEXP (x, 0);
 
   /* Call target hook to avoid the effects of -fpic etc....  */
   addr = XEXP (x, 0);
 
   /* Call target hook to avoid the effects of -fpic etc....  */
-  addr = (*targetm.delegitimize_address) (addr);
+  addr = targetm.delegitimize_address (addr);
 
   if (GET_CODE (addr) == LO_SUM)
     addr = XEXP (addr, 1);
 
   if (GET_CODE (addr) == LO_SUM)
     addr = XEXP (addr, 1);
@@ -187,10 +223,9 @@ simplify_gen_ternary (enum rtx_code code, enum machine_mode mode,
 
   return gen_rtx_fmt_eee (code, mode, op0, op1, op2);
 }
 
   return gen_rtx_fmt_eee (code, mode, op0, op1, op2);
 }
-\f
+
 /* Likewise, for relational operations.
 /* Likewise, for relational operations.
-   CMP_MODE specifies mode comparison is done in.
-  */
+   CMP_MODE specifies mode comparison is done in.  */
 
 rtx
 simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
 
 rtx
 simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
@@ -198,61 +233,9 @@ simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
 {
   rtx tem;
 
 {
   rtx tem;
 
-  if (cmp_mode == VOIDmode)
-    cmp_mode = GET_MODE (op0);
-  if (cmp_mode == VOIDmode)
-    cmp_mode = GET_MODE (op1);
-
-  if (cmp_mode != VOIDmode)
-    {
-      tem = simplify_relational_operation (code, cmp_mode, op0, op1);
-
-      if (tem)
-       {
-#ifdef FLOAT_STORE_FLAG_VALUE
-         if (GET_MODE_CLASS (mode) == MODE_FLOAT)
-           {
-             REAL_VALUE_TYPE val;
-             if (tem == const0_rtx)
-               return CONST0_RTX (mode);
-             if (tem != const_true_rtx)
-               abort ();
-             val = FLOAT_STORE_FLAG_VALUE (mode);
-             return CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
-           }
-#endif
-         return tem;
-       }
-    }
-
-  /* For the following tests, ensure const0_rtx is op1.  */
-  if (swap_commutative_operands_p (op0, op1)
-      || (op0 == const0_rtx && op1 != const0_rtx))
-    tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
-
-  /* If op0 is a compare, extract the comparison arguments from it.  */
-  if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
-    return simplify_gen_relational (code, mode, VOIDmode,
-                                   XEXP (op0, 0), XEXP (op0, 1));
-
-  /* If op0 is a comparison, extract the comparison arguments form it.  */
-  if (GET_RTX_CLASS (GET_CODE (op0)) == '<' && op1 == const0_rtx)
-    {
-      if (code == NE)
-       {
-         if (GET_MODE (op0) == mode)
-           return op0;
-         return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode,
-                                         XEXP (op0, 0), XEXP (op0, 1));
-       }
-      else if (code == EQ)
-       {
-         enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
-         if (new != UNKNOWN)
-           return simplify_gen_relational (new, mode, VOIDmode,
-                                           XEXP (op0, 0), XEXP (op0, 1));
-        }
-    }
+  if (0 != (tem = simplify_relational_operation (code, mode, cmp_mode,
+                                                op0, op1)))
+    return tem;
 
   return gen_rtx_fmt_ee (code, mode, op0, op1);
 }
 
   return gen_rtx_fmt_ee (code, mode, op0, op1);
 }
@@ -277,7 +260,7 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
 
   switch (GET_RTX_CLASS (code))
     {
 
   switch (GET_RTX_CLASS (code))
     {
-    case '1':
+    case RTX_UNARY:
       op0 = XEXP (x, 0);
       op_mode = GET_MODE (op0);
       op0 = simplify_replace_rtx (op0, old, new);
       op0 = XEXP (x, 0);
       op_mode = GET_MODE (op0);
       op0 = simplify_replace_rtx (op0, old, new);
@@ -285,15 +268,16 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
        return x;
       return simplify_gen_unary (code, mode, op0, op_mode);
 
        return x;
       return simplify_gen_unary (code, mode, op0, op_mode);
 
-    case '2':
-    case 'c':
+    case RTX_BIN_ARITH:
+    case RTX_COMM_ARITH:
       op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
       op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
        return x;
       return simplify_gen_binary (code, mode, op0, op1);
 
       op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
       op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
        return x;
       return simplify_gen_binary (code, mode, op0, op1);
 
-    case '<':
+    case RTX_COMPARE:
+    case RTX_COMM_COMPARE:
       op0 = XEXP (x, 0);
       op1 = XEXP (x, 1);
       op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
       op0 = XEXP (x, 0);
       op1 = XEXP (x, 1);
       op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
@@ -303,8 +287,8 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
        return x;
       return simplify_gen_relational (code, mode, op_mode, op0, op1);
 
        return x;
       return simplify_gen_relational (code, mode, op_mode, op0, op1);
 
-    case '3':
-    case 'b':
+    case RTX_TERNARY:
+    case RTX_BITFIELD_OPS:
       op0 = XEXP (x, 0);
       op_mode = GET_MODE (op0);
       op0 = simplify_replace_rtx (op0, old, new);
       op0 = XEXP (x, 0);
       op_mode = GET_MODE (op0);
       op0 = simplify_replace_rtx (op0, old, new);
@@ -316,7 +300,7 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
        op_mode = GET_MODE (op0);
       return simplify_gen_ternary (code, mode, op_mode, op0, op1, op2);
 
        op_mode = GET_MODE (op0);
       return simplify_gen_ternary (code, mode, op_mode, op0, op1, op2);
 
-    case 'x':
+    case RTX_EXTRA:
       /* The only case we try to handle is a SUBREG.  */
       if (code == SUBREG)
        {
       /* The only case we try to handle is a SUBREG.  */
       if (code == SUBREG)
        {
@@ -330,7 +314,7 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
        }
       break;
 
        }
       break;
 
-    case 'o':
+    case RTX_OBJ:
       if (code == MEM)
        {
          op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
       if (code == MEM)
        {
          op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
@@ -771,7 +755,16 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
        case FIX:
          real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL);
          break;
        case FIX:
          real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL);
          break;
+       case NOT:
+         {
+           long tmp[4];
+           int i;
 
 
+           real_to_target (tmp, &d, GET_MODE (trueop));
+           for (i = 0; i < 4; i++)
+             tmp[i] = ~tmp[i];
+           real_from_target (&d, tmp, mode);
+         }
        default:
          abort ();
        }
        default:
          abort ();
        }
@@ -893,7 +886,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
            return XEXP (op, 0);
 
          /* (not (eq X Y)) == (ne X Y), etc.  */
            return XEXP (op, 0);
 
          /* (not (eq X Y)) == (ne X Y), etc.  */
-         if (GET_RTX_CLASS (GET_CODE (op)) == '<'
+         if (COMPARISON_P (op)
              && (mode == BImode || STORE_FLAG_VALUE == -1)
              && ((reversed = reversed_comparison_code (op, NULL_RTX))
                  != UNKNOWN))
              && (mode == BImode || STORE_FLAG_VALUE == -1)
              && ((reversed = reversed_comparison_code (op, NULL_RTX))
                  != UNKNOWN))
@@ -917,6 +910,16 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
                                                   mode)) != 0)
            return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp);
 
                                                   mode)) != 0)
            return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp);
 
+         /* (not (plus X C)) for signbit C is (xor X D) with D = ~C.  */
+         if (GET_CODE (op) == PLUS
+             && GET_CODE (XEXP (op, 1)) == CONST_INT
+             && mode_signbit_p (mode, XEXP (op, 1))
+             && (temp = simplify_unary_operation (NOT, mode,
+                                                  XEXP (op, 1),
+                                                  mode)) != 0)
+           return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp);
+
+
 
          /* (not (ashift 1 X)) is (rotate ~1 X).  We used to do this for
             operands other than 1, but that is not valid.  We could do a
 
          /* (not (ashift 1 X)) is (rotate ~1 X).  We used to do this for
             operands other than 1, but that is not valid.  We could do a
@@ -933,7 +936,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
          /* If STORE_FLAG_VALUE is -1, (not (comparison X Y)) can be done
             by reversing the comparison code if valid.  */
          if (STORE_FLAG_VALUE == -1
          /* If STORE_FLAG_VALUE is -1, (not (comparison X Y)) can be done
             by reversing the comparison code if valid.  */
          if (STORE_FLAG_VALUE == -1
-             && GET_RTX_CLASS (GET_CODE (op)) == '<'
+             && COMPARISON_P (op)
              && (reversed = reversed_comparison_code (op, NULL_RTX))
                 != UNKNOWN)
            return simplify_gen_relational (reversed, mode, VOIDmode,
              && (reversed = reversed_comparison_code (op, NULL_RTX))
                 != UNKNOWN)
            return simplify_gen_relational (reversed, mode, VOIDmode,
@@ -1018,6 +1021,22 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
                                            XEXP (op, 1));
            }
 
                                            XEXP (op, 1));
            }
 
+         /* (neg (ashiftrt X C)) can be replaced by (lshiftrt X C) when
+            C is equal to the width of MODE minus 1.  */
+         if (GET_CODE (op) == ASHIFTRT
+             && GET_CODE (XEXP (op, 1)) == CONST_INT
+             && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
+               return simplify_gen_binary (LSHIFTRT, mode,
+                                           XEXP (op, 0), XEXP (op, 1));
+
+         /* (neg (lshiftrt X C)) can be replaced by (ashiftrt X C) when
+            C is equal to the width of MODE minus 1.  */
+         if (GET_CODE (op) == LSHIFTRT
+             && GET_CODE (XEXP (op, 1)) == CONST_INT
+             && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
+               return simplify_gen_binary (ASHIFTRT, mode,
+                                           XEXP (op, 0), XEXP (op, 1));
+
          break;
 
        case SIGN_EXTEND:
          break;
 
        case SIGN_EXTEND:
@@ -1156,16 +1175,19 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
   rtx trueop0, trueop1;
   rtx tem;
 
   rtx trueop0, trueop1;
   rtx tem;
 
+#ifdef ENABLE_CHECKING
   /* Relational operations don't work here.  We must know the mode
      of the operands in order to do the comparison correctly.
      Assuming a full word can give incorrect results.
      Consider comparing 128 with -128 in QImode.  */
 
   /* Relational operations don't work here.  We must know the mode
      of the operands in order to do the comparison correctly.
      Assuming a full word can give incorrect results.
      Consider comparing 128 with -128 in QImode.  */
 
-  if (GET_RTX_CLASS (code) == '<')
+  if (GET_RTX_CLASS (code) == RTX_COMPARE
+      || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
     abort ();
     abort ();
+#endif
 
   /* Make sure the constant is second.  */
 
   /* Make sure the constant is second.  */
-  if (GET_RTX_CLASS (code) == 'c'
+  if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
       && swap_commutative_operands_p (op0, op1))
     {
       tem = op0, op0 = op1, op1 = tem;
       && swap_commutative_operands_p (op0, op1))
     {
       tem = op0, op0 = op1, op1 = tem;
@@ -1210,26 +1232,56 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       && GET_CODE (trueop1) == CONST_DOUBLE
       && mode == GET_MODE (op0) && mode == GET_MODE (op1))
     {
       && GET_CODE (trueop1) == CONST_DOUBLE
       && mode == GET_MODE (op0) && mode == GET_MODE (op1))
     {
-      REAL_VALUE_TYPE f0, f1, value;
+      if (code == AND
+         || code == IOR
+         || code == XOR)
+       {
+         long tmp0[4];
+         long tmp1[4];
+         REAL_VALUE_TYPE r;
+         int i;
+
+         real_to_target (tmp0, CONST_DOUBLE_REAL_VALUE (op0),
+                         GET_MODE (op0));
+         real_to_target (tmp1, CONST_DOUBLE_REAL_VALUE (op1),
+                         GET_MODE (op1));
+         for (i = 0; i < 4; i++)
+           {
+             if (code == AND)
+               tmp0[i] &= tmp1[i];
+             else if (code == IOR)
+               tmp0[i] |= tmp1[i];
+             else if (code == XOR)
+               tmp0[i] ^= tmp1[i];
+             else
+               abort ();
+           }
+          real_from_target (&r, tmp0, mode);
+          return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
+       }
+      else
+       {
+         REAL_VALUE_TYPE f0, f1, value;
 
 
-      REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
-      REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
-      f0 = real_value_truncate (mode, f0);
-      f1 = real_value_truncate (mode, f1);
+         REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
+         REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
+         f0 = real_value_truncate (mode, f0);
+         f1 = real_value_truncate (mode, f1);
 
 
-      if (HONOR_SNANS (mode)
-         && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1)))
-       return 0;
+         if (HONOR_SNANS (mode)
+             && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1)))
+           return 0;
 
 
-      if (code == DIV
-         && REAL_VALUES_EQUAL (f1, dconst0)
-         && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
-       return 0;
+         if (code == DIV
+             && REAL_VALUES_EQUAL (f1, dconst0)
+             && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
+           return 0;
 
 
-      REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
+         REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
 
 
-      value = real_value_truncate (mode, value);
-      return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
+         value = real_value_truncate (mode, value);
+         return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
+       }
     }
 
   /* We can fold some multi-word operations.  */
     }
 
   /* We can fold some multi-word operations.  */
@@ -1240,8 +1292,8 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       && (GET_CODE (trueop1) == CONST_DOUBLE
          || GET_CODE (trueop1) == CONST_INT))
     {
       && (GET_CODE (trueop1) == CONST_DOUBLE
          || GET_CODE (trueop1) == CONST_INT))
     {
-      unsigned HOST_WIDE_INT l1, l2, lv;
-      HOST_WIDE_INT h1, h2, hv;
+      unsigned HOST_WIDE_INT l1, l2, lv, lt;
+      HOST_WIDE_INT h1, h2, hv, ht;
 
       if (GET_CODE (trueop0) == CONST_DOUBLE)
        l1 = CONST_DOUBLE_LOW (trueop0), h1 = CONST_DOUBLE_HIGH (trueop0);
 
       if (GET_CODE (trueop0) == CONST_DOUBLE)
        l1 = CONST_DOUBLE_LOW (trueop0), h1 = CONST_DOUBLE_HIGH (trueop0);
@@ -1270,10 +1322,29 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
          mul_double (l1, h1, l2, h2, &lv, &hv);
          break;
 
          mul_double (l1, h1, l2, h2, &lv, &hv);
          break;
 
-       case DIV:  case MOD:   case UDIV:  case UMOD:
-         /* We'd need to include tree.h to do this and it doesn't seem worth
-            it.  */
-         return 0;
+       case DIV:
+         if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2,
+                                   &lv, &hv, &lt, &ht))
+           return 0;
+         break;
+
+       case MOD:
+         if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2,
+                                   &lt, &ht, &lv, &hv))
+           return 0;
+         break;
+
+       case UDIV:
+         if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2,
+                                   &lv, &hv, &lt, &ht))
+           return 0;
+         break;
+
+       case UMOD:
+         if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2,
+                                   &lt, &ht, &lv, &hv))
+           return 0;
+         break;
 
        case AND:
          lv = l1 & l2, hv = h1 & h2;
 
        case AND:
          lv = l1 & l2, hv = h1 & h2;
@@ -1330,10 +1401,8 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
        case LSHIFTRT:   case ASHIFTRT:
        case ASHIFT:
        case ROTATE:     case ROTATERT:
        case LSHIFTRT:   case ASHIFTRT:
        case ASHIFT:
        case ROTATE:     case ROTATERT:
-#ifdef SHIFT_COUNT_TRUNCATED
          if (SHIFT_COUNT_TRUNCATED)
            l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0;
          if (SHIFT_COUNT_TRUNCATED)
            l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0;
-#endif
 
          if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode))
            return 0;
 
          if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode))
            return 0;
@@ -1452,6 +1521,17 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
                }
            }
 
                }
            }
 
+         /* (plus (xor X C1) C2) is (xor X (C1^C2)) if C2 is signbit.  */
+         if ((GET_CODE (op1) == CONST_INT
+              || GET_CODE (op1) == CONST_DOUBLE)
+             && GET_CODE (op0) == XOR
+             && (GET_CODE (XEXP (op0, 1)) == CONST_INT
+                 || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE)
+             && mode_signbit_p (mode, op1))
+           return simplify_gen_binary (XOR, mode, XEXP (op0, 0),
+                                       simplify_gen_binary (XOR, mode, op1,
+                                                            XEXP (op0, 1)));
+
          /* If one of the operands is a PLUS or a MINUS, see if we can
             simplify this by the associative law.
             Don't use the associative law for floating point.
          /* If one of the operands is a PLUS or a MINUS, see if we can
             simplify this by the associative law.
             Don't use the associative law for floating point.
@@ -1735,9 +1815,27 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
              && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
                  == GET_MODE_MASK (mode)))
            return simplify_gen_unary (NOT, mode, op0, mode);
              && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
                  == GET_MODE_MASK (mode)))
            return simplify_gen_unary (NOT, mode, op0, mode);
-         if (trueop0 == trueop1 && ! side_effects_p (op0)
+         if (trueop0 == trueop1
+             && ! side_effects_p (op0)
              && GET_MODE_CLASS (mode) != MODE_CC)
            return const0_rtx;
              && GET_MODE_CLASS (mode) != MODE_CC)
            return const0_rtx;
+
+         /* Canonicalize XOR of the most significant bit to PLUS.  */
+         if ((GET_CODE (op1) == CONST_INT
+              || GET_CODE (op1) == CONST_DOUBLE)
+             && mode_signbit_p (mode, op1))
+           return simplify_gen_binary (PLUS, mode, op0, op1);
+         /* (xor (plus X C1) C2) is (xor X (C1^C2)) if C1 is signbit.  */
+         if ((GET_CODE (op1) == CONST_INT
+              || GET_CODE (op1) == CONST_DOUBLE)
+             && GET_CODE (op0) == PLUS
+             && (GET_CODE (XEXP (op0, 1)) == CONST_INT
+                 || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE)
+             && mode_signbit_p (mode, XEXP (op0, 1)))
+           return simplify_gen_binary (XOR, mode, XEXP (op0, 0),
+                                       simplify_gen_binary (XOR, mode, op1,
+                                                            XEXP (op0, 1)));
+             
          tem = simplify_associative_operation (code, mode, op0, op1);
          if (tem)
            return tem;
          tem = simplify_associative_operation (code, mode, op0, op1);
          if (tem)
            return tem;
@@ -1765,70 +1863,127 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
          break;
 
        case UDIV:
          break;
 
        case UDIV:
-         /* Convert divide by power of two into shift (divide by 1 handled
-            below).  */
-         if (GET_CODE (trueop1) == CONST_INT
-             && (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
-           return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1));
-
-         /* Fall through....  */
-
-       case DIV:
-         if (trueop1 == CONST1_RTX (mode))
+         /* 0/x is 0 (or x&0 if x has side-effects).  */
+         if (trueop0 == const0_rtx)
+           return side_effects_p (op1)
+                  ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                  : const0_rtx;
+         /* x/1 is x.  */
+         if (trueop1 == const1_rtx)
            {
            {
-             /* On some platforms DIV uses narrower mode than its
-                operands.  */
+             /* Handle narrowing UDIV.  */
              rtx x = gen_lowpart_common (mode, op0);
              if (x)
                return x;
              rtx x = gen_lowpart_common (mode, op0);
              if (x)
                return x;
-             else if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
+             if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
                return gen_lowpart_SUBREG (mode, op0);
                return gen_lowpart_SUBREG (mode, op0);
-             else
-               return op0;
+             return op0;
            }
            }
+         /* Convert divide by power of two into shift.  */
+         if (GET_CODE (trueop1) == CONST_INT
+             && (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
+           return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1));
+         break;
 
 
-         /* Maybe change 0 / x to 0.  This transformation isn't safe for
-            modes with NaNs, since 0 / 0 will then be NaN rather than 0.
-            Nor is it safe for modes with signed zeros, since dividing
-            0 by a negative number gives -0, not 0.  */
-         if (!HONOR_NANS (mode)
-             && !HONOR_SIGNED_ZEROS (mode)
-             && trueop0 == CONST0_RTX (mode)
-             && ! side_effects_p (op1))
-           return op0;
-
-         /* Change division by a constant into multiplication.  Only do
-            this with -funsafe-math-optimizations.  */
-         else if (GET_CODE (trueop1) == CONST_DOUBLE
-                  && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
-                  && trueop1 != CONST0_RTX (mode)
-                  && flag_unsafe_math_optimizations)
+       case DIV:
+         /* Handle floating point and integers separately.  */
+         if (GET_MODE_CLASS (mode) == MODE_FLOAT)
            {
            {
-             REAL_VALUE_TYPE d;
-             REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
+             /* Maybe change 0.0 / x to 0.0.  This transformation isn't
+                safe for modes with NaNs, since 0.0 / 0.0 will then be
+                NaN rather than 0.0.  Nor is it safe for modes with signed
+                zeros, since dividing 0 by a negative number gives -0.0  */
+             if (trueop0 == CONST0_RTX (mode)
+                 && !HONOR_NANS (mode)
+                 && !HONOR_SIGNED_ZEROS (mode)
+                 && ! side_effects_p (op1))
+               return op0;
+             /* x/1.0 is x.  */
+             if (trueop1 == CONST1_RTX (mode)
+                 && !HONOR_SNANS (mode))
+               return op0;
 
 
-             if (! REAL_VALUES_EQUAL (d, dconst0))
+             if (GET_CODE (trueop1) == CONST_DOUBLE
+                 && trueop1 != CONST0_RTX (mode))
+               {
+                 REAL_VALUE_TYPE d;
+                 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
+
+                 /* x/-1.0 is -x.  */
+                 if (REAL_VALUES_EQUAL (d, dconstm1)
+                     && !HONOR_SNANS (mode))
+                   return simplify_gen_unary (NEG, mode, op0, mode);
+
+                 /* Change FP division by a constant into multiplication.
+                    Only do this with -funsafe-math-optimizations.  */
+                 if (flag_unsafe_math_optimizations
+                     && !REAL_VALUES_EQUAL (d, dconst0))
+                   {
+                     REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d);
+                     tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
+                     return simplify_gen_binary (MULT, mode, op0, tem);
+                   }
+               }
+           }
+         else
+           {
+             /* 0/x is 0 (or x&0 if x has side-effects).  */
+             if (trueop0 == const0_rtx)
+               return side_effects_p (op1)
+                      ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                      : const0_rtx;
+             /* x/1 is x.  */
+             if (trueop1 == const1_rtx)
                {
                {
-                 REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d);
-                 tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
-                 return simplify_gen_binary (MULT, mode, op0, tem);
+                 /* Handle narrowing DIV.  */
+                 rtx x = gen_lowpart_common (mode, op0);
+                 if (x)
+                   return x;
+                 if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
+                   return gen_lowpart_SUBREG (mode, op0);
+                 return op0;
+               }
+             /* x/-1 is -x.  */
+             if (trueop1 == constm1_rtx)
+               {
+                 rtx x = gen_lowpart_common (mode, op0);
+                 if (!x)
+                   x = (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
+                       ? gen_lowpart_SUBREG (mode, op0) : op0;
+                 return simplify_gen_unary (NEG, mode, x, mode);
                }
            }
          break;
 
        case UMOD:
                }
            }
          break;
 
        case UMOD:
-         /* Handle modulus by power of two (mod with 1 handled below).  */
+         /* 0%x is 0 (or x&0 if x has side-effects).  */
+         if (trueop0 == const0_rtx)
+           return side_effects_p (op1)
+                  ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                  : const0_rtx;
+         /* x%1 is 0 (of x&0 if x has side-effects).  */
+         if (trueop1 == const1_rtx)
+           return side_effects_p (op0)
+                  ? simplify_gen_binary (AND, mode, op0, const0_rtx)
+                  : const0_rtx;
+         /* Implement modulus by power of two as AND.  */
          if (GET_CODE (trueop1) == CONST_INT
              && exact_log2 (INTVAL (trueop1)) > 0)
            return simplify_gen_binary (AND, mode, op0,
                                        GEN_INT (INTVAL (op1) - 1));
          if (GET_CODE (trueop1) == CONST_INT
              && exact_log2 (INTVAL (trueop1)) > 0)
            return simplify_gen_binary (AND, mode, op0,
                                        GEN_INT (INTVAL (op1) - 1));
-
-         /* Fall through....  */
+         break;
 
        case MOD:
 
        case MOD:
-         if ((trueop0 == const0_rtx || trueop1 == const1_rtx)
-             && ! side_effects_p (op0) && ! side_effects_p (op1))
-           return const0_rtx;
+         /* 0%x is 0 (or x&0 if x has side-effects).  */
+         if (trueop0 == const0_rtx)
+           return side_effects_p (op1)
+                  ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                  : const0_rtx;
+         /* x%1 and x%-1 is 0 (or x&0 if x has side-effects).  */
+         if (trueop1 == const1_rtx || trueop1 == constm1_rtx)
+           return side_effects_p (op0)
+                  ? simplify_gen_binary (AND, mode, op0, const0_rtx)
+                  : const0_rtx;
          break;
 
        case ROTATERT:
          break;
 
        case ROTATERT:
@@ -2113,10 +2268,8 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       if (arg1 < 0)
        return 0;
 
       if (arg1 < 0)
        return 0;
 
-#ifdef SHIFT_COUNT_TRUNCATED
       if (SHIFT_COUNT_TRUNCATED)
        arg1 %= width;
       if (SHIFT_COUNT_TRUNCATED)
        arg1 %= width;
-#endif
 
       val = ((unsigned HOST_WIDE_INT) arg0) >> arg1;
       break;
 
       val = ((unsigned HOST_WIDE_INT) arg0) >> arg1;
       break;
@@ -2125,10 +2278,8 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       if (arg1 < 0)
        return 0;
 
       if (arg1 < 0)
        return 0;
 
-#ifdef SHIFT_COUNT_TRUNCATED
       if (SHIFT_COUNT_TRUNCATED)
        arg1 %= width;
       if (SHIFT_COUNT_TRUNCATED)
        arg1 %= width;
-#endif
 
       val = ((unsigned HOST_WIDE_INT) arg0) << arg1;
       break;
 
       val = ((unsigned HOST_WIDE_INT) arg0) << arg1;
       break;
@@ -2137,10 +2288,8 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       if (arg1 < 0)
        return 0;
 
       if (arg1 < 0)
        return 0;
 
-#ifdef SHIFT_COUNT_TRUNCATED
       if (SHIFT_COUNT_TRUNCATED)
        arg1 %= width;
       if (SHIFT_COUNT_TRUNCATED)
        arg1 %= width;
-#endif
 
       val = arg0s >> arg1;
 
 
       val = arg0s >> arg1;
 
@@ -2476,16 +2625,109 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
 }
 
 /* Like simplify_binary_operation except used for relational operators.
 }
 
 /* Like simplify_binary_operation except used for relational operators.
-   MODE is the mode of the operands, not that of the result.  If MODE
-   is VOIDmode, both operands must also be VOIDmode and we compare the
-   operands in "infinite precision".
-
-   If no simplification is possible, this function returns zero.  Otherwise,
-   it returns either const_true_rtx or const0_rtx.  */
+   MODE is the mode of the result. If MODE is VOIDmode, both operands must
+   also be VOIDmode.
 
 
+   CMP_MODE specifies in which mode the comparison is done in, so it is
+   the mode of the operands.  If CMP_MODE is VOIDmode, it is taken from
+   the operands or, if both are VOIDmode, the operands are compared in
+   "infinite precision".  */
 rtx
 simplify_relational_operation (enum rtx_code code, enum machine_mode mode,
 rtx
 simplify_relational_operation (enum rtx_code code, enum machine_mode mode,
-                              rtx op0, rtx op1)
+                              enum machine_mode cmp_mode, rtx op0, rtx op1)
+{
+  rtx tem, trueop0, trueop1;
+
+  if (cmp_mode == VOIDmode)
+    cmp_mode = GET_MODE (op0);
+  if (cmp_mode == VOIDmode)
+    cmp_mode = GET_MODE (op1);
+
+  tem = simplify_const_relational_operation (code, cmp_mode, op0, op1);
+  if (tem)
+    {
+#ifdef FLOAT_STORE_FLAG_VALUE
+      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+       {
+          if (tem == const0_rtx)
+            return CONST0_RTX (mode);
+          else if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+           {
+             REAL_VALUE_TYPE val;
+             val = FLOAT_STORE_FLAG_VALUE (mode);
+             return CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
+           }
+       }
+#endif
+
+      return tem;
+    }
+
+  /* For the following tests, ensure const0_rtx is op1.  */
+  if (swap_commutative_operands_p (op0, op1)
+      || (op0 == const0_rtx && op1 != const0_rtx))
+    tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
+
+  /* If op0 is a compare, extract the comparison arguments from it.  */
+  if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
+    return simplify_relational_operation (code, mode, VOIDmode,
+                                         XEXP (op0, 0), XEXP (op0, 1));
+
+  if (mode == VOIDmode
+      || GET_MODE_CLASS (cmp_mode) == MODE_CC
+      || CC0_P (op0))
+    return NULL_RTX;
+
+  trueop0 = avoid_constant_pool_reference (op0);
+  trueop1 = avoid_constant_pool_reference (op1);
+  return simplify_relational_operation_1 (code, mode, cmp_mode,
+                                         trueop0, trueop1);
+}
+
+/* This part of simplify_relational_operation is only used when CMP_MODE
+   is not in class MODE_CC (i.e. it is a real comparison).
+
+   MODE is the mode of the result, while CMP_MODE specifies in which
+   mode the comparison is done in, so it is the mode of the operands.  */
+rtx
+simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode,
+                                enum machine_mode cmp_mode, rtx op0, rtx op1)
+{
+  if (GET_CODE (op1) == CONST_INT)
+    {
+      if (INTVAL (op1) == 0 && COMPARISON_P (op0))
+       {
+         /* If op0 is a comparison, extract the comparison arguments form it.  */
+         if (code == NE)
+           {
+             if (GET_MODE (op0) == cmp_mode)
+               return simplify_rtx (op0);
+             else
+               return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode,
+                                               XEXP (op0, 0), XEXP (op0, 1));
+           }
+         else if (code == EQ)
+           {
+             enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
+             if (new != UNKNOWN)
+               return simplify_gen_relational (new, mode, VOIDmode,
+                                               XEXP (op0, 0), XEXP (op0, 1));
+           }
+       }
+    }
+
+  return NULL_RTX;
+}
+
+/* Check if the given comparison (done in the given MODE) is actually a
+   tautology or a contradiction.
+   If no simplification is possible, this function returns zero.
+   Otherwise, it returns either const_true_rtx or const0_rtx.  */
+
+rtx
+simplify_const_relational_operation (enum rtx_code code,
+                                    enum machine_mode mode,
+                                    rtx op0, rtx op1)
 {
   int equal, op0lt, op0ltu, op1lt, op1ltu;
   rtx tem;
 {
   int equal, op0lt, op0ltu, op1lt, op1ltu;
   rtx tem;
@@ -2524,17 +2766,18 @@ simplify_relational_operation (enum rtx_code code, enum machine_mode mode,
      If CODE is an unsigned comparison, then we can never do this optimization,
      because it gives an incorrect result if the subtraction wraps around zero.
      ANSI C defines unsigned operations such that they never overflow, and
      If CODE is an unsigned comparison, then we can never do this optimization,
      because it gives an incorrect result if the subtraction wraps around zero.
      ANSI C defines unsigned operations such that they never overflow, and
-     thus such cases can not be ignored.  */
+     thus such cases can not be ignored; but we cannot do it even for
+     signed comparisons for languages such as Java, so test flag_wrapv.  */
 
 
-  if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
+  if (!flag_wrapv && INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
       && ! ((GET_CODE (op0) == REG || GET_CODE (trueop0) == CONST_INT)
            && (GET_CODE (op1) == REG || GET_CODE (trueop1) == CONST_INT))
       && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
       /* We cannot do this for == or != if tem is a nonzero address.  */
       && ((code != EQ && code != NE) || ! nonzero_address_p (tem))
       && code != GTU && code != GEU && code != LTU && code != LEU)
       && ! ((GET_CODE (op0) == REG || GET_CODE (trueop0) == CONST_INT)
            && (GET_CODE (op1) == REG || GET_CODE (trueop1) == CONST_INT))
       && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
       /* We cannot do this for == or != if tem is a nonzero address.  */
       && ((code != EQ && code != NE) || ! nonzero_address_p (tem))
       && code != GTU && code != GEU && code != LTU && code != LEU)
-    return simplify_relational_operation (signed_condition (code),
-                                         mode, tem, const0_rtx);
+    return simplify_const_relational_operation (signed_condition (code),
+                                               mode, tem, const0_rtx);
 
   if (flag_unsafe_math_optimizations && code == ORDERED)
     return const_true_rtx;
 
   if (flag_unsafe_math_optimizations && code == ORDERED)
     return const_true_rtx;
@@ -2854,24 +3097,12 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
                  && rtx_equal_p (XEXP (op0, 1), op1))))
        return op2;
 
                  && rtx_equal_p (XEXP (op0, 1), op1))))
        return op2;
 
-      if (GET_RTX_CLASS (GET_CODE (op0)) == '<' && ! side_effects_p (op0))
+      if (COMPARISON_P (op0) && ! side_effects_p (op0))
        {
          enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode
                                        ? GET_MODE (XEXP (op0, 1))
                                        : GET_MODE (XEXP (op0, 0)));
          rtx temp;
        {
          enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode
                                        ? GET_MODE (XEXP (op0, 1))
                                        : GET_MODE (XEXP (op0, 0)));
          rtx temp;
-         if (cmp_mode == VOIDmode)
-           cmp_mode = op0_mode;
-         temp = simplify_relational_operation (GET_CODE (op0), cmp_mode,
-                                               XEXP (op0, 0), XEXP (op0, 1));
-
-         /* See if any simplifications were possible.  */
-         if (temp == const0_rtx)
-           return op2;
-         else if (temp == const_true_rtx)
-           return op1;
-         else if (temp)
-           abort ();
 
          /* Look for happy constants in op1 and op2.  */
          if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
 
          /* Look for happy constants in op1 and op2.  */
          if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
@@ -2892,7 +3123,23 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
              else
                break;
 
              else
                break;
 
-             return gen_rtx_fmt_ee (code, mode, XEXP (op0, 0), XEXP (op0, 1));
+             return simplify_gen_relational (code, mode, cmp_mode,
+                                             XEXP (op0, 0), XEXP (op0, 1));
+           }
+
+         if (cmp_mode == VOIDmode)
+           cmp_mode = op0_mode;
+         temp = simplify_relational_operation (GET_CODE (op0), op0_mode,
+                                               cmp_mode, XEXP (op0, 0),
+                                               XEXP (op0, 1));
+
+         /* See if any simplifications were possible.  */
+         if (temp)
+           {
+             if (GET_CODE (temp) == CONST_INT)
+               return temp == const0_rtx ? op2 : op1;
+             else if (temp)
+               return gen_rtx_IF_THEN_ELSE (mode, temp, op1, op2);
            }
        }
       break;
            }
        }
       break;
@@ -3501,48 +3748,38 @@ simplify_rtx (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
   enum machine_mode mode = GET_MODE (x);
 {
   enum rtx_code code = GET_CODE (x);
   enum machine_mode mode = GET_MODE (x);
-  rtx temp;
 
   switch (GET_RTX_CLASS (code))
     {
 
   switch (GET_RTX_CLASS (code))
     {
-    case '1':
+    case RTX_UNARY:
       return simplify_unary_operation (code, mode,
                                       XEXP (x, 0), GET_MODE (XEXP (x, 0)));
       return simplify_unary_operation (code, mode,
                                       XEXP (x, 0), GET_MODE (XEXP (x, 0)));
-    case 'c':
+    case RTX_COMM_ARITH:
       if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
        return simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0));
 
       /* Fall through....  */
 
       if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
        return simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0));
 
       /* Fall through....  */
 
-    case '2':
+    case RTX_BIN_ARITH:
       return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1));
 
       return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1));
 
-    case '3':
-    case 'b':
+    case RTX_TERNARY:
+    case RTX_BITFIELD_OPS:
       return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)),
                                         XEXP (x, 0), XEXP (x, 1),
                                         XEXP (x, 2));
 
       return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)),
                                         XEXP (x, 0), XEXP (x, 1),
                                         XEXP (x, 2));
 
-    case '<':
-      temp = simplify_relational_operation (code,
-                                           ((GET_MODE (XEXP (x, 0))
-                                             != VOIDmode)
-                                            ? GET_MODE (XEXP (x, 0))
-                                            : GET_MODE (XEXP (x, 1))),
-                                           XEXP (x, 0), XEXP (x, 1));
-#ifdef FLOAT_STORE_FLAG_VALUE
-      if (temp != 0 && GET_MODE_CLASS (mode) == MODE_FLOAT)
-       {
-         if (temp == const0_rtx)
-           temp = CONST0_RTX (mode);
-         else
-           temp = CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE (mode),
-                                                mode);
-       }
-#endif
-      return temp;
-
-    case 'x':
+    case RTX_COMPARE:
+    case RTX_COMM_COMPARE:
+      return simplify_relational_operation (code, mode,
+                                            ((GET_MODE (XEXP (x, 0))
+                                             != VOIDmode)
+                                            ? GET_MODE (XEXP (x, 0))
+                                            : GET_MODE (XEXP (x, 1))),
+                                            XEXP (x, 0),
+                                            XEXP (x, 1));
+
+    case RTX_EXTRA:
       if (code == SUBREG)
        return simplify_gen_subreg (mode, SUBREG_REG (x),
                                    GET_MODE (SUBREG_REG (x)),
       if (code == SUBREG)
        return simplify_gen_subreg (mode, SUBREG_REG (x),
                                    GET_MODE (SUBREG_REG (x)),
@@ -3554,7 +3791,7 @@ simplify_rtx (rtx x)
        }
       break;
 
        }
       break;
 
-    case 'o':
+    case RTX_OBJ:
       if (code == LO_SUM)
        {
          /* Convert (lo_sum (high FOO) FOO) to FOO.  */
       if (code == LO_SUM)
        {
          /* Convert (lo_sum (high FOO) FOO) to FOO.  */