reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS.
authorJoern Rennecke <amylaar@cygnus.co.uk>
Thu, 2 Apr 1998 02:42:26 +0000 (02:42 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 2 Apr 1998 02:42:26 +0000 (18:42 -0800)
* reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS.
(move_replacements): New function.
* reload.h: Prototype it.
* alpha.h (LEGITIMIZE_RELOAD_ADDRESS): New definition.

Co-Authored-By: Richard Henderson <rth@cygnus.com>
From-SVN: r18947

gcc/ChangeLog
gcc/config/alpha/alpha.h
gcc/reload.c
gcc/reload.h
gcc/tm.texi

index 578b9b7ac9bf9f72b94c1c3c435ad94456db113c..ac37ecd95b44777d9be00170f074bf92a7d784ad 100644 (file)
@@ -1,3 +1,12 @@
+Thu Apr  2 02:37:07 1998  Joern Rennecke  (amylaar@cygnus.co.uk)
+                         Richard Henderson  <rth@cygnus.com>
+
+       * reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS.
+       (move_replacements): New function.
+       * reload.h: Prototype it.
+       
+       * alpha.h (LEGITIMIZE_RELOAD_ADDRESS): New definition.
+       
 Thu Apr  2 01:01:34 1998  Richard Henderson  <rth@cygnus.com>
 
        * configure (alpha-*-linuxecoff, alpha-*-linux-gnulibc1):
index be3030ea19930cd1f06aa11ac4eaf5f2dd912a3c..39b5abfb4c0942a7a948d37bd514269bf02cf0d3 100644 (file)
@@ -1467,6 +1467,46 @@ extern void alpha_init_expanders ();
     }                                                          \
 }
 
+/* Try a machine-dependent way of reloading an illegitimate address
+   operand.  If we find one, push the reload and jump to WIN.  This
+   macro is used in only one place: `find_reloads_address' in reload.c.
+
+   For the Alpha, we wish to handle large displacements off a base
+   register by splitting the addend across an ldah and the mem insn.
+   This cuts number of extra insns needed from 3 to 1.  */
+   
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)    \
+do {                                                                   \
+  if (GET_CODE (X) == PLUS                                             \
+      && GET_CODE (XEXP (X, 0)) == REG                                 \
+      && REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER                   \
+      && REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE)                    \
+      && GET_CODE (XEXP (X, 1)) == CONST_INT)                          \
+    {                                                                  \
+      HOST_WIDE_INT val = INTVAL (XEXP (X, 1));                                \
+      HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;          \
+      HOST_WIDE_INT high                                               \
+       = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;       \
+                                                                       \
+      /* Check for 32-bit overflow.  */                                        \
+      if (high + low != val)                                           \
+       break;                                                          \
+                                                                       \
+      /* Reload the high part into a base reg; leave the low part      \
+        in the mem directly.  */                                       \
+                                                                       \
+      X = gen_rtx_PLUS (GET_MODE (X),                                  \
+                       gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0),        \
+                                     GEN_INT (high)),                  \
+                       GEN_INT (low));                                 \
+                                                                       \
+      push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR,      \
+                  BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0,        \
+                  OPNUM, TYPE);                                        \
+      goto WIN;                                                                \
+    }                                                                  \
+} while (0)
+
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.
    On the Alpha this is true only for the unaligned modes.   We can
index e89c2515d9e352b9bcd7b2af55a95212dbcec921..6548243023424d7f757b4d7560b354673f3536ee 100644 (file)
@@ -4422,6 +4422,24 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
        return 0;
     }
 
