OSDN Git Service

2007-07-09 Thomas Koenig <tkoenig@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index cb1c4f6..9b27bbd 100644 (file)
@@ -202,14 +202,6 @@ avoid_constant_pool_reference (rtx x)
 
   return x;
 }
-
-/* Return true if X is a MEM referencing the constant pool.  */
-
-bool
-constant_pool_reference_p (rtx x)
-{
-  return avoid_constant_pool_reference (x) != x;
-}
 \f
 /* Make a unary operation by first seeing if it folds and otherwise making
    the specified operation.  */
@@ -708,10 +700,11 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
       /*  (float_truncate (float x)) is (float x)  */
       if (GET_CODE (op) == FLOAT
          && (flag_unsafe_math_optimizations
-             || ((unsigned)significand_size (GET_MODE (op))
-                 >= (GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0)))
-                     - num_sign_bit_copies (XEXP (op, 0),
-                                            GET_MODE (XEXP (op, 0)))))))
+             || (SCALAR_FLOAT_MODE_P (GET_MODE (op))
+                 && ((unsigned)significand_size (GET_MODE (op))
+                     >= (GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0)))
+                         - num_sign_bit_copies (XEXP (op, 0),
+                                                GET_MODE (XEXP (op, 0))))))))
        return simplify_gen_unary (FLOAT, mode,
                                   XEXP (op, 0),
                                   GET_MODE (XEXP (op, 0)));
@@ -744,6 +737,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
           */
       if (GET_CODE (op) == FLOAT_EXTEND
          || (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)))
                      - num_sign_bit_copies (XEXP (op, 0),
@@ -1696,7 +1690,8 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
                                                         XEXP (op0, 1)));
 
       /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)).  */
-      if (GET_CODE (op0) == MULT
+      if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode)
+         && GET_CODE (op0) == MULT
          && GET_CODE (XEXP (op0, 0)) == NEG)
        {
          rtx in1, in2;
@@ -1779,10 +1774,14 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
     case MINUS:
       /* We can't assume x-x is 0 even with non-IEEE floating point,
         but since it is zero except in very strange circumstances, we
-        will treat it as zero with -funsafe-math-optimizations.  */
+        will treat it as zero with -funsafe-math-optimizations and
+        -ffinite-math-only.  */
       if (rtx_equal_p (trueop0, trueop1)
          && ! side_effects_p (op0)
-         && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
+         && (! FLOAT_MODE_P (mode)
+             || (flag_unsafe_math_optimizations
+                 && !HONOR_NANS (mode)
+                 && !HONOR_INFINITIES (mode))))
        return CONST0_RTX (mode);
 
       /* Change subtraction from zero into negation.  (0 - x) is the
@@ -1924,7 +1923,8 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
        return reversed;
 
       /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A).  */
-      if (GET_CODE (op1) == MULT
+      if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode)
+         && GET_CODE (op1) == MULT
          && GET_CODE (XEXP (op1, 0)) == NEG)
        {
          rtx in1, in2;
@@ -1939,7 +1939,8 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
 
       /* Canonicalize (minus (neg A) (mult B C)) to
         (minus (mult (neg B) C) A).  */
-      if (GET_CODE (op1) == MULT
+      if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode)
+         && GET_CODE (op1) == MULT
          && GET_CODE (op0) == NEG)
        {
          rtx in1, in2;
@@ -2072,6 +2073,33 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
          && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0)
        return op1;
  
+      /* Canonicalize (X & C1) | C2.  */
+      if (GET_CODE (op0) == AND
+         && GET_CODE (trueop1) == CONST_INT
+         && GET_CODE (XEXP (op0, 1)) == CONST_INT)
+       {
+         HOST_WIDE_INT mask = GET_MODE_MASK (mode);
+         HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1));
+         HOST_WIDE_INT c2 = INTVAL (trueop1);
+
+         /* If (C1&C2) == C1, then (X&C1)|C2 becomes X.  */
+         if ((c1 & c2) == c1
+             && !side_effects_p (XEXP (op0, 0)))
+           return trueop1;
+
+         /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2.  */
+         if (((c1|c2) & mask) == mask)
+           return simplify_gen_binary (IOR, mode, XEXP (op0, 0), op1);
+
+         /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2.  */
+         if (((c1 & ~c2) & mask) != (c1 & mask))
+           {
+             tem = simplify_gen_binary (AND, mode, XEXP (op0, 0),
+                                        gen_int_mode (c1 & ~c2, mode));
+             return simplify_gen_binary (IOR, mode, tem, op1);
+           }
+       }
+
       /* Convert (A & B) | A to A.  */
       if (GET_CODE (op0) == AND
          && (rtx_equal_p (XEXP (op0, 0), op1)
@@ -2312,6 +2340,18 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
          return simplify_gen_unary (ZERO_EXTEND, mode, tem, imode);
        }
 
+      /* Canonicalize (A | C1) & C2 as (A & C2) | (C1 & C2).  */
+      if (GET_CODE (op0) == IOR
+         && GET_CODE (trueop1) == CONST_INT
+         && GET_CODE (XEXP (op0, 1)) == CONST_INT)
+       {
+         HOST_WIDE_INT tmp = INTVAL (trueop1) & INTVAL (XEXP (op0, 1));
+         return simplify_gen_binary (IOR, mode,
+                                     simplify_gen_binary (AND, mode,
+                                                          XEXP (op0, 0), op1),
+                                     gen_int_mode (tmp, mode));
+       }
+
       /* Convert (A ^ B) & A to A & (~B) since the latter is often a single
         insn (and may simplify more).  */
       if (GET_CODE (op0) == XOR