OSDN Git Service

* gcc.dg/20040910-1.c, gcc.dg/cpp/digraph2.c,
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index 3789f33..e463fef 100644 (file)
@@ -50,7 +50,6 @@ 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);
-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);
@@ -72,7 +71,7 @@ neg_const_int (enum machine_mode mode, rtx i)
 /* Test whether expression, X, is an immediate constant that represents
    the most significant bit of machine mode MODE.  */
 
-static bool
+bool
 mode_signbit_p (enum machine_mode mode, rtx x)
 {
   unsigned HOST_WIDE_INT val;
@@ -240,38 +239,38 @@ simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
   return gen_rtx_fmt_ee (code, mode, op0, op1);
 }
 \f
-/* Replace all occurrences of OLD in X with NEW and try to simplify the
+/* Replace all occurrences of OLD_RTX in X with NEW_RTX and try to simplify the
    resulting RTX.  Return a new RTX which is as simplified as possible.  */
 
 rtx
-simplify_replace_rtx (rtx x, rtx old, rtx new)
+simplify_replace_rtx (rtx x, rtx old_rtx, rtx new_rtx)
 {
   enum rtx_code code = GET_CODE (x);
   enum machine_mode mode = GET_MODE (x);
   enum machine_mode op_mode;
   rtx op0, op1, op2;
 
-  /* If X is OLD, return NEW.  Otherwise, if this is an expression, try
+  /* If X is OLD_RTX, return NEW_RTX.  Otherwise, if this is an expression, try
      to build a new expression substituting recursively.  If we can't do
      anything, return our input.  */
 
-  if (x == old)
-    return new;
+  if (x == old_rtx)
+    return new_rtx;
 
   switch (GET_RTX_CLASS (code))
     {
     case RTX_UNARY:
       op0 = XEXP (x, 0);
       op_mode = GET_MODE (op0);
-      op0 = simplify_replace_rtx (op0, old, new);
+      op0 = simplify_replace_rtx (op0, old_rtx, new_rtx);
       if (op0 == XEXP (x, 0))
        return x;
       return simplify_gen_unary (code, mode, op0, op_mode);
 
     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);
+      op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx);
+      op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx);
       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
        return x;
       return simplify_gen_binary (code, mode, op0, op1);
@@ -281,8 +280,8 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
       op0 = XEXP (x, 0);
       op1 = XEXP (x, 1);
       op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
-      op0 = simplify_replace_rtx (op0, old, new);
-      op1 = simplify_replace_rtx (op1, old, new);
+      op0 = simplify_replace_rtx (op0, old_rtx, new_rtx);
+      op1 = simplify_replace_rtx (op1, old_rtx, new_rtx);
       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
        return x;
       return simplify_gen_relational (code, mode, op_mode, op0, op1);
@@ -291,9 +290,9 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
     case RTX_BITFIELD_OPS:
       op0 = XEXP (x, 0);
       op_mode = GET_MODE (op0);
-      op0 = simplify_replace_rtx (op0, old, new);
-      op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
-      op2 = simplify_replace_rtx (XEXP (x, 2), old, new);
+      op0 = simplify_replace_rtx (op0, old_rtx, new_rtx);
+      op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx);
+      op2 = simplify_replace_rtx (XEXP (x, 2), old_rtx, new_rtx);
       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2))
        return x;
       if (op_mode == VOIDmode)
@@ -304,7 +303,7 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
       /* The only case we try to handle is a SUBREG.  */
       if (code == SUBREG)
        {
-         op0 = simplify_replace_rtx (SUBREG_REG (x), old, new);
+         op0 = simplify_replace_rtx (SUBREG_REG (x), old_rtx, new_rtx);
          if (op0 == SUBREG_REG (x))
            return x;
          op0 = simplify_gen_subreg (GET_MODE (x), op0,
@@ -317,15 +316,15 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
     case RTX_OBJ:
       if (code == MEM)
        {
-         op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
+         op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx);
          if (op0 == XEXP (x, 0))
            return x;
          return replace_equiv_address_nv (x, op0);
        }
       else if (code == LO_SUM)
        {
-         op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
-         op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
+         op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx);
+         op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx);
 
          /* (lo_sum (high x) x) -> x  */
          if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
