diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 40 | ||||
-rw-r--r-- | gcc/reload.c | 37 | ||||
-rw-r--r-- | gcc/reload.h | 3 | ||||
-rw-r--r-- | gcc/tm.texi | 45 |
5 files changed, 134 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 578b9b7..ac37ecd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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): diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index be3030e..39b5abf 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -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 diff --git a/gcc/reload.c b/gcc/reload.c index e89c251..6548243 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -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; + } +} /* If LOC was scheduled to be replaced by something, return the replacement. Otherwise, return *LOC. */ diff --git a/gcc/reload.h b/gcc/reload.h index d86542f..79f5882 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -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 *)); diff --git a/gcc/tm.texi b/gcc/tm.texi index ad57838..9a8887f 100644 --- a/gcc/tm.texi +++ b/gcc/tm.texi @@ -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 |