expmed.c (store_bit_field): Pun non-integral str_rtx modes.
authorRichard Henderson <rth@cygnus.com>
Fri, 9 Oct 1998 15:50:25 +0000 (08:50 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 9 Oct 1998 15:50:25 +0000 (08:50 -0700)
        * expmed.c (store_bit_field): Pun non-integral str_rtx modes.
        Take extra care for op0 now possibly being a subreg.
        (extract_bit_field): Likewise.
        * function.c (purge_addressof_1): Revert Oct 4 change.  Drop
        the reg to memory if there is no equal sized integral mode.
        * stor-layout.c (int_mode_for_mode): New function.
        * machmode.h: Prototype it.

From-SVN: r22962

gcc/ChangeLog
gcc/expmed.c
gcc/function.c
gcc/machmode.h
gcc/stor-layout.c

index 436cd1d33a27962d5851ad9b7c51c619e061038b..2a0bd6636410ce13084fcc536b5401cf7b75b508 100644 (file)
@@ -1,3 +1,13 @@
+Fri Oct  9 15:49:29 1998  Richard Henderson  <rth@cygnus.com>
+
+       * expmed.c (store_bit_field): Pun non-integral str_rtx modes.
+       Take extra care for op0 now possibly being a subreg.
+       (extract_bit_field): Likewise.
+       * function.c (purge_addressof_1): Revert Oct 4 change.  Drop
+       the reg to memory if there is no equal sized integral mode.
+       * stor-layout.c (int_mode_for_mode): New function.
+       * machmode.h: Prototype it.
+
 Fri Oct  9 14:26:44 1998  Jeffrey A Law  (law@cygnus.com)
 
        * global.c (build_insn_chain): Verify no real insns exist past the
index f9bd9ad20bebddb9491d68e0f7a8b149c7281944..9b285d0e23f680a045c773459756d69ea40ae245 100644 (file)
@@ -261,6 +261,21 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
       op0 = SUBREG_REG (op0);
     }
 
+  /* Make sure we are playing with integral modes.  Pun with subregs
+     if we aren't.  */
+  {
+    enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
+    if (imode != GET_MODE (op0))
+      {
+       if (GET_CODE (op0) == MEM)
+         op0 = change_address (op0, imode, NULL_RTX);
+       else if (imode != BLKmode)
+         op0 = gen_lowpart (imode, op0);
+       else
+         abort ();
+      }
+  }
+
   /* If OP0 is a register, BITPOS must count within a word.
      But as we have it, it counts within whatever size OP0 now has.
      On a bigendian machine, these are not the same, so convert.  */
@@ -287,6 +302,18 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
         can be done with just SUBREG.  */
       if (GET_MODE (op0) != fieldmode)
        {
+         if (GET_CODE (op0) == SUBREG)
+           {
+             if (GET_MODE (SUBREG_REG (op0)) == fieldmode
+                 || GET_MODE_CLASS (fieldmode) == MODE_INT
+                 || GET_MODE_CLASS (fieldmode) == MODE_PARTIAL_INT)
+               op0 = SUBREG_REG (op0);
+             else
+               /* Else we've got some float mode source being extracted into
+                  a different float mode destination -- this combination of
+                  subregs results in Severe Tire Damage.  */
+               abort ();
+           }
          if (GET_CODE (op0) == REG)
            op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
          else
@@ -955,6 +982,21 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
       op0 = SUBREG_REG (op0);
     }
 
+  /* Make sure we are playing with integral modes.  Pun with subregs
+     if we aren't.  */
+  {
+    enum machine_mode imode = int_mode_for_mode (GET_MODE (op0));
+    if (imode != GET_MODE (op0))
+      {
+       if (GET_CODE (op0) == MEM)
+         op0 = change_address (op0, imode, NULL_RTX);
+       else if (imode != BLKmode)
+         op0 = gen_lowpart (imode, op0);
+       else
+         abort ();
+      }
+  }
+
   /* ??? We currently assume TARGET is at least as big as BITSIZE.
      If that's wrong, the solution is to test for it and set TARGET to 0
      if needed.  */
@@ -973,7 +1015,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
      So too extracting a subword value in
      the least significant part of the register.  */
 
