OSDN Git Service

* fixinc/fixtests.c(stdc_0_in_system_headers_test): Must return "FIX"
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index c4dee23..621bd90 100644 (file)
@@ -113,12 +113,7 @@ simplify_gen_binary (code, mode, op0, op1)
 
   /* Put complex operands first and constants second if commutative.  */
   if (GET_RTX_CLASS (code) == 'c'
-      && ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
-         || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
-             && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
-         || (GET_CODE (op0) == SUBREG
-             && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
-             && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
+      && swap_commutative_operands_p (op0, op1))
     tem = op0, op0 = op1, op1 = tem;
 
   /* If this simplifies, do it.  */
@@ -194,12 +189,7 @@ simplify_gen_relational (code, mode, cmp_mode, op0, op1)
     return tem;
 
   /* Put complex operands first and constants second.  */
-  if ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
-      || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
-         && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
-      || (GET_CODE (op0) == SUBREG
-         && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
-         && GET_RTX_CLASS (GET_CODE (op1)) != 'o'))
+  if (swap_commutative_operands_p (op0, op1))
     tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
 
   return gen_rtx_fmt_ee (code, mode, op0, op1);
@@ -259,13 +249,18 @@ simplify_replace_rtx (x, old, new)
                              simplify_replace_rtx (XEXP (x, 2), old, new));
 
     case 'x':
-      /* The only case we try to handle is a lowpart SUBREG of a single-word
-        CONST_INT.  */
-      if (code == SUBREG && subreg_lowpart_p (x) && old == SUBREG_REG (x)
-         && GET_CODE (new) == CONST_INT
-         && GET_MODE_SIZE (GET_MODE (old)) <= UNITS_PER_WORD)
-       return GEN_INT (INTVAL (new) & GET_MODE_MASK (mode));
-
+      /* The only case we try to handle is a SUBREG.  */
+      if (code == SUBREG)
+       {
+         rtx exp;
+         exp = simplify_gen_subreg (GET_MODE (x),
+                                    simplify_replace_rtx (SUBREG_REG (x),
+                                                          old, new),
+                                    GET_MODE (SUBREG_REG (x)),
+                                    SUBREG_BYTE (x));
+         if (exp)
+          x = exp;
+       }
       return x;
 
     default:
@@ -1822,8 +1817,7 @@ simplify_relational_operation (code, mode, op0, op1)
     return 0;
 
   /* Make sure the constant is second.  */
-  if ((CONSTANT_P (op0) && ! CONSTANT_P (op1))
-      || (GET_CODE (op0) == CONST_INT && GET_CODE (op1) != CONST_INT))
+  if (swap_commutative_operands_p (op0, op1))
     {
       tem = op0, op0 = op1, op1 = tem;
       code = swap_condition (code);
@@ -2207,6 +2201,9 @@ simplify_subreg (outermode, op, innermode, byte)
       || byte >= GET_MODE_SIZE (innermode))
     abort ();
 
+  if (outermode == innermode && !byte)
+    return op;
+
   /* Attempt to simplify constant to non-SUBREG expression.  */
   if (CONSTANT_P (op))
     {
@@ -2331,12 +2328,17 @@ simplify_subreg (outermode, op, innermode, byte)
                               % UNITS_PER_WORD));
        }
 
+      /* Bail out in case resulting subreg would be incorrect.  */
+      if (final_offset % GET_MODE_SIZE (outermode)
+         || final_offset >= GET_MODE_SIZE (innermostmode))
+       return NULL;
       /* Recurse for futher possible simplifications.  */
-      new = simplify_subreg (outermode, op, GET_MODE (op),
+      new = simplify_subreg (outermode, SUBREG_REG (op),
+                            GET_MODE (SUBREG_REG (op)),
                             final_offset);
       if (new)
        return new;
-      return gen_rtx_SUBREG (outermode, op, final_offset);
+      return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
     }
 
   /* SUBREG of a hard register => just change the register number
@@ -2344,7 +2346,7 @@ simplify_subreg (outermode, op, innermode, byte)
      suppress this simplification.  If the hard register is the stack,
      frame, or argument pointer, leave this as a SUBREG.  */
 
-  if (REG_P (op) == REG
+  if (REG_P (op)
       && REGNO (op) < FIRST_PSEUDO_REGISTER
       && REGNO (op) != FRAME_POINTER_REGNUM
 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
@@ -2378,8 +2380,52 @@ simplify_subreg (outermode, op, innermode, byte)
       MEM_COPY_ATTRIBUTES (new, op);
       return new;
     }
+
+  /* Handle complex values represented as CONCAT
+     of real and imaginary part.  */
+  if (GET_CODE (op) == CONCAT)
+    {
+      int is_realpart = byte < GET_MODE_UNIT_SIZE (innermode) / 2;
+      rtx part = is_realpart ? XEXP (op, 0) : XEXP (op, 1);
+      unsigned int final_offset;
+
+      final_offset = byte % (GET_MODE_UNIT_SIZE (innermode) / 2);
+      return simplify_subreg (outermode, part, GET_MODE (part), final_offset);
+    }
+
   return NULL_RTX;
 }
+/* Make a SUBREG operation or equivalent if it folds.  */
+
+rtx
+simplify_gen_subreg (outermode, op, innermode, byte)
+     rtx op;
+     unsigned int byte;
+     enum machine_mode outermode, innermode;
+{
+  rtx new;
+  /* 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 ();
+
+  if (byte % GET_MODE_SIZE (outermode)
+      || byte >= GET_MODE_SIZE (innermode))
+    abort ();
+
+  new = simplify_subreg (outermode, op, innermode, byte);
+  if (new)
+    return new;
+
+  if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode)
+    return NULL_RTX;
+
+  return gen_rtx_SUBREG (outermode, op, byte);
+}
 /* Simplify X, an rtx expression.
 
    Return the simplified expression or NULL if no simplifications
@@ -2449,6 +2495,13 @@ simplify_rtx (x)
                                             ? GET_MODE (XEXP (x, 0))
                                             : GET_MODE (XEXP (x, 1))),
                                            XEXP (x, 0), XEXP (x, 1));
+    case 'x':
+      /* The only case we try to handle is a SUBREG.  */
+      if (code == SUBREG)
+        return simplify_gen_subreg (mode, SUBREG_REG (x),
+                                   GET_MODE (SUBREG_REG (x)),
+                                   SUBREG_BYTE (x));
+      return NULL;
     default:
       return NULL;
     }