OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index 6a5ec1a..a0c4395 100644 (file)
@@ -1,7 +1,7 @@
 /* RTL simplification functions for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011  Free Software Foundation, Inc.
+   2011, 2012  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -244,7 +244,8 @@ avoid_constant_pool_reference (rtx x)
       /* If we're accessing the constant in a different mode than it was
          originally stored, attempt to fix that up via subreg simplifications.
          If that fails we have no choice but to return the original memory.  */
-      if (offset != 0 || cmode != GET_MODE (x))
+      if ((offset != 0 || cmode != GET_MODE (x))
+         && offset >= 0 && offset < GET_MODE_SIZE (cmode))
         {
           rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset);
           if (tem && CONSTANT_P (tem))
@@ -268,7 +269,7 @@ delegitimize_mem_from_attrs (rtx x)
      use their base addresses as equivalent.  */
   if (MEM_P (x)
       && MEM_EXPR (x)
-      && MEM_OFFSET (x))
+      && MEM_OFFSET_KNOWN_P (x))
     {
       tree decl = MEM_EXPR (x);
       enum machine_mode mode = GET_MODE (x);
@@ -321,7 +322,7 @@ delegitimize_mem_from_attrs (rtx x)
        {
          rtx newx;
 
-         offset += INTVAL (MEM_OFFSET (x));
+         offset += MEM_OFFSET (x);
 
          newx = DECL_RTL (decl);
 
@@ -649,7 +650,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
       if (STORE_FLAG_VALUE == -1
          && GET_CODE (op) == ASHIFTRT
          && GET_CODE (XEXP (op, 1))
-         && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
+         && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1)
        return simplify_gen_relational (GE, mode, VOIDmode,
                                        XEXP (op, 0), const0_rtx);
 
@@ -765,7 +766,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
         C is equal to the width of MODE minus 1.  */
       if (GET_CODE (op) == ASHIFTRT
          && CONST_INT_P (XEXP (op, 1))
-         && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
+         && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1)
        return simplify_gen_binary (LSHIFTRT, mode,
                                    XEXP (op, 0), XEXP (op, 1));
 
@@ -773,7 +774,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
         C is equal to the width of MODE minus 1.  */
       if (GET_CODE (op) == LSHIFTRT
          && CONST_INT_P (XEXP (op, 1))
-         && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
+         && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1)
        return simplify_gen_binary (ASHIFTRT, mode,
                                    XEXP (op, 0), XEXP (op, 1));
 
@@ -790,14 +791,14 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
          && SCALAR_INT_MODE_P (GET_MODE (XEXP (op, 0))))
        {
          enum machine_mode inner = GET_MODE (XEXP (op, 0));
-         int isize = GET_MODE_BITSIZE (inner);
+         int isize = GET_MODE_PRECISION (inner);
          if (STORE_FLAG_VALUE == 1)
            {
              temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0),
                                          GEN_INT (isize - 1));
              if (mode == inner)
                return temp;
-             if (GET_MODE_BITSIZE (mode) > isize)
+             if (GET_MODE_PRECISION (mode) > isize)
                return simplify_gen_unary (SIGN_EXTEND, mode, temp, inner);
              return simplify_gen_unary (TRUNCATE, mode, temp, inner);
            }
@@ -807,7 +808,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
                                          GEN_INT (isize - 1));
              if (mode == inner)
                return temp;
-             if (GET_MODE_BITSIZE (mode) > isize)
+             if (GET_MODE_PRECISION (mode) > isize)
                return simplify_gen_unary (ZERO_EXTEND, mode, temp, inner);
              return simplify_gen_unary (TRUNCATE, mode, temp, inner);
            }
@@ -852,11 +853,10 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
          truncation.  But don't do this for an (LSHIFTRT (MULT ...))
          since this will cause problems with the umulXi3_highpart
          patterns.  */
-      if ((TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
-                                GET_MODE_BITSIZE (GET_MODE (op)))
+      if ((TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op))
           ? (num_sign_bit_copies (op, GET_MODE (op))
-             > (unsigned int) (GET_MODE_BITSIZE (GET_MODE (op))
-                               - GET_MODE_BITSIZE (mode)))
+             > (unsigned int) (GET_MODE_PRECISION (GET_MODE (op))
+                               - GET_MODE_PRECISION (mode)))
           : truncated_to_mode (mode, op))
          && ! (GET_CODE (op) == LSHIFTRT
                && GET_CODE (XEXP (op, 0)) == MULT))