@@ -337,8 +336,8 @@ simplify_replace_rtx (rtx x, rtx old, rtx new)
        }
       else if (code == REG)
        {
-         if (REG_P (old) && REGNO (x) == REGNO (old))
-           return new;
+         if (REG_P (old_rtx) && REGNO (x) == REGNO (old_rtx))
+           return new_rtx;
        }
       break;
 
@@ -360,16 +359,15 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
 
   if (code == VEC_DUPLICATE)
     {
-      if (!VECTOR_MODE_P (mode))
-       abort ();
-      if (GET_MODE (trueop) != VOIDmode
-         && !VECTOR_MODE_P (GET_MODE (trueop))
-         && GET_MODE_INNER (mode) != GET_MODE (trueop))
-       abort ();
-      if (GET_MODE (trueop) != VOIDmode
-         && VECTOR_MODE_P (GET_MODE (trueop))
-         && GET_MODE_INNER (mode) != GET_MODE_INNER (GET_MODE (trueop)))
-       abort ();
+      gcc_assert (VECTOR_MODE_P (mode));
+      if (GET_MODE (trueop) != VOIDmode)
+      {
+       if (!VECTOR_MODE_P (GET_MODE (trueop)))
+         gcc_assert (GET_MODE_INNER (mode) == GET_MODE (trueop));
+       else
+         gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER
+                                               (GET_MODE (trueop)));
+      }
       if (GET_CODE (trueop) == CONST_INT || GET_CODE (trueop) == CONST_DOUBLE
          || GET_CODE (trueop) == CONST_VECTOR)
        {
@@ -387,8 +385,8 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
               int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode));
               unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size);
 
-             if (in_n_elts >= n_elts || n_elts % in_n_elts)
-               abort ();
+             gcc_assert (in_n_elts < n_elts);
+             gcc_assert ((n_elts % in_n_elts) == 0);
              for (i = 0; i < n_elts; i++)
                RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop, i % in_n_elts);
            }
@@ -408,9 +406,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
       rtvec v = rtvec_alloc (n_elts);
       unsigned int i;
 
-      if (op_n_elts != n_elts)
-       abort ();
-
+      gcc_assert (op_n_elts == n_elts);
       for (i = 0; i < n_elts; i++)
        {
          rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode),
@@ -541,15 +537,13 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
        case ZERO_EXTEND:
          /* When zero-extending a CONST_INT, we need to know its
              original mode.  */
-         if (op_mode == VOIDmode)
-           abort ();
+         gcc_assert (op_mode != VOIDmode);
          if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
            {
              /* If we were really extending the mode,
                 we would have to distinguish between zero-extension
                 and sign-extension.  */
-             if (width != GET_MODE_BITSIZE (op_mode))
-               abort ();
+             gcc_assert (width == GET_MODE_BITSIZE (op_mode));
              val = arg0;
            }
          else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
@@ -566,8 +560,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
              /* If we were really extending the mode,
                 we would have to distinguish between zero-extension
                 and sign-extension.  */
-             if (width != GET_MODE_BITSIZE (op_mode))
-               abort ();
+             gcc_assert (width == GET_MODE_BITSIZE (op_mode));
              val = arg0;
            }
          else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
@@ -590,7 +583,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
          return 0;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       val = trunc_int_for_mode (val, mode);
@@ -690,8 +683,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
          break;
 
        case ZERO_EXTEND:
-         if (op_mode == VOIDmode)
-           abort ();
+         gcc_assert (op_mode != VOIDmode);
 
          if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
            return 0;
@@ -766,7 +758,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
            real_from_target (&d, tmp, mode);
          }
        default:
