PR f/6138.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Apr 2002 19:26:19 +0000 (19:26 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Apr 2002 19:26:19 +0000 (19:26 +0000)
* function.c (fixup_memory_subreg): Add promoted_mode parameter.
(walk_fixup_memory_subreg): Likewise.
(fixup_var_refs_insn): Adjust accordingly.
(fixup_var_refs_1): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52631 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/function.c

index a6696c1..ab675e0 100644 (file)
@@ -1,3 +1,11 @@
+2002-04-21  Mark Mitchell  <mark@codesourcery.com>
+
+       PR f/6138.
+       * function.c (fixup_memory_subreg): Add promoted_mode parameter.
+       (walk_fixup_memory_subreg): Likewise.
+       (fixup_var_refs_insn): Adjust accordingly.
+       (fixup_var_refs_1): Likewise.
+
 2002-04-22  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * config/s390/linux.h: (LIBPATH_SPEC, LIBPATH_ARCH31_SPEC,
index e22273d..5904919 100644 (file)
@@ -246,8 +246,9 @@ static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode,
                                         int, int, rtx));
 static void fixup_var_refs_1   PARAMS ((rtx, enum machine_mode, rtx *, rtx,
                                         struct fixup_replacement **, rtx));
-static rtx fixup_memory_subreg PARAMS ((rtx, rtx, int));
-static rtx walk_fixup_memory_subreg  PARAMS ((rtx, rtx, int));
+static rtx fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int));
+static rtx walk_fixup_memory_subreg  PARAMS ((rtx, rtx, enum machine_mode, 
+                                             int));
 static rtx fixup_stack_1       PARAMS ((rtx, rtx));
 static void optimize_bit_field PARAMS ((rtx, rtx, rtx *));
 static void instantiate_decls  PARAMS ((tree, int));
@@ -1859,7 +1860,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
              /* OLD might be a (subreg (mem)).  */
              if (GET_CODE (replacements->old) == SUBREG)
                replacements->old
-                 = fixup_memory_subreg (replacements->old, insn, 0);
+                 = fixup_memory_subreg (replacements->old, insn, 
+                                        promoted_mode, 0);
              else
                replacements->old
                  = fixup_stack_1 (replacements->old, insn);
@@ -1899,7 +1901,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
     {
       if (GET_CODE (note) != INSN_LIST)
        XEXP (note, 0)
-         = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1);
+         = walk_fixup_memory_subreg (XEXP (note, 0), insn,
+                                     promoted_mode, 1);
       note = XEXP (note, 1);
     }
 }
@@ -2070,7 +2073,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
                  return;
                }
              else
-               tem = fixup_memory_subreg (tem, insn, 0);
+               tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
            }
          else
            tem = fixup_stack_1 (tem, insn);
@@ -2185,7 +2188,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
              return;
            }
 
-         replacement->new = *loc = fixup_memory_subreg (x, insn, 0);
+         replacement->new = *loc = fixup_memory_subreg (x, insn, 
+                                                        promoted_mode, 0);
 
          INSN_CODE (insn) = -1;
          if (! flag_force_mem && recog_memoized (insn) >= 0)
@@ -2276,7 +2280,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
               This was legitimate when the MEM was a REG.  */
            if (GET_CODE (tem) == SUBREG
                && SUBREG_REG (tem) == var)
-             tem = fixup_memory_subreg (tem, insn, 0);
+             tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
            else
              tem = fixup_stack_1 (tem, insn);
 
@@ -2378,7 +2382,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
                  SET_SRC (x) = replacement->new;
                else if (GET_CODE (SET_SRC (x)) == SUBREG)
                  SET_SRC (x) = replacement->new
-                   = fixup_memory_subreg (SET_SRC (x), insn, 0);
+                   = fixup_memory_subreg (SET_SRC (x), insn, promoted_mode,
+                                          0);
                else
                  SET_SRC (x) = replacement->new
                    = fixup_stack_1 (SET_SRC (x), insn);
@@ -2431,7 +2436,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
            rtx pat, last;
 
            if (GET_CODE (SET_DEST (x)) == SUBREG)
-             SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0);
+             SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 
+                                                 promoted_mode, 0);
            else
              SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
 