@@ -866,7 +866,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
          STORE_FLAG_VALUE permits.  This is like the previous test,
          but it works even if the comparison is done in a mode larger
          than HOST_BITS_PER_WIDE_INT.  */
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+      if (HWI_COMPUTABLE_MODE_P (mode)
          && COMPARISON_P (op)
          && (STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0)
        return rtl_hooks.gen_lowpart_no_emit (mode, op);
@@ -905,7 +905,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
          && (flag_unsafe_math_optimizations
              || (SCALAR_FLOAT_MODE_P (GET_MODE (op))
                  && ((unsigned)significand_size (GET_MODE (op))
-                     >= (GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0)))
+                     >= (GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))
                          - num_sign_bit_copies (XEXP (op, 0),
                                                 GET_MODE (XEXP (op, 0))))))))
        return simplify_gen_unary (FLOAT, mode,
@@ -942,7 +942,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
          || (GET_CODE (op) == FLOAT
              && SCALAR_FLOAT_MODE_P (GET_MODE (op))
              && ((unsigned)significand_size (GET_MODE (op))
-                 >= (GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0)))
+                 >= (GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))
                      - num_sign_bit_copies (XEXP (op, 0),
                                             GET_MODE (XEXP (op, 0)))))))
        return simplify_gen_unary (GET_CODE (op), mode,
@@ -969,7 +969,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
        return op;
 
       /* If operand is known to be only -1 or 0, convert ABS to NEG.  */
-      if (num_sign_bit_copies (op, mode) == GET_MODE_BITSIZE (mode))
+      if (num_sign_bit_copies (op, mode) == GET_MODE_PRECISION (mode))
        return gen_rtx_NEG (mode, op);
 
       break;
@@ -1262,8 +1262,8 @@ rtx
 simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
                                rtx op, enum machine_mode op_mode)
 {
-  unsigned int width = GET_MODE_BITSIZE (mode);
-  unsigned int op_width = GET_MODE_BITSIZE (op_mode);
+  unsigned int width = GET_MODE_PRECISION (mode);
+  unsigned int op_width = GET_MODE_PRECISION (op_mode);
 
   if (code == VEC_DUPLICATE)
     {
@@ -1363,7 +1363,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          if (hv < 0)
            return 0;
        }
-      else if (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT * 2)
+      else if (GET_MODE_PRECISION (op_mode) >= HOST_BITS_PER_WIDE_INT * 2)
        ;
       else
        hv = 0, lv &= GET_MODE_MASK (op_mode);
@@ -1374,8 +1374,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
     }
 
   if (CONST_INT_P (op)
-      && width <= HOST_BITS_PER_WIDE_INT
-      && op_width <= HOST_BITS_PER_WIDE_INT && op_width > 0)
+      && width <= HOST_BITS_PER_WIDE_INT && width > 0)
     {
       HOST_WIDE_INT arg0 = INTVAL (op);
       HOST_WIDE_INT val;
@@ -1395,50 +1394,50 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          break;
 
        case FFS:
-         arg0 &= GET_MODE_MASK (op_mode);
+         arg0 &= GET_MODE_MASK (mode);
          val = ffs_hwi (arg0);
          break;
 
        case CLZ:
-         arg0 &= GET_MODE_MASK (op_mode);
-         if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (op_mode, val))
+         arg0 &= GET_MODE_MASK (mode);
+         if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val))
            ;
          else
-           val = GET_MODE_BITSIZE (op_mode) - floor_log2 (arg0) - 1;
+           val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 1;
          break;
 
        case CLRSB:
-         arg0 &= GET_MODE_MASK (op_mode);
+         arg0 &= GET_MODE_MASK (mode);
          if (arg0 == 0)
-           val = GET_MODE_BITSIZE (op_mode) - 1;
+           val = GET_MODE_PRECISION (mode) - 1;
          else if (arg0 >= 0)
