OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index d7e9da6..1b99677 100644 (file)
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 #include "config.h"
@@ -145,6 +145,7 @@ avoid_constant_pool_reference (rtx x)
 {
   rtx c, tmp, addr;
   enum machine_mode cmode;
+  HOST_WIDE_INT offset = 0;
 
   switch (GET_CODE (x))
     {
@@ -173,26 +174,48 @@ avoid_constant_pool_reference (rtx x)
   /* Call target hook to avoid the effects of -fpic etc....  */
   addr = targetm.delegitimize_address (addr);
 
+  /* Split the address into a base and integer offset.  */
+  if (GET_CODE (addr) == CONST
+      && GET_CODE (XEXP (addr, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+    {
+      offset = INTVAL (XEXP (XEXP (addr, 0), 1));
+      addr = XEXP (XEXP (addr, 0), 0);
+    }
+
   if (GET_CODE (addr) == LO_SUM)
     addr = XEXP (addr, 1);
 
-  if (GET_CODE (addr) != SYMBOL_REF
-      || ! CONSTANT_POOL_ADDRESS_P (addr))
-    return x;
-
-  c = get_pool_constant (addr);
-  cmode = get_pool_mode (addr);
-
-  /* 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 (cmode != GET_MODE (x))
+  /* If this is a constant pool reference, we can turn it into its
+     constant and hope that simplifications happen.  */
+  if (GET_CODE (addr) == SYMBOL_REF
+      && CONSTANT_POOL_ADDRESS_P (addr))
     {
-      c = simplify_subreg (GET_MODE (x), c, cmode, 0);
-      return c ? c : x;
+      c = get_pool_constant (addr);
+      cmode = get_pool_mode (addr);
+
+      /* 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))
+        {
+          rtx tem = simplify_subreg (GET_MODE (x), c, cmode, offset);
+          if (tem && CONSTANT_P (tem))
+            return tem;
+        }
+      else
+        return c;
     }
 
-  return c;
+  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
@@ -1638,7 +1661,7 @@ simplify_binary_operation_1 (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);
-      if (trueop0 == trueop1
+      if (rtx_equal_p (trueop0, trueop1)
          && ! side_effects_p (op0)
          && GET_MODE_CLASS (mode) != MODE_CC)
         return CONST0_RTX (mode);
@@ -1673,7 +1696,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
          && (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0)
        return op0;
-      if (trueop0 == trueop1 && ! side_effects_p (op0)
+      if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)
          && GET_MODE_CLASS (mode) != MODE_CC)
        return op0;
       /* A & (~A) -> 0 */
@@ -2559,7 +2582,8 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode,
 struct simplify_plus_minus_op_data
 {
   rtx op;
-  int neg;
+  short neg;
+  short ix;
 };
 
 static int
@@ -2567,9 +2591,13 @@ simplify_plus_minus_op_data_cmp (const void *p1, const void *p2)
 {
   const struct simplify_plus_minus_op_data *d1 = p1;
   const struct simplify_plus_minus_op_data *d2 = p2;
+  int result;
 
-  return (commutative_operand_precedence (d2->op)
-         - commutative_operand_precedence (d1->op));
+  result = (commutative_operand_precedence (d2->op)
+           - commutative_operand_precedence (d1->op));
+  if (result)
+    return result;
+  return d1->ix - d2->ix;
 }
 
 static rtx
@@ -2744,7 +2772,12 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
   /* Pack all the operands to the lower-numbered entries.  */
   for (i = 0, j = 0; j < n_ops; j++)
     if (ops[j].op)
-      ops[i++] = ops[j];
+      {
+       ops[i] = ops[j];
+       /* Stabilize sort.  */
+       ops[i].ix = i;
+       i++;
+      }
   n_ops = i;
 
   /* Sort the operations based on swap_commutative_operands_p.  */
@@ -2999,7 +3032,17 @@ simplify_const_relational_operation (enum rtx_code code,
 
   /* If op0 is a compare, extract the comparison arguments from it.  */
   if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
-    op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
+    {
+      op1 = XEXP (op0, 1);
+      op0 = XEXP (op0, 0);
+
+      if (GET_MODE (op0) != VOIDmode)
+       mode = GET_MODE (op0);
+      else if (GET_MODE (op1) != VOIDmode)
+       mode = GET_MODE (op1);
+      else
+       return 0;
+    }
 
   /* We can't simplify MODE_CC values since we don't know what the
      actual comparison is.  */
@@ -3221,7 +3264,9 @@ simplify_const_relational_operation (enum rtx_code code,
 
        case LT:
          /* Optimize abs(x) < 0.0.  */
-         if (trueop1 == CONST0_RTX (mode) && !HONOR_SNANS (mode))
+         if (trueop1 == CONST0_RTX (mode)
+             && !HONOR_SNANS (mode)
+             && !(flag_wrapv && INTEGRAL_MODE_P (mode)))
            {
              tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
                                                       : trueop0;
@@ -3232,7 +3277,9 @@ simplify_const_relational_operation (enum rtx_code code,
 
        case GE:
          /* Optimize abs(x) >= 0.0.  */
-         if (trueop1 == CONST0_RTX (mode) && !HONOR_NANS (mode))
+         if (trueop1 == CONST0_RTX (mode)
+             && !HONOR_NANS (mode)
+             && !(flag_wrapv && INTEGRAL_MODE_P (mode)))
            {
              tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
                                                       : trueop0;
@@ -3576,7 +3623,7 @@ simplify_immed_subreg (enum machine_mode outermode, rtx op,
                }
              /* It shouldn't matter what's done here, so fill it with
                 zero.  */
-             for (; i < max_bitsize; i += value_bit)
+             for (; i < elem_bitsize; i += value_bit)
                *vp++ = 0;
            }
          else