-         abort ();
+         gcc_unreachable ();
        }
       return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
     }
@@ -864,7 +856,7 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
       return immed_double_const (xl, xh, mode);
     }
@@ -1175,16 +1167,12 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
   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.  */
-
-  if (GET_RTX_CLASS (code) == RTX_COMPARE
-      || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
-    abort ();
-#endif
+  gcc_assert (GET_RTX_CLASS (code) != RTX_COMPARE);
+  gcc_assert (GET_RTX_CLASS (code) != RTX_COMM_COMPARE);
 
   /* Make sure the constant is second.  */
   if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
@@ -1211,9 +1199,8 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       rtvec v = rtvec_alloc (n_elts);
       unsigned int i;
 
-      if (op0_n_elts != n_elts || op1_n_elts != n_elts)
-       abort ();
-
+      gcc_assert (op0_n_elts == n_elts);
+      gcc_assert (op1_n_elts == n_elts);
       for (i = 0; i < n_elts; i++)
        {
          rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode),
@@ -1247,14 +1234,20 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
                          GET_MODE (op1));
          for (i = 0; i < 4; i++)
            {
-             if (code == AND)
+             switch (code)
+             {
+             case AND:
                tmp0[i] &= tmp1[i];
-             else if (code == IOR)
+               break;
+             case IOR:
                tmp0[i] |= tmp1[i];
-             else if (code == XOR)
+               break;
+             case XOR:
                tmp0[i] ^= tmp1[i];
-             else
-               abort ();
+               break;
+             default:
+               gcc_unreachable ();
+             }
            }
           real_from_target (&r, tmp0, mode);
           return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
@@ -1791,8 +1784,7 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
                 uppermost bit is set, then this isn't a power of two due
                 to implicit sign extension.  */
              && (width <= HOST_BITS_PER_WIDE_INT
-                 || val != HOST_BITS_PER_WIDE_INT - 1)
-             && ! rtx_equal_function_value_matters)
+                 || val != HOST_BITS_PER_WIDE_INT - 1))
            return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val));
 
          /* x*2 is x+x and x*(-1) is -x */
@@ -2143,24 +2135,22 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
        case VEC_SELECT:
          if (!VECTOR_MODE_P (mode))
            {
-             if (!VECTOR_MODE_P (GET_MODE (trueop0))
-                 || (mode
-                     != GET_MODE_INNER (GET_MODE (trueop0)))
-                 || GET_CODE (trueop1) != PARALLEL
-                 || XVECLEN (trueop1, 0) != 1
-                 || GET_CODE (XVECEXP (trueop1, 0, 0)) != CONST_INT)
-               abort ();
+             gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0)));
+             gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0)));
+             gcc_assert (GET_CODE (trueop1) == PARALLEL);
+             gcc_assert (XVECLEN (trueop1, 0) == 1);
+             gcc_assert (GET_CODE (XVECEXP (trueop1, 0, 0)) == CONST_INT);
 
              if (GET_CODE (trueop0) == CONST_VECTOR)
-               return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP (trueop1, 0, 0)));
+               return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP
+                                                         (trueop1, 0, 0)));
            }
          else
            {
-             if (!VECTOR_MODE_P (GET_MODE (trueop0))
-                 || (GET_MODE_INNER (mode)
-                     != GET_MODE_INNER (GET_MODE (trueop0)))
-                 || GET_CODE (trueop1) != PARALLEL)
-               abort ();
+             gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0)));
+             gcc_assert (GET_MODE_INNER (mode)
+                         == GET_MODE_INNER (GET_MODE (trueop0)));
+             gcc_assert (GET_CODE (trueop1) == PARALLEL);
 
              if (GET_CODE (trueop0) == CONST_VECTOR)
                {
@@ -2169,15 +2159,14 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
                  rtvec v = rtvec_alloc (n_elts);
                  unsigned int i;
 
-                 if (XVECLEN (trueop1, 0) != (int) n_elts)
-                   abort ();
+                 gcc_assert (XVECLEN (trueop1, 0) == (int) n_elts);
                  for (i = 0; i < n_elts; i++)
                    {
                      rtx x = XVECEXP (trueop1, 0, i);
 
-                     if (GET_CODE (x) != CONST_INT)
-                       abort ();
-                     RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, INTVAL (x));
+                     gcc_assert (GET_CODE (x) == CONST_INT);
+                     RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0,
+                                                          INTVAL (x));
                    }
 
                  return gen_rtx_CONST_VECTOR (mode, v);