-           val = GET_MODE_BITSIZE (op_mode) - floor_log2 (arg0) - 2;
+           val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 2;
          else if (arg0 < 0)
-           val = GET_MODE_BITSIZE (op_mode) - floor_log2 (~arg0) - 2;
+           val = GET_MODE_PRECISION (mode) - floor_log2 (~arg0) - 2;
          break;
 
        case CTZ:
-         arg0 &= GET_MODE_MASK (op_mode);
+         arg0 &= GET_MODE_MASK (mode);
          if (arg0 == 0)
            {
              /* Even if the value at zero is undefined, we have to come
                 up with some replacement.  Seems good enough.  */
-             if (! CTZ_DEFINED_VALUE_AT_ZERO (op_mode, val))
-               val = GET_MODE_BITSIZE (op_mode);
+             if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val))
+               val = GET_MODE_PRECISION (mode);
            }
          else
            val = ctz_hwi (arg0);
          break;
 
        case POPCOUNT:
-         arg0 &= GET_MODE_MASK (op_mode);
+         arg0 &= GET_MODE_MASK (mode);
          val = 0;
          while (arg0)
            val++, arg0 &= arg0 - 1;
          break;
 
        case PARITY:
-         arg0 &= GET_MODE_MASK (op_mode);
+         arg0 &= GET_MODE_MASK (mode);
          val = 0;
          while (arg0)
            val++, arg0 &= arg0 - 1;
@@ -1468,12 +1467,12 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          /* When zero-extending a CONST_INT, we need to know its
              original mode.  */
          gcc_assert (op_mode != VOIDmode);
-         if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
+         if (op_width == HOST_BITS_PER_WIDE_INT)
            {
              /* If we were really extending the mode,
                 we would have to distinguish between zero-extension
                 and sign-extension.  */
-             gcc_assert (width == GET_MODE_BITSIZE (op_mode));
+             gcc_assert (width == op_width);
              val = arg0;
            }
          else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
@@ -1485,15 +1484,16 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
        case SIGN_EXTEND:
          if (op_mode == VOIDmode)
            op_mode = mode;
-         if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
+         op_width = GET_MODE_PRECISION (op_mode);
+         if (op_width == HOST_BITS_PER_WIDE_INT)
            {
              /* If we were really extending the mode,
                 we would have to distinguish between zero-extension
                 and sign-extension.  */
-             gcc_assert (width == GET_MODE_BITSIZE (op_mode));
+             gcc_assert (width == op_width);
              val = arg0;
            }
-         else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
+         else if (op_width < HOST_BITS_PER_WIDE_INT)
            {
              val = arg0 & GET_MODE_MASK (op_mode);
              if (val_signbit_known_set_p (op_mode, val))
@@ -1566,12 +1566,12 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
        case CLZ:
          hv = 0;
          if (h1 != 0)
-           lv = GET_MODE_BITSIZE (mode) - floor_log2 (h1) - 1
+           lv = GET_MODE_PRECISION (mode) - floor_log2 (h1) - 1
              - HOST_BITS_PER_WIDE_INT;
          else if (l1 != 0)
-           lv = GET_MODE_BITSIZE (mode) - floor_log2 (l1) - 1;
+           lv = GET_MODE_PRECISION (mode) - floor_log2 (l1) - 1;
          else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv))
-           lv = GET_MODE_BITSIZE (mode);
+           lv = GET_MODE_PRECISION (mode);
          break;
 
        case CTZ:
@@ -1581,7 +1581,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          else if (h1 != 0)
            lv = HOST_BITS_PER_WIDE_INT + ctz_hwi (h1);
          else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv))
-           lv = GET_MODE_BITSIZE (mode);
+           lv = GET_MODE_PRECISION (mode);
          break;
 
        case POPCOUNT:
@@ -1635,7 +1635,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
        case ZERO_EXTEND:
          gcc_assert (op_mode != VOIDmode);
 
-         if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
+         if (op_width > HOST_BITS_PER_WIDE_INT)
            return 0;
 
          hv = 0;