-  if (((GET_CODE (op0) == REG
+  if (((GET_CODE (op0) != MEM
        && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
                                  GET_MODE_BITSIZE (GET_MODE (op0))))
        || (GET_CODE (op0) == MEM
@@ -996,6 +1038,18 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
 
       if (mode1 != GET_MODE (op0))
        {
+         if (GET_CODE (op0) == SUBREG)
+           {
+             if (GET_MODE (SUBREG_REG (op0)) == mode1
+                 || GET_MODE_CLASS (mode1) == MODE_INT
+                 || GET_MODE_CLASS (mode1) == MODE_PARTIAL_INT)
+               op0 = SUBREG_REG (op0);
+             else
+               /* Else we've got some float mode source being extracted into
+                  a different float mode destination -- this combination of
+                  subregs results in Severe Tire Damage.  */
+               abort ();
+           }
          if (GET_CODE (op0) == REG)
            op0 = gen_rtx_SUBREG (mode1, op0, offset);
          else
@@ -1088,12 +1142,12 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
   /* OFFSET is the number of words or bytes (UNIT says which)
      from STR_RTX to the first word or byte containing part of the field.  */
 
-  if (GET_CODE (op0) == REG)
+  if (GET_CODE (op0) != MEM)
     {
       if (offset != 0
          || GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
-       op0 = gen_rtx_SUBREG (TYPE_MODE (type_for_size (BITS_PER_WORD, 0)),
-                      op0, offset);
+       op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
+                             op0, offset);
       offset = 0;
     }
   else
index 5e607597f4f6cd8cf91237973a9ca3d1d630ebbf..5ad113cfc9372cf28961bce14e30cb0fd77a5d8b 100644 (file)
@@ -2874,24 +2874,14 @@ purge_addressof_1 (loc, insn, force, store)
 
          /* Don't even consider working with paradoxical subregs,
             or the moral equivalent seen here.  */
-         if (size_x < size_sub)
+         if (size_x < size_sub
+             && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
            {
              /* Do a bitfield insertion to mirror what would happen
                 in memory.  */
 
              rtx val, seq;
 
-             /* We cannot do this if we are trying to pick out
-                an integral piece, smaller than a word, of a
-                floating point value.  */
-             if (INTEGRAL_MODE_P (GET_MODE (x))
-                 && GET_MODE_SIZE (GET_MODE (x)) < UNITS_PER_WORD
-                 && FLOAT_MODE_P (GET_MODE (sub)))
-               {
-                 put_addressof_into_stack (XEXP (x, 0));
-                 return;
-               }
-
              if (store)
                {
                  /* If we can't replace with a register, be afraid.  */
index 119950c4348f6a527bf5f41a715529ac65a71fac..e8c17e01642e34099d58a5f2f309122599abf6cc 100644 (file)
@@ -211,6 +211,11 @@ extern unsigned char mode_wider_mode[];
 
 extern enum machine_mode mode_for_size PROTO((unsigned int, enum mode_class, int));
 
+/* Return an integer mode of the exact same size as the input mode,
+   or BLKmode on failure.  */
+
+extern enum machine_mode int_mode_for_mode PROTO((enum machine_mode));
+
 /* Find the best mode to use to access a bit field.  */
 
 extern enum machine_mode get_best_mode PROTO((int, int, int, enum machine_mode, int));
index 3c7cf23d7d37f3c59301ae34649fe874947a58c8..a6bf053ba76d7cd579616fffae784c7e21559dc2 100644 (file)
@@ -176,6 +176,37 @@ smallest_mode_for_size (size, class)
   abort ();
 }
 
+/* Find an integer mode of the exact same size, or BLKmode on failure.  */
+
+enum machine_mode
+int_mode_for_mode (mode)
+     enum machine_mode mode;
+{
+  switch (GET_MODE_CLASS (mode))
+    {
+    case MODE_INT:
+    case MODE_PARTIAL_INT:
+      break;
+
+    case MODE_COMPLEX_INT:
+    case MODE_COMPLEX_FLOAT:
+    case MODE_FLOAT:
+      mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
+      break;
+
+    case MODE_RANDOM:
+      if (mode == BLKmode)
+        break;
+      /* FALLTHRU */
+
+    case MODE_CC:
+    default:
+      abort();
+    }
+
+  return mode;
+}
+
 /* Return the value of VALUE, rounded up to a multiple of DIVISOR.  */
 
 tree