@@ -2193,24 +2182,21 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
                                          ? GET_MODE (trueop1)
                                          : GET_MODE_INNER (mode));
 
-           if (!VECTOR_MODE_P (mode)
-               || (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode)
-                   != GET_MODE_SIZE (mode)))
-             abort ();
-
-           if ((VECTOR_MODE_P (op0_mode)
-                && (GET_MODE_INNER (mode)
-                    != GET_MODE_INNER (op0_mode)))
-               || (!VECTOR_MODE_P (op0_mode)
-                   && GET_MODE_INNER (mode) != op0_mode))
-             abort ();
-
-           if ((VECTOR_MODE_P (op1_mode)
-                && (GET_MODE_INNER (mode)
-                    != GET_MODE_INNER (op1_mode)))
-               || (!VECTOR_MODE_P (op1_mode)
-                   && GET_MODE_INNER (mode) != op1_mode))
-             abort ();
+           gcc_assert (VECTOR_MODE_P (mode));
+           gcc_assert (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode)
+                       == GET_MODE_SIZE (mode));
+
+           if (VECTOR_MODE_P (op0_mode))
+             gcc_assert (GET_MODE_INNER (mode)
+                         == GET_MODE_INNER (op0_mode));
+           else
+             gcc_assert (GET_MODE_INNER (mode) == op0_mode);
+
+           if (VECTOR_MODE_P (op1_mode))
+             gcc_assert (GET_MODE_INNER (mode)
+                         == GET_MODE_INNER (op1_mode));
+           else
+             gcc_assert (GET_MODE_INNER (mode) == op1_mode);
 
            if ((GET_CODE (trueop0) == CONST_VECTOR
                 || GET_CODE (trueop0) == CONST_INT
@@ -2252,7 +2238,7 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
          return 0;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       return 0;
@@ -2344,41 +2330,26 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       break;
 
     case LSHIFTRT:
-      /* If shift count is undefined, don't fold it; let the machine do
-        what it wants.  But truncate it if the machine will do that.  */
-      if (arg1 < 0)
-       return 0;
-
-      if (SHIFT_COUNT_TRUNCATED)
-       arg1 %= width;
-
-      val = ((unsigned HOST_WIDE_INT) arg0) >> arg1;
-      break;
-
     case ASHIFT:
-      if (arg1 < 0)
-       return 0;
-
-      if (SHIFT_COUNT_TRUNCATED)
-       arg1 %= width;
-
-      val = ((unsigned HOST_WIDE_INT) arg0) << arg1;
-      break;
-
     case ASHIFTRT:
-      if (arg1 < 0)
-       return 0;
-
+      /* Truncate the shift if SHIFT_COUNT_TRUNCATED, otherwise make sure the
+        value is in range.  We can't return any old value for out-of-range
+        arguments because either the middle-end (via shift_truncation_mask)
+        or the back-end might be relying on target-specific knowledge.
+        Nor can we rely on shift_truncation_mask, since the shift might
+        not be part of an ashlM3, lshrM3 or ashrM3 instruction.  */
       if (SHIFT_COUNT_TRUNCATED)
-       arg1 %= width;
-
-      val = arg0s >> arg1;
+       arg1 = (unsigned HOST_WIDE_INT) arg1 % width;
+      else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode))
+       return 0;
 