@@ -1644,7 +1644,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
 
        case SIGN_EXTEND:
          if (op_mode == VOIDmode
-             || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
+             || op_width > HOST_BITS_PER_WIDE_INT)
            return 0;
          else
            {
@@ -1921,7 +1921,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
 {
   rtx tem, reversed, opleft, opright;
   HOST_WIDE_INT val;
-  unsigned int width = GET_MODE_BITSIZE (mode);
+  unsigned int width = GET_MODE_PRECISION (mode);
 
   /* Even if we can't compute a constant result,
      there are some cases worth simplifying.  */
@@ -2033,7 +2033,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
              coeff = immed_double_int_const (val, mode);
 
              tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-             return rtx_cost (tem, SET, speed) <= rtx_cost (orig, SET, speed)
+             return set_src_cost (tem, speed) <= set_src_cost (orig, speed)
                ? tem : 0;
            }
        }
@@ -2214,7 +2214,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
              coeff = immed_double_int_const (val, mode);
 
              tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-             return rtx_cost (tem, SET, speed) <= rtx_cost (orig, SET, speed)
+             return set_src_cost (tem, speed) <= set_src_cost (orig, speed)
                ? tem : 0;
            }
        }
@@ -2240,7 +2240,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
                                    neg_const_int (mode, op1));
 
       /* (x - (x & y)) -> (x & ~y) */
-      if (GET_CODE (op1) == AND)
+      if (INTEGRAL_MODE_P (mode) && GET_CODE (op1) == AND)
        {
          if (rtx_equal_p (op0, XEXP (op1, 0)))
            {
@@ -2432,9 +2432,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
     case IOR:
       if (trueop1 == CONST0_RTX (mode))
        return op0;
-      if (CONST_INT_P (trueop1)
-         && ((UINTVAL (trueop1) & GET_MODE_MASK (mode))
-             == GET_MODE_MASK (mode)))
+      if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode))
        return op1;
       if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
        return op0;
@@ -2447,7 +2445,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
 
       /* (ior A C) is C if all bits of A that might be nonzero are on in C.  */
       if (CONST_INT_P (op1)
-         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+         && HWI_COMPUTABLE_MODE_P (mode)
          && (nonzero_bits (op0, mode) & ~UINTVAL (op1)) == 0)
        return op1;
 
