OSDN Git Service

2012-01-30 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index eb328e5..6733b84 100644 (file)
@@ -1373,8 +1373,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;
@@ -1394,50 +1393,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_PRECISION (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_PRECISION (op_mode) - 1;
+           val = GET_MODE_PRECISION (mode) - 1;
          else if (arg0 >= 0)
-           val = GET_MODE_PRECISION (op_mode) - floor_log2 (arg0) - 2;
+           val = GET_MODE_PRECISION (mode) - floor_log2 (arg0) - 2;
          else if (arg0 < 0)
-           val = GET_MODE_PRECISION (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_PRECISION (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;
@@ -2432,9 +2431,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;
@@ -2574,9 +2571,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)
@@ -2722,6 +2717,8 @@ 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 (INTEGRAL_MODE_P (mode) && trueop1 == CONSTM1_RTX (mode))
+       return op0;
       if (HWI_COMPUTABLE_MODE_P (mode))
        {
          HOST_WIDE_INT nzop0 = nonzero_bits (trueop0, mode);
@@ -2956,7 +2953,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)
@@ -4355,10 +4352,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
@@ -5612,6 +5619,7 @@ 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)
+      && SCALAR_INT_MODE_P (innermode)
       && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode))
     {
       unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte);
@@ -5650,6 +5658,7 @@ 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
@@ -5669,6 +5678,7 @@ 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)
       && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode)
       && CONST_INT_P (XEXP (op, 1))
       && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND
@@ -5683,6 +5693,7 @@ 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)
+      && 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
@@ -5696,7 +5707,7 @@ 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)
+      && 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))
@@ -5718,6 +5729,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))