OSDN Git Service

PR middle-end/18164
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index 4af468a..75bf42a 100644 (file)
@@ -1185,6 +1185,7 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
   trueop1 = avoid_constant_pool_reference (op1);
 
   if (VECTOR_MODE_P (mode)
+      && code != VEC_CONCAT
       && GET_CODE (trueop0) == CONST_VECTOR
       && GET_CODE (trueop1) == CONST_VECTOR)
     {
@@ -3170,7 +3171,7 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
                  != ((HOST_WIDE_INT) (-1) << (width - 1))))
            val &= ((HOST_WIDE_INT) 1 << width) - 1;
 
-         return GEN_INT (val);
+         return gen_int_mode (val, mode);
        }
       break;
 
@@ -3641,12 +3642,14 @@ simplify_subreg (enum machine_mode outermode, rtx op,
        }
 
       /* Recurse for further possible simplifications.  */
-      newx = simplify_subreg (outermode, SUBREG_REG (op),
-                            GET_MODE (SUBREG_REG (op)),
-                            final_offset);
+      newx = simplify_subreg (outermode, SUBREG_REG (op), innermostmode,
+                             final_offset);
       if (newx)
        return newx;
-      return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+      if (validate_subreg (outermode, innermostmode,
+                          SUBREG_REG (op), final_offset))
+        return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+      return NULL_RTX;
     }
 
   /* SUBREG of a hard register => just change the register number
@@ -3674,14 +3677,15 @@ simplify_subreg (enum machine_mode outermode, rtx op,
       && subreg_offset_representable_p (REGNO (op), innermode,
                                        byte, outermode))
     {
-      rtx tem = gen_rtx_SUBREG (outermode, op, byte);
-      int final_regno = subreg_hard_regno (tem, 0);
+      unsigned int regno = REGNO (op);
+      unsigned int final_regno
+       = regno + subreg_regno_offset (regno, innermode, byte, outermode);
 
       /* ??? We do allow it if the current REG is not valid for
         its mode.  This is a kludge to work around how float/complex
         arguments are passed on 32-bit SPARC and should be fixed.  */
       if (HARD_REGNO_MODE_OK (final_regno, outermode)
-         || ! HARD_REGNO_MODE_OK (REGNO (op), innermode))
+         || ! HARD_REGNO_MODE_OK (regno, innermode))
        {
          rtx x = gen_rtx_REG_offset (op, outermode, final_regno, byte);
 
@@ -3723,9 +3727,9 @@ simplify_subreg (enum machine_mode outermode, rtx op,
       res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
       if (res)
        return res;
-      /* We can at least simplify it by referring directly to the
-        relevant part.  */
-      return gen_rtx_SUBREG (outermode, part, final_offset);
+      if (validate_subreg (outermode, GET_MODE (part), part, final_offset))
+        return gen_rtx_SUBREG (outermode, part, final_offset);
+      return NULL_RTX;
     }
 
   /* Optimize SUBREG truncations of zero and sign extended values.  */
@@ -3773,17 +3777,6 @@ simplify_gen_subreg (enum machine_mode outermode, rtx op,
                     enum machine_mode innermode, unsigned int byte)
 {
   rtx newx;
-  /* Little bit of sanity checking.  */
-  gcc_assert (innermode != VOIDmode);
-  gcc_assert (outermode != VOIDmode);
-  gcc_assert (innermode != BLKmode);
-  gcc_assert (outermode != BLKmode);
-
-  gcc_assert (GET_MODE (op) == innermode
-             || GET_MODE (op) == VOIDmode);
-
-  gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0);
-  gcc_assert (byte < GET_MODE_SIZE (innermode));
 
   newx = simplify_subreg (outermode, op, innermode, byte);
   if (newx)
@@ -3792,8 +3785,12 @@ simplify_gen_subreg (enum machine_mode outermode, rtx op,
   if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode)
     return NULL_RTX;
 
-  return gen_rtx_SUBREG (outermode, op, byte);
+  if (validate_subreg (outermode, innermode, op, byte))
+    return gen_rtx_SUBREG (outermode, op, byte);
+
+  return NULL_RTX;
 }
+
 /* Simplify X, an rtx expression.
 
    Return the simplified expression or NULL if no simplifications