@@ -2506,7 +2504,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
           && CONST_INT_P (XEXP (opleft, 1))
           && CONST_INT_P (XEXP (opright, 1))
           && (INTVAL (XEXP (opleft, 1)) + INTVAL (XEXP (opright, 1))
-              == GET_MODE_BITSIZE (mode)))
+              == GET_MODE_PRECISION (mode)))
         return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1));
 
       /* Same, but for ashift that has been "simplified" to a wider mode
@@ -2525,14 +2523,14 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
           && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1))
           && CONST_INT_P (XEXP (opright, 1))
           && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + INTVAL (XEXP (opright, 1))
-              == GET_MODE_BITSIZE (mode)))
+              == GET_MODE_PRECISION (mode)))
         return gen_rtx_ROTATE (mode, XEXP (opright, 0),
                                XEXP (SUBREG_REG (opleft), 1));
 
       /* If we have (ior (and (X C1) C2)), simplify this by making
         C1 as small as possible if C1 actually changes.  */
       if (CONST_INT_P (op1)
-         && (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+         && (HWI_COMPUTABLE_MODE_P (mode)
              || INTVAL (op1) > 0)
          && GET_CODE (op0) == AND
          && CONST_INT_P (XEXP (op0, 1))
@@ -2560,6 +2558,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
           HOST_WIDE_INT mask = INTVAL (trueop1) << count;
 
           if (mask >> count == INTVAL (trueop1)
+             && trunc_int_for_mode (mask, mode) == mask
               && (mask & nonzero_bits (XEXP (op0, 0), mode)) == 0)
            return simplify_gen_binary (ASHIFTRT, mode,
                                        plus_constant (XEXP (op0, 0), mask),
@@ -2574,9 +2573,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
     case XOR:
       if (trueop1 == CONST0_RTX (mode))
        return op0;
-      if (CONST_INT_P (trueop1)
-         && ((UINTVAL (trueop1) & GET_MODE_MASK (mode))
-             == GET_MODE_MASK (mode)))
+      if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode))
        return simplify_gen_unary (NOT, mode, op0, mode);
       if (rtx_equal_p (trueop0, trueop1)
          && ! side_effects_p (op0)
@@ -2603,7 +2600,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
         convert them into an IOR.  This helps to detect rotation encoded
         using those methods and possibly other simplifications.  */
 
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+      if (HWI_COMPUTABLE_MODE_P (mode)
          && (nonzero_bits (op0, mode)
              & nonzero_bits (op1, mode)) == 0)
        return (simplify_gen_binary (IOR, mode, op0, op1));
@@ -2703,7 +2700,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
          && trueop1 == const1_rtx
          && GET_CODE (op0) == LSHIFTRT
          && CONST_INT_P (XEXP (op0, 1))
-         && INTVAL (XEXP (op0, 1)) == GET_MODE_BITSIZE (mode) - 1)
+         && INTVAL (XEXP (op0, 1)) == GET_MODE_PRECISION (mode) - 1)
        return gen_rtx_GE (mode, XEXP (op0, 0), const0_rtx);
 
       /* (xor (comparison foo bar) (const_int sign-bit))
@@ -2722,7 +2719,9 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
     case AND:
       if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0))
        return trueop1;
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+      if (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode))
+       return op0;
+      if (HWI_COMPUTABLE_MODE_P (mode))
        {
          HOST_WIDE_INT nzop0 = nonzero_bits (trueop0, mode);
          HOST_WIDE_INT nzop1;
@@ -2755,7 +2754,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
       if ((GET_CODE (op0) == SIGN_EXTEND
           || GET_CODE (op0) == ZERO_EXTEND)
          && CONST_INT_P (trueop1)
-         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+         && HWI_COMPUTABLE_MODE_P (mode)
          && (~GET_MODE_MASK (GET_MODE (XEXP (op0, 0)))
              & UINTVAL (trueop1)) == 0)
        {
@@ -2837,7 +2836,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
          Also, if (N & M) == 0, then
         (A +- N) & M -> A & M.  */
       if (CONST_INT_P (trueop1)
-         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+         && HWI_COMPUTABLE_MODE_P (mode)
          && ~UINTVAL (trueop1)
          && (UINTVAL (trueop1) & (UINTVAL (trueop1) + 1)) == 0
          && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS))
@@ -2956,7 +2955,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
                }
            }
        }
