combine.c (do_SUBST): Sanity check substitutions of CONST_INTs...
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 20 Feb 2002 23:15:00 +0000 (23:15 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Wed, 20 Feb 2002 23:15:00 +0000 (23:15 +0000)
* combine.c (do_SUBST): Sanity check substitutions of
CONST_INTs, and reject them in SUBREGs and ZERO_EXTENDs.
(subst): Simplify SUBREG or ZERO_EXTEND instead of SUBSTing a
CONST_INT into its operand.
(known_cond): Likewise, for ZERO_EXTEND.
* simplify-rtx.c (simplify_unary_operation): Fix condition to
allow for simplification of wide modes.  Reject CONST_INTs in
ZERO_EXTEND when their actual mode is not given.

From-SVN: r49920

gcc/ChangeLog
gcc/combine.c
gcc/simplify-rtx.c

index 9538ca24128306e685017cb1cd6efed855b5586f..7a64a64af8aafb60d5815fe0e8653237abf5453f 100644 (file)
@@ -1,3 +1,14 @@
+2002-02-20  Alexandre Oliva  <aoliva@redhat.com>
+
+       * combine.c (do_SUBST): Sanity check substitutions of
+       CONST_INTs, and reject them in SUBREGs and ZERO_EXTENDs.
+       (subst): Simplify SUBREG or ZERO_EXTEND instead of SUBSTing a
+       CONST_INT into its operand.
+       (known_cond): Likewise, for ZERO_EXTEND.
+       * simplify-rtx.c (simplify_unary_operation): Fix condition to
+       allow for simplification of wide modes.  Reject CONST_INTs in
+       ZERO_EXTEND when their actual mode is not given.
+
 2002-02-20  Alexandre Oliva  <aoliva@redhat.com>
 
        * c-decl.c (pushdecl): If no global declaration is found for an
index eb825311613682bc2b83978a4bd9963a9343be57..dba799766edfb1ee7f9d96a0835ad91db3da59bc 100644 (file)
@@ -424,6 +424,33 @@ do_SUBST (into, newval)
   if (oldval == newval)
     return;
 
+  /* We'd like to catch as many invalid transformations here as
+     possible.  Unfortunately, there are way too many mode changes
+     that are perfectly valid, so we'd waste too much effort for
+     little gain doing the checks here.  Focus on catching invalid
+     transformations involving integer constants.  */
+  if (GET_MODE_CLASS (GET_MODE (oldval)) == MODE_INT
+      && GET_CODE (newval) == CONST_INT)
+    {
+      /* Sanity check that we're replacing oldval with a CONST_INT
+        that is a valid sign-extension for the original mode.  */
+      if (INTVAL (newval) != trunc_int_for_mode (INTVAL (newval),
+                                                GET_MODE (oldval)))
+       abort ();
+
+      /* Replacing the operand of a SUBREG or a ZERO_EXTEND with a
+        CONST_INT is not valid, because after the replacement, the
+        original mode would be gone.  Unfortunately, we can't tell
+        when do_SUBST is called to replace the operand thereof, so we
+        perform this test on oldval instead, checking whether an
+        invalid replacement took place before we got here.  */
+      if ((GET_CODE (oldval) == SUBREG
+          && GET_CODE (SUBREG_REG (oldval)) == CONST_INT)
+         || (GET_CODE (oldval) == ZERO_EXTEND
+             && GET_CODE (XEXP (oldval, 0)) == CONST_INT))
+       abort ();
+     }
+
   if (undobuf.frees)
     buf = undobuf.frees, undobuf.frees = buf->next;
   else
@@ -3505,7 +3532,24 @@ subst (x, from, to, in_dest, unique_copy)
              if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
                return new;
 
-             SUBST (XEXP (x, i), new);
+             if (GET_CODE (new) == CONST_INT && GET_CODE (x) == SUBREG)
+               {
+                 x = simplify_subreg (GET_MODE (x), new,
+                                      GET_MODE (SUBREG_REG (x)),
+                                      SUBREG_BYTE (x));
+                 if (! x)
+                   abort ();
+               }
+             else if (GET_CODE (new) == CONST_INT
+                      && GET_CODE (x) == ZERO_EXTEND)
+               {
+                 x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
+                                               new, GET_MODE (XEXP (x, 0)));
+                 if (! x)
+                   abort ();
+               }
+             else
+               SUBST (XEXP (x, i), new);
            }
        }
     }
@@ -7449,6 +7493,31 @@ known_cond (x, cond, reg, val)
 
       return x;
     }
+  /* We don't have to handle SIGN_EXTEND here, because even in the
+     case of replacing something with a modeless CONST_INT, a
+     CONST_INT is already (supposed to be) a valid sign extension for
+     its narrower mode, which implies it's already properly
+     sign-extended for the wider mode.  Now, for ZERO_EXTEND, the
+     story is different.  */
+  else if (code == ZERO_EXTEND)
+    {
+      enum machine_mode inner_mode = GET_MODE (XEXP (x, 0));
+      rtx new, r = known_cond (XEXP (x, 0), cond, reg, val);
+
+      if (XEXP (x, 0) != r)
+       {
+         /* We must simplify the zero_extend here, before we lose
+             track of the original inner_mode.  */
+         new = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
+                                         r, inner_mode);
+         if (new)
+           return new;
+         else
+           SUBST (XEXP (x, 0), r);
+       }
+
+      return x;
+    }
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
index 2db3ec0f7be88c7108a0503fd1687b42ad37479d..84b8cb240cebcb38dfe2b92e496d7d010c3200d0 100644 (file)
@@ -528,8 +528,10 @@ simplify_unary_operation (code, mode, op, op_mode)
          break;
 
        case ZERO_EXTEND:
+         /* When zero-extending a CONST_INT, we need to know its
+             original mode.  */
          if (op_mode == VOIDmode)
-           op_mode = mode;
+           abort ();
          if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
            {
              /* If we were really extending the mode,
@@ -587,7 +589,8 @@ simplify_unary_operation (code, mode, op, op_mode)
 
   /* We can do some operations on integer CONST_DOUBLEs.  Also allow
      for a DImode operation on a CONST_INT.  */
-  else if (GET_MODE (trueop) == VOIDmode && width <= HOST_BITS_PER_INT * 2
+  else if (GET_MODE (trueop) == VOIDmode
+          && width <= HOST_BITS_PER_WIDE_INT * 2
           && (GET_CODE (trueop) == CONST_DOUBLE
               || GET_CODE (trueop) == CONST_INT))
     {
@@ -631,8 +634,10 @@ simplify_unary_operation (code, mode, op, op_mode)
          break;
 
        case ZERO_EXTEND:
-         if (op_mode == VOIDmode
-             || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
+         if (op_mode == VOIDmode)
+           abort ();
+
+         if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
            return 0;
 
          hv = 0;