-      /* Bootstrap compiler may not have sign extended the right shift.
-        Manually extend the sign to insure bootstrap cc matches gcc.  */
-      if (arg0s < 0 && arg1 > 0)
-       val |= ((HOST_WIDE_INT) -1) << (HOST_BITS_PER_WIDE_INT - arg1);
+      val = (code == ASHIFT
+            ? ((unsigned HOST_WIDE_INT) arg0) << arg1
+            : ((unsigned HOST_WIDE_INT) arg0) >> arg1);
 
+      /* Sign-extend the result for arithmetic right shifts.  */
+      if (code == ASHIFTRT && arg0s < 0 && arg1 > 0)
+       val |= ((HOST_WIDE_INT) -1) << (width - arg1);
       break;
 
     case ROTATERT:
@@ -2429,7 +2400,7 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
       return 0;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   val = trunc_int_for_mode (val, mode);
@@ -2707,7 +2678,7 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
 
 /* Like simplify_binary_operation except used for relational operators.
    MODE is the mode of the result. If MODE is VOIDmode, both operands must
-   also be VOIDmode.
+   not 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
@@ -2727,19 +2698,45 @@ simplify_relational_operation (enum rtx_code code, enum machine_mode mode,
   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);
-           }
+#ifdef FLOAT_STORE_FLAG_VALUE
+         {
+           REAL_VALUE_TYPE val;
+           val = FLOAT_STORE_FLAG_VALUE (mode);
+           return CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
+         }
+#else
+         return NULL_RTX;
+#endif 
        }
+      if (VECTOR_MODE_P (mode))
+       {
+         if (tem == const0_rtx)
+           return CONST0_RTX (mode);
+#ifdef VECTOR_STORE_FLAG_VALUE
+         {
+           int i, units;
+           rtvec c;
+
+           rtx val = VECTOR_STORE_FLAG_VALUE (mode);
+           if (val == NULL_RTX)
+             return NULL_RTX;
+           if (val == const1_rtx)
+             return CONST1_RTX (mode);
+
+           units = GET_MODE_NUNITS (mode);
+           v = rtvec_alloc (units);
+           for (i = 0; i < units; i++)
+             RTVEC_ELT (v, i) = val;
+           return gen_rtx_raw_CONST_VECTOR (mode, v);
+         }
+#else
+         return NULL_RTX;
 #endif
+       }
 
       return tem;
     }
@@ -2789,9 +2786,9 @@ simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode,
            }
          else if (code == EQ)
            {
-             enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
-             if (new != UNKNOWN)
-               return simplify_gen_relational (new, mode, VOIDmode,
+             enum rtx_code new_code = reversed_comparison_code (op0, NULL_RTX);
+             if (new_code != UNKNOWN)
+               return simplify_gen_relational (new_code, mode, VOIDmode,
                                                XEXP (op0, 0), XEXP (op0, 1));
            }
        }
@@ -2815,10 +2812,9 @@ simplify_const_relational_operation (enum rtx_code code,
   rtx trueop0;
   rtx trueop1;
 
-  if (mode == VOIDmode
-      && (GET_MODE (op0) != VOIDmode
-         || GET_MODE (op1) != VOIDmode))
-    abort ();
+  gcc_assert (mode != VOIDmode
+             || (GET_MODE (op0) == VOIDmode
+                 && GET_MODE (op1) == VOIDmode));
 
   /* If op0 is a compare, extract the comparison arguments from it.  */
   if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