-      else
+      else if (SCALAR_INT_MODE_P (mode))
        {
          /* 0/x is 0 (or x&0 if x has side-effects).  */
          if (trueop0 == CONST0_RTX (mode)
@@ -3062,7 +3061,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
          unsigned HOST_WIDE_INT zero_val = 0;
 
          if (CLZ_DEFINED_VALUE_AT_ZERO (imode, zero_val)
-             && zero_val == GET_MODE_BITSIZE (imode)
+             && zero_val == GET_MODE_PRECISION (imode)
              && INTVAL (trueop1) == exact_log2 (zero_val))
            return simplify_gen_relational (EQ, mode, imode,
                                            XEXP (op0, 0), const0_rtx);
@@ -3352,7 +3351,7 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode,
 {
   HOST_WIDE_INT arg0, arg1, arg0s, arg1s;
   HOST_WIDE_INT val;
-  unsigned int width = GET_MODE_BITSIZE (mode);
+  unsigned int width = GET_MODE_PRECISION (mode);
 
   if (VECTOR_MODE_P (mode)
       && code != VEC_CONCAT
@@ -3637,24 +3636,24 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode,
            unsigned HOST_WIDE_INT cnt;
 
            if (SHIFT_COUNT_TRUNCATED)
-             o1 = double_int_zext (o1, GET_MODE_BITSIZE (mode));
+             o1 = double_int_zext (o1, GET_MODE_PRECISION (mode));
 
            if (!double_int_fits_in_uhwi_p (o1)
-               || double_int_to_uhwi (o1) >= GET_MODE_BITSIZE (mode))
+               || double_int_to_uhwi (o1) >= GET_MODE_PRECISION (mode))
              return 0;
 
            cnt = double_int_to_uhwi (o1);
 
            if (code == LSHIFTRT || code == ASHIFTRT)
-             res = double_int_rshift (o0, cnt, GET_MODE_BITSIZE (mode),
+             res = double_int_rshift (o0, cnt, GET_MODE_PRECISION (mode),
                                       code == ASHIFTRT);
            else if (code == ASHIFT)
-             res = double_int_lshift (o0, cnt, GET_MODE_BITSIZE (mode),
+             res = double_int_lshift (o0, cnt, GET_MODE_PRECISION (mode),
                                       true);
            else if (code == ROTATE)
-             res = double_int_lrotate (o0, cnt, GET_MODE_BITSIZE (mode));
+             res = double_int_lrotate (o0, cnt, GET_MODE_PRECISION (mode));
            else /* code == ROTATERT */
-             res = double_int_rrotate (o0, cnt, GET_MODE_BITSIZE (mode));
+             res = double_int_rrotate (o0, cnt, GET_MODE_PRECISION (mode));
          }
          break;
 
@@ -3768,8 +3767,8 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode,
             shift_truncation_mask, since the shift might not be part of an
             ashlM3, lshrM3 or ashrM3 instruction.  */
          if (SHIFT_COUNT_TRUNCATED)
-           arg1 &= targetm.shift_truncation_mask (mode);
-         else if (arg1 < 0 || arg1 >= GET_MODE_PRECISION (mode))
+           arg1 = (unsigned HOST_WIDE_INT) arg1 % width;
+         else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode))
            return 0;
 
          val = (code == ASHIFT
@@ -3950,7 +3949,7 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
              /* ~a -> (-a - 1) */
              if (n_ops != 7)
                {
-                 ops[n_ops].op = constm1_rtx;
+                 ops[n_ops].op = CONSTM1_RTX (mode);
                  ops[n_ops++].neg = this_neg;
                  ops[i].op = XEXP (this_op, 0);
                  ops[i].neg = !this_neg;
@@ -4355,10 +4354,20 @@ simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode,
     {
       rtx x = XEXP (op0, 0);
       rtx c = XEXP (op0, 1);
+      enum rtx_code invcode = op0code == PLUS ? MINUS : PLUS;
+      rtx tem = simplify_gen_binary (invcode, cmp_mode, op1, c);
+
+      /* Detect an infinite recursive condition, where we oscillate at this
+        simplification case between:
+           A + B == C  <--->  C - B == A,
+        where A, B, and C are all constants with non-simplifiable expressions,
+        usually SYMBOL_REFs.  */
+      if (GET_CODE (tem) == invcode
+         && CONSTANT_P (x)
+         && rtx_equal_p (c, XEXP (tem, 1)))
+       return NULL_RTX;
 
-      c = simplify_gen_binary (op0code == PLUS ? MINUS : PLUS,
-                              cmp_mode, op1, c);
-      return simplify_gen_relational (code, mode, cmp_mode, x, c);
+      return simplify_gen_relational (code, mode, cmp_mode, x, tem);
     }
 
   /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is
@@ -4627,7 +4636,7 @@ simplify_const_relational_operation (enum rtx_code code,
        && (GET_CODE (trueop1) == CONST_DOUBLE
           || CONST_INT_P (trueop1)))
     {
-      int width = GET_MODE_BITSIZE (mode);
+      int width = GET_MODE_PRECISION (mode);
       HOST_WIDE_INT l0s, h0s, l1s, h1s;
       unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u;
 
@@ -4682,8 +4691,7 @@ simplify_const_relational_operation (enum rtx_code code,
     }
 
   /* Optimize comparisons with upper and lower bounds.  */
-  if (SCALAR_INT_MODE_P (mode)
-      && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+  if (HWI_COMPUTABLE_MODE_P (mode)
       && CONST_INT_P (trueop1))
     {
       int sign;
@@ -4816,7 +4824,7 @@ simplify_const_relational_operation (enum rtx_code code,
          rtx inner_const = avoid_constant_pool_reference (XEXP (op0, 1));
          if (CONST_INT_P (inner_const) && inner_const != const0_rtx)
            {
-             int sign_bitnum = GET_MODE_BITSIZE (mode) - 1;
+             int sign_bitnum = GET_MODE_PRECISION (mode) - 1;
              int has_sign = (HOST_BITS_PER_WIDE_INT >= sign_bitnum
                              && (UINTVAL (inner_const)
                                  & ((unsigned HOST_WIDE_INT) 1
@@ -4908,7 +4916,7 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
                            enum machine_mode op0_mode, rtx op0, rtx op1,
                            rtx op2)
 {
-  unsigned int width = GET_MODE_BITSIZE (mode);
+  unsigned int width = GET_MODE_PRECISION (mode);
   bool any_change = false;
   rtx tem;
 
@@ -4953,32 +4961,24 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
        {
          /* Extracting a bit-field from a constant */
          unsigned HOST_WIDE_INT val = UINTVAL (op0);
-
+         HOST_WIDE_INT op1val = INTVAL (op1);
+         HOST_WIDE_INT op2val = INTVAL (op2);
          if (BITS_BIG_ENDIAN)
-           val >>= GET_MODE_BITSIZE (op0_mode) - INTVAL (op2) - INTVAL (op1);
+           val >>= GET_MODE_PRECISION (op0_mode) - op2val - op1val;
          else
-           val >>= INTVAL (op2);
+           val >>= op2val;
 
-         if (HOST_BITS_PER_WIDE_INT != INTVAL (op1))
+         if (HOST_BITS_PER_WIDE_INT != op1val)
            {
              /* First zero-extend.  */
-             val &= ((unsigned HOST_WIDE_INT) 1 << INTVAL (op1)) - 1;
+             val &= ((unsigned HOST_WIDE_INT) 1 << op1val) - 1;
              /* If desired, propagate sign bit.  */
              if (code == SIGN_EXTRACT
-                 && (val & ((unsigned HOST_WIDE_INT) 1 << (INTVAL (op1) - 1)))
+                 && (val & ((unsigned HOST_WIDE_INT) 1 << (op1val - 1)))
                     != 0)
-               val |= ~ (((unsigned HOST_WIDE_INT) 1 << INTVAL (op1)) - 1);
+               val |= ~ (((unsigned HOST_WIDE_INT) 1 << op1val) - 1);
            }
 
-         /* Clear the bits that don't belong in our mode,
-            unless they and our sign bit are all one.
-            So we get either a reasonable negative value or a reasonable
-            unsigned value for this mode.  */
-         if (width < HOST_BITS_PER_WIDE_INT
-             && ((val & ((unsigned HOST_WIDE_INT) (-1) << (width - 1)))
-                 != ((unsigned HOST_WIDE_INT) (-1) << (width - 1))))
-           val &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
-
          return gen_int_mode (val, mode);
        }
       break;
@@ -5621,7 +5621,8 @@ simplify_subreg (enum machine_mode outermode, rtx op,
   /* Optimize SUBREG truncations of zero and sign extended values.  */
   if ((GET_CODE (op) == ZERO_EXTEND
        || GET_CODE (op) == SIGN_EXTEND)
-      && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode))
+      && SCALAR_INT_MODE_P (innermode)
+      && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode))
     {
       unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte);
 
@@ -5637,7 +5638,7 @@ simplify_subreg (enum machine_mode outermode, rtx op,
          enum machine_mode origmode = GET_MODE (XEXP (op, 0));
          if (outermode == origmode)
            return XEXP (op, 0);
-         if (GET_MODE_BITSIZE (outermode) <= GET_MODE_BITSIZE (origmode))
+         if (GET_MODE_PRECISION (outermode) <= GET_MODE_PRECISION (origmode))
            return simplify_gen_subreg (outermode, XEXP (op, 0), origmode,
                                        subreg_lowpart_offset (outermode,
                                                               origmode));
@@ -5649,7 +5650,7 @@ simplify_subreg (enum machine_mode outermode, rtx op,
       /* A SUBREG resulting from a zero extension may fold to zero if
         it extracts higher bits that the ZERO_EXTEND's source bits.  */
       if (GET_CODE (op) == ZERO_EXTEND
-         && bitpos >= GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))))
+         && bitpos >= GET_MODE_PRECISION (GET_MODE (XEXP (op, 0))))
        return CONST0_RTX (outermode);
     }
 
@@ -5659,15 +5660,16 @@ simplify_subreg (enum machine_mode outermode, rtx op,
   if ((GET_CODE (op) == LSHIFTRT
        || GET_CODE (op) == ASHIFTRT)
       && SCALAR_INT_MODE_P (outermode)
+      && SCALAR_INT_MODE_P (innermode)
       /* Ensure that OUTERMODE is at least twice as wide as the INNERMODE
         to avoid the possibility that an outer LSHIFTRT shifts by more
         than the sign extension's sign_bit_copies and introduces zeros
         into the high bits of the result.  */
-      && (2 * GET_MODE_BITSIZE (outermode)) <= GET_MODE_BITSIZE (innermode)
+      && (2 * GET_MODE_PRECISION (outermode)) <= GET_MODE_PRECISION (innermode)
       && CONST_INT_P (XEXP (op, 1))
       && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND
       && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode
-      && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode)
+      && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode)
       && subreg_lsb_1 (outermode, innermode, byte) == 0)
     return simplify_gen_binary (ASHIFTRT, outermode,
                                XEXP (XEXP (op, 0), 0), XEXP (op, 1));
@@ -5678,11 +5680,12 @@ simplify_subreg (enum machine_mode outermode, rtx op,
   if ((GET_CODE (op) == LSHIFTRT
        || GET_CODE (op) == ASHIFTRT)
       && SCALAR_INT_MODE_P (outermode)
-      && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode)
+      && SCALAR_INT_MODE_P (innermode)
+      && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode)
       && CONST_INT_P (XEXP (op, 1))
       && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND
       && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode
-      && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode)
+      && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode)
       && subreg_lsb_1 (outermode, innermode, byte) == 0)
     return simplify_gen_binary (LSHIFTRT, outermode,
                                XEXP (XEXP (op, 0), 0), XEXP (op, 1));
@@ -5692,12 +5695,13 @@ simplify_subreg (enum machine_mode outermode, rtx op,
      the outer subreg is effectively a truncation to the original mode.  */
   if (GET_CODE (op) == ASHIFT
       && SCALAR_INT_MODE_P (outermode)
-      && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode)
+      && SCALAR_INT_MODE_P (innermode)
+      && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode)
       && CONST_INT_P (XEXP (op, 1))
       && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND
          || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND)
       && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode
-      && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode)
+      && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode)
       && subreg_lsb_1 (outermode, innermode, byte) == 0)
     return simplify_gen_binary (ASHIFT, outermode,
                                XEXP (XEXP (op, 0), 0), XEXP (op, 1));