@@ -2476,6 +2482,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
          {
            rtx temp;
            rtx fixeddest = SET_DEST (x);
+           enum machine_mode temp_mode;
 
            /* STRICT_LOW_PART can be discarded, around a MEM.  */
            if (GET_CODE (fixeddest) == STRICT_LOW_PART)
@@ -2483,13 +2490,17 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
            /* Convert (SUBREG (MEM)) to a MEM in a changed mode.  */
            if (GET_CODE (fixeddest) == SUBREG)
              {
-               fixeddest = fixup_memory_subreg (fixeddest, insn, 0);
-               promoted_mode = GET_MODE (fixeddest);
+               fixeddest = fixup_memory_subreg (fixeddest, insn, 
+                                                promoted_mode, 0);
+               temp_mode = GET_MODE (fixeddest);
              }
            else
-             fixeddest = fixup_stack_1 (fixeddest, insn);
+             {
+               fixeddest = fixup_stack_1 (fixeddest, insn);
+               temp_mode = promoted_mode;
+             }
 
-           temp = gen_reg_rtx (promoted_mode);
+           temp = gen_reg_rtx (temp_mode);
 
            emit_insn_after (gen_move_insn (fixeddest,
                                            gen_lowpart (GET_MODE (fixeddest),
@@ -2522,36 +2533,47 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
     }
 }
 \f
-/* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)),
-   return an rtx (MEM:m1 newaddr) which is equivalent.
-   If any insns must be emitted to compute NEWADDR, put them before INSN.
+/* Previously, X had the form (SUBREG:m1 (REG:PROMOTED_MODE ...)).
+   The REG  was placed on the stack, so X now has the form (SUBREG:m1
+   (MEM:m2 ...)). 
+
+   Return an rtx (MEM:m1 newaddr) which is equivalent.  If any insns
+   must be emitted to compute NEWADDR, put them before INSN.
 
    UNCRITICAL nonzero means accept paradoxical subregs.
    This is used for subregs found inside REG_NOTES.  */
 
 static rtx
-fixup_memory_subreg (x, insn, uncritical)
+fixup_memory_subreg (x, insn, promoted_mode, uncritical)
      rtx x;
      rtx insn;
+     enum machine_mode promoted_mode;
      int uncritical;
 {
-  int offset = SUBREG_BYTE (x);
-  rtx addr = XEXP (SUBREG_REG (x), 0);
+  int offset;
+  rtx mem = SUBREG_REG (x);
+  rtx addr = XEXP (mem, 0);
   enum machine_mode mode = GET_MODE (x);
   rtx result;
 
   /* Paradoxical SUBREGs are usually invalid during RTL generation.  */
-  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
-      && ! uncritical)
+  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical)
     abort ();
 
+  offset = SUBREG_BYTE (x);
+  if (BYTES_BIG_ENDIAN)
+    /* If the PROMOTED_MODE is wider than the mode of the MEM, adjust
+       the offset so that it points to the right location within the
+       MEM. */
+    offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem)));
+
   if (!flag_force_addr
       && memory_address_p (mode, plus_constant (addr, offset)))
     /* Shortcut if no insns need be emitted.  */
-    return adjust_address (SUBREG_REG (x), mode, offset);
+    return adjust_address (mem, mode, offset);
 
   start_sequence ();
-  result = adjust_address (SUBREG_REG (x), mode, offset);
+  result = adjust_address (mem, mode, offset);
   emit_insn_before (gen_sequence (), insn);
   end_sequence ();
   return result;
@@ -2562,14 +2584,14 @@ fixup_memory_subreg (x, insn, uncritical)
    If X itself is a (SUBREG (MEM ...) ...), return the replacement expression.
    Otherwise return X, with its contents possibly altered.
 
-   If any insns must be emitted to compute NEWADDR, put them before INSN.
-
-   UNCRITICAL is as in fixup_memory_subreg.  */
+   INSN, PROMOTED_MODE and UNCRITICAL are as for 
+   fixup_memory_subreg.  */
 
 static rtx
-walk_fixup_memory_subreg (x, insn, uncritical)
+walk_fixup_memory_subreg (x, insn, promoted_mode, uncritical)
      rtx x;
      rtx insn;
+     enum machine_mode promoted_mode;
      int uncritical;
 {
   enum rtx_code code;
@@ -2582,7 +2604,7 @@ walk_fixup_memory_subreg (x, insn, uncritical)
   code = GET_CODE (x);
 
   if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
-    return fixup_memory_subreg (x, insn, uncritical);
+    return fixup_memory_subreg (x, insn, promoted_mode, uncritical);
 
   /* Nothing special about this RTX; fix its operands.  */
 
@@ -2590,13 +2612,15 @@ walk_fixup_memory_subreg (x, insn, uncritical)
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-       XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, uncritical);
+       XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, 
+                                               promoted_mode, uncritical);
       else if (fmt[i] == 'E')
        {
          int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            XVECEXP (x, i, j)
-             = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, uncritical);
+             = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, 
+                                         promoted_mode, uncritical);
        }
     }
   return x;