@@ -2974,7 +2970,7 @@ simplify_const_relational_operation (enum rtx_code code,
   else
     {
       /* Optimize comparisons with upper and lower bounds.  */
-      if (INTEGRAL_MODE_P (mode)
+      if (SCALAR_INT_MODE_P (mode)
          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
        {
          rtx mmin, mmax;
@@ -3117,7 +3113,7 @@ simplify_const_relational_operation (enum rtx_code code,
     case UNORDERED:
       return const0_rtx;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 \f
@@ -3256,10 +3252,9 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
       break;
 
     case VEC_MERGE:
-      if (GET_MODE (op0) != mode
-         || GET_MODE (op1) != mode
-         || !VECTOR_MODE_P (mode))
-       abort ();
+      gcc_assert (GET_MODE (op0) == mode);
+      gcc_assert (GET_MODE (op1) == mode);
+      gcc_assert (VECTOR_MODE_P (mode));
       op2 = avoid_constant_pool_reference (op2);
       if (GET_CODE (op2) == CONST_INT)
        {
@@ -3290,7 +3285,7 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   return 0;
@@ -3344,11 +3339,10 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
       elems = &op;
       elem_bitsize = max_bitsize;
     }
-
-  if (BITS_PER_UNIT % value_bit != 0)
-    abort ();  /* Too complicated; reducing value_bit may help.  */
-  if (elem_bitsize % BITS_PER_UNIT != 0)
-    abort ();  /* I don't know how to handle endianness of sub-units.  */
+  /* If this asserts, it is too complicated; reducing value_bit may help.  */
+  gcc_assert (BITS_PER_UNIT % value_bit == 0);
+  /* I don't know how to handle endianness of sub-units.  */
+  gcc_assert (elem_bitsize % BITS_PER_UNIT == 0);
   
   for (elem = 0; elem < num_elem; elem++)
     {
@@ -3385,8 +3379,7 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
            {
              /* If this triggers, someone should have generated a
                 CONST_INT instead.  */
-             if (elem_bitsize <= HOST_BITS_PER_WIDE_INT)
-               abort ();
+             gcc_assert (elem_bitsize > HOST_BITS_PER_WIDE_INT);
 
              for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit)
                *vp++ = CONST_DOUBLE_LOW (el) >> i;
@@ -3401,15 +3394,14 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
              for (; i < max_bitsize; i += value_bit)
                *vp++ = 0;
            }
-         else if (GET_MODE_CLASS (GET_MODE (el)) == MODE_FLOAT)
+         else
            {
              long tmp[max_bitsize / 32];
              int bitsize = GET_MODE_BITSIZE (GET_MODE (el));
-             
-             if (bitsize > elem_bitsize)
-               abort ();
-             if (bitsize % value_bit != 0)
-               abort ();
+
+             gcc_assert (GET_MODE_CLASS (GET_MODE (el)) == MODE_FLOAT);
+             gcc_assert (bitsize <= elem_bitsize);
+             gcc_assert (bitsize % value_bit == 0);
 
              real_to_target (tmp, CONST_DOUBLE_REAL_VALUE (el),
                              GET_MODE (el));
@@ -3433,12 +3425,10 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
              for (; i < elem_bitsize; i += value_bit)
                *vp++ = 0;
            }
-         else
-           abort ();
          break;
          
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -3458,8 +3448,7 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
 
   /* BYTE should still be inside OP.  (Note that BYTE is unsigned,
      so if it's become negative it will instead be very large.)  */
-  if (byte >= GET_MODE_SIZE (innermode))
-    abort ();
+  gcc_assert (byte < GET_MODE_SIZE (innermode));
 
   /* Convert from bytes to chunks of size value_bit.  */
   value_start = byte * (BITS_PER_UNIT / value_bit);
@@ -3483,10 +3472,8 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
   outer_class = GET_MODE_CLASS (outer_submode);
   elem_bitsize = GET_MODE_BITSIZE (outer_submode);
 
-  if (elem_bitsize % value_bit != 0)
-    abort ();
-  if (elem_bitsize + value_start * value_bit > max_bitsize)
-    abort ();
+  gcc_assert (elem_bitsize % value_bit == 0);
+  gcc_assert (elem_bitsize + value_start * value_bit <= max_bitsize);
 
   for (elem = 0; elem < num_elem; elem++)
     {
@@ -3556,7 +3543,7 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
          break;
            
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   if (VECTOR_MODE_P (outermode))
@@ -3572,17 +3559,16 @@ simplify_subreg (enum machine_mode outermode, rtx op,
                 enum machine_mode innermode, unsigned int byte)
 {
   /* Little bit of sanity checking.  */
-  if (innermode == VOIDmode || outermode == VOIDmode
-      || innermode == BLKmode || outermode == BLKmode)
-    abort ();
+  gcc_assert (innermode != VOIDmode);
+  gcc_assert (outermode != VOIDmode);
+  gcc_assert (innermode != BLKmode);
+  gcc_assert (outermode != BLKmode);
 
-  if (GET_MODE (op) != innermode
-      && GET_MODE (op) != VOIDmode)
-    abort ();
+  gcc_assert (GET_MODE (op) == innermode
+             || GET_MODE (op) == VOIDmode);
 
-  if (byte % GET_MODE_SIZE (outermode)
-      || byte >= GET_MODE_SIZE (innermode))
-    abort ();
+  gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0);
+  gcc_assert (byte < GET_MODE_SIZE (innermode));
 
   if (outermode == innermode && !byte)
     return op;
@@ -3598,7 +3584,7 @@ simplify_subreg (enum machine_mode outermode, rtx op,
     {
       enum machine_mode innermostmode = GET_MODE (SUBREG_REG (op));
       int final_offset = byte + SUBREG_BYTE (op);
-      rtx new;
+      rtx newx;
 
       if (outermode == innermostmode
          && byte == 0 && SUBREG_BYTE (op) == 0)
@@ -3655,11 +3641,11 @@ simplify_subreg (enum machine_mode outermode, rtx op,
        }
 
       /* Recurse for further possible simplifications.  */
-      new = simplify_subreg (outermode, SUBREG_REG (op),
+      newx = simplify_subreg (outermode, SUBREG_REG (op),
                             GET_MODE (SUBREG_REG (op)),
                             final_offset);
-      if (new)
-       return new;
+      if (newx)
+       return newx;
       return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
     }
 
@@ -3669,8 +3655,6 @@ simplify_subreg (enum machine_mode outermode, rtx op,
      frame, or argument pointer, leave this as a SUBREG.  */
 
   if (REG_P (op)
-      && (! REG_FUNCTION_VALUE_P (op)
-         || ! rtx_equal_function_value_matters)
       && REGNO (op) < FIRST_PSEUDO_REGISTER
 #ifdef CANNOT_CHANGE_MODE_CLASS
       && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode)
@@ -3788,28 +3772,25 @@ rtx
 simplify_gen_subreg (enum machine_mode outermode, rtx op,
                     enum machine_mode innermode, unsigned int byte)
 {
-  rtx new;
+  rtx newx;
   /* Little bit of sanity checking.  */
-  if (innermode == VOIDmode || outermode == VOIDmode
-      || innermode == BLKmode || outermode == BLKmode)
-    abort ();
-
-  if (GET_MODE (op) != innermode
-      && GET_MODE (op) != VOIDmode)
-    abort ();
+  gcc_assert (innermode != VOIDmode);
+  gcc_assert (outermode != VOIDmode);
+  gcc_assert (innermode != BLKmode);
+  gcc_assert (outermode != BLKmode);
 
-  if (byte % GET_MODE_SIZE (outermode)
-      || byte >= GET_MODE_SIZE (innermode))
-    abort ();
+  gcc_assert (GET_MODE (op) == innermode
+             || GET_MODE (op) == VOIDmode);
 
-  if (GET_CODE (op) == QUEUED)
-    return NULL_RTX;
+  gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0);
+  gcc_assert (byte < GET_MODE_SIZE (innermode));
 
-  new = simplify_subreg (outermode, op, innermode, byte);
-  if (new)
-    return new;
+  newx = simplify_subreg (outermode, op, innermode, byte);
+  if (newx)
+    return newx;
 
-  if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode)
+  if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode
+      || (REG_P (op) && REGNO (op) < FIRST_PSEUDO_REGISTER))
     return NULL_RTX;
 
   return gen_rtx_SUBREG (outermode, op, byte);