+#ifdef LEGITIMIZE_RELOAD_ADDRESS
+  do
+    {
+      if (memrefloc)
+       {
+         LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
+                                    ind_levels, win);
+       }
+      break;
+    win:
+      *memrefloc = copy_rtx (*memrefloc);
+      XEXP (*memrefloc, 0) = ad;
+      move_replacements (&ad, &XEXP (*memrefloc, 0));
+      return 1;
+    }
+  while (0);
+#endif
+
   /* The address is not valid.  We have to figure out why.  One possibility
      is that it is itself a MEM.  This can happen when the frame pointer is
      being eliminated, a pseudo is not allocated to a hard register, and the
@@ -5372,6 +5390,25 @@ copy_replacements (x, y)
            }
        }
 }
+
+/* Change any replacements being done to *X to be done to *Y */
+
+void
+move_replacements (x, y)
+     rtx *x;
+     rtx *y;
+{
+  int i;
+
+  for (i = 0; i < n_replacements; i++)
+    if (replacements[i].subreg_loc == x)
+      replacements[i].subreg_loc = y;
+    else if (replacements[i].where == x)
+      {
+       replacements[i].where = y;
+       replacements[i].subreg_loc = 0;
+      }
+}
 \f
 /* If LOC was scheduled to be replaced by something, return the replacement.
    Otherwise, return *LOC.  */
index d86542fa5053c8e270a8f5e11e6dd4da71d65e18..79f5882e98edbfd2d3e07d8dbe395ecc3ecf08d2 100644 (file)
@@ -187,6 +187,9 @@ extern void subst_reloads PROTO((void));
    the RTL.  */
 extern void copy_replacements PROTO((rtx, rtx));
 
+/* Change any replacements being done to *X to be done to *Y */
+extern void move_replacements PROTO((rtx *x, rtx *y));
+
 /* If LOC was scheduled to be replaced by something, return the replacement.
    Otherwise, return *LOC.  */
 extern rtx find_replacement PROTO((rtx *));
index ad578386be67d109d81ac380ea187f099abd0cf4..9a8887fdaf98f84ec32a924f16e2914e260c1ad5 100644 (file)
@@ -4223,6 +4223,51 @@ address.  The compiler has standard ways of doing so in all cases.  In
 fact, it is safe for this macro to do nothing.  But often a
 machine-dependent strategy can generate better code.
 
+@findex LEGITIMIZE_RELOAD_ADDRESS
+@item LEGITIMIZE_RELOAD_ADDRESS (@var{x}, @var{mode}, @var{opnum}, @var{type}, @var{ind_levels}, @var{win})
+A C compound statement that attempts to replace @var{x}, which is an address
+that needs reloading, with a valid memory address for an operand of mode
+@var{mode}.  @var{win} will be a C statement label elsewhere in the code.
+It is not necessary to define this macro, but it might be useful for
+performance reasons. 
+
+For example, on the i386, it is sometimes possible to use a single
+reload register instead of two by reloading a sum of two pseudo
+registers into a register.  On the other hand, for number of RISC
+processors offsets are limited so that often an intermediate address
+needs to be generated in order to address a stack slot.  By defining
+LEGITIMIZE_RELOAD_ADDRESS appropriately, the intermediate addresses
+generated for adjacent some stack slots can be made identical, and thus
+be shared.
+
+@findex strict_memory_address_p
+The macro definition may use @code{strict_memory_address_p} to test if
+the address has become legitimate.
+
+@findex push_reload
+It may use @code{push_reload} to indicate parts that need reloading.
+@var{opnum}, @var{type} and @var{ind_levels} are usually suitable to be
+passed unaltered to push_reload.
+
+The code generated by this macro should not alter the substructure of
+@var{x}.  If it transforms @var{x} into a more legitimate form, it
+should assign @var{x} (which will always be a C variable) a new value.
+This also applies to parts that you change indirectly by calling
+@code{push_reload}.
+
+@findex copy_rtx
+If you want to change only a part of @var{x}, one standard way of doing
+this is to use @code{copy_rtx}.  Note, however, that is unshares only a
+single level of rtl.  Thus, if the part to be changed is not at the
+top level, you'll need to replace first the top leve
+It is not necessary for this macro to come up with a legitimate
+address;  but often a machine-dependent strategy can generate better code.
+
+@emph{Note}: This macro should be used with caution.  It is necessary
+to know something of how reload works in order to effectively use this,
+and it is quite easy to produce macros that build in too much knowledge
+of reload internals.
+
 @findex GO_IF_MODE_DEPENDENT_ADDRESS
 @item GO_IF_MODE_DEPENDENT_ADDRESS (@var{addr}, @var{label})
 A C statement or compound statement with a conditional @code{goto