@@ -5705,13 +5709,13 @@ simplify_subreg (enum machine_mode outermode, rtx op,
   /* Recognize a word extraction from a multi-word subreg.  */
   if ((GET_CODE (op) == LSHIFTRT
        || GET_CODE (op) == ASHIFTRT)
-      && SCALAR_INT_MODE_P (outermode)
-      && GET_MODE_BITSIZE (outermode) >= BITS_PER_WORD
-      && GET_MODE_BITSIZE (innermode) >= (2 * GET_MODE_BITSIZE (outermode))
+      && SCALAR_INT_MODE_P (innermode)
+      && GET_MODE_PRECISION (outermode) >= BITS_PER_WORD
+      && GET_MODE_PRECISION (innermode) >= (2 * GET_MODE_PRECISION (outermode))
       && CONST_INT_P (XEXP (op, 1))
-      && (INTVAL (XEXP (op, 1)) & (GET_MODE_BITSIZE (outermode) - 1)) == 0
+      && (INTVAL (XEXP (op, 1)) & (GET_MODE_PRECISION (outermode) - 1)) == 0
       && INTVAL (XEXP (op, 1)) >= 0
-      && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (innermode)
+      && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (innermode)
       && byte == subreg_lowpart_offset (outermode, innermode))
     {
       int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
@@ -5727,6 +5731,7 @@ simplify_subreg (enum machine_mode outermode, rtx op,
 
   if ((GET_CODE (op) == LSHIFTRT
        || GET_CODE (op) == ASHIFTRT)
+      && SCALAR_INT_MODE_P (innermode)
       && MEM_P (XEXP (op, 0))
       && CONST_INT_P (XEXP (op, 1))
       && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (GET_MODE (op))