public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Hookize LEGITIMIZE_ADDRESS
@ 2009-04-17  7:03 Paolo Bonzini
  2009-04-17 10:12 ` Joseph S. Myers
  2009-05-03  0:09 ` Ian Lance Taylor
  0 siblings, 2 replies; 5+ messages in thread
From: Paolo Bonzini @ 2009-04-17  7:03 UTC (permalink / raw)
  To: GCC Patches, Michael Meissner

[-- Attachment #1: Type: text/plain, Size: 635 bytes --]

This patch turns LEGITIMIZE_ADDRESS into a hook.  The patch has been
bootstrapped i686-pc-linux-gnu and has no difference in testsuite output
for pa-linux, mips64-elf, alpha-elf, arm-elf, avr-elf, frv-elf,
m32c-elf, spu-elf, sparc-elf, m32r-elf, sh-elf, xtensa-elf, m68hc11-elf,
cris-elf, iq2000-elf, mn10300-elf, m68k-linux, powerpc-eabispe,
score-elf, s390-linux.

The idea is that when the named address branch is branched, this will
avoid creating a new hook for address-space-savvy legitimize_address.

Ok for mainline?  Or Michael, do you prefer me to put this on the
named-address branch, fixing conflicts along the way?

Paolo

[-- Attachment #2: legitimize-address.patch --]
[-- Type: text/plain, Size: 90135 bytes --]

2009-04-16  Paolo Bonzini  <bonzini@gnu.org>

	* doc/tm.texi (LEGITIMIZE_ADDRESS): Revise documentation.
        * gcc/defaults.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/explow.c (memory_address): Use target hook.
        * gcc/targhooks.c (default_legitimize_address): New.
        * gcc/targhooks.h (default_legitimize_address): New.
        * gcc/target.h (legitimize_address): New.
        * gcc/target-def.h (TARGET_LEGITIMIZE_ADDRESS): New.
        (TARGET_INITIALIZER): Include it.
        * gcc/system.h (LEGITIMIZE_ADDRESS): Poison.

        * config/bfin/bfin-protos.h (legitimize_address): Remove.
        * config/bfin/bfin.c (legitimize_address): Remove.
        * config/bfin/bfin.h (LEGITIMIZE_ADDRESS): Remove.
        * config/m68hc11/m68hc11-protos.h (m68hc11_legitimize_address): Remove.
        * config/m68hc11/m68hc11.c (m68hc11_legitimize_address): Remove.
        * config/m68hc11/m68hc11.h (LEGITIMIZE_ADDRESS): Remove.

        * gcc/config/arm/arm.h (LEGITIMIZE_ADDRESS, ARM_LEGITIMIZE_ADDRESS,
        THUMB_LEGITIMIZE_ADDRESS, THUMB2_LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/s390/s390.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/m32c/m32c.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/sparc/sparc.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/m32r/m32r.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/i386/i386.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/sh/sh.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/avr/avr.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/m68hc11/m68hc11.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/iq2000/iq2000.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/mn10300/mn10300.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/m68k/m68k.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/score/score.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/pa/pa.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/mips/mips.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/alpha/alpha.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/frv/frv.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/spu/spu.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/xtensa/xtensa.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/cris/cris.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/rs6000/rs6000.h (LEGITIMIZE_ADDRESS): Delete.
        * gcc/config/picochip/picochip.h (LEGITIMIZE_ADDRESS): Delete.

        * gcc/config/s390/s390-protos.h (legitimize_address): Delete.
        * gcc/config/m32c/m32c-protos.h (m32c_legitimize_address): Delete.
        * gcc/config/sparc/sparc-protos.h (legitimize_address): Delete.
        * gcc/config/i386/i386-protos.h (legitimize_address): Delete.
        * gcc/config/avr/avr-protos.h (legitimize_address): Delete.
        * gcc/config/mn10300/mn10300-protos.h (legitimize_address): Delete.
        * gcc/config/score/score-protos.h (score_legitimize_address): Delete.
        * gcc/config/arm/arm-protos.h (arm_legitimize_address,
        (thumb_legitimize_address): Delete.
        * gcc/config/pa/pa-protos.h (hppa_legitimize_address): Delete.
        * gcc/config/mips/mips-protos.h (mips_legitimize_address): Delete.
        * gcc/config/alpha/alpha-protos.h (alpha_legitimize_address): Delete.
        * gcc/config/frv/frv-protos.h (frv_legitimize_address): Delete.
        * gcc/config/spu/spu-protos.h (spu_legitimize_address): Delete.
        * gcc/config/xtensa/xtensa-protos.h (xtensa_legitimize_address): Delete.
        * gcc/config/rs6000/rs6000-protos.h (rs6000_legitimize_address): Delete.

        * config/arm/arm.c (arm_legitimize_address): Maybe call Thumb version.
        * config/m32c/m32c.c (m32c_legitimize_address): Standardize.
        * config/m32r/m32r.c (m32r_legitimize_address): New.
        * config/m68k/m68k.c (m68k_legitimize_address): New.
        * config/score/score.c (score_legitimize_address): Standardize.
        * config/score/score3.c (score3_legitimize_address): Standardize.
        * config/score/score3.h (score3_legitimize_address): Adjust.
        * config/score/score7.c (score7_legitimize_address): Standardize.
        * config/score/score7.h (score7_legitimize_address): Adjust.
        * config/sh/sh.c (sh_legitimize_address): New.
        * config/iq2000/iq2000.c (iq2000_legitimize_address): New.

        * gcc/config/s390/s390.c (legitimize_address): Rename to...
	(s390_legitimize_address): ... this.
        * gcc/config/sparc/sparc.c (legitimize_address): Rename to...
        (sparc_legitimize_address): ... this.
        * gcc/config/i386/i386.c (legitimize_address): Rename to...
        (ix86_legitimize_address): ... this.
        * gcc/config/avr/avr.c (legitimize_address): Rename to...
        (avr_legitimize_address): ... this.
        * gcc/config/mn10300/mn10300.c (legitimize_address): Rename to...
        (mn10300_legitimize_address): ... this.
        * config/alpha/alpha.c (alpha_legitimize_address): Wrap...
        (alpha_legitimize_address_1): ... the old alpha_legitimize_address.
        (alpha_expand_mov): Adjust call.

        * config/frv/frv.c (frv_legitimize_address): Return x on failure.
        * config/spu/spu.c (spu_legitimize_address): Likewise.
        * config/xtensa/xtensa.c (xtensa_legitimize_address): Likewise.
        * config/rs6000/rs6000.c (rs6000_legitimize_address): Likewise.


Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 144857)
+++ gcc/doc/tm.texi	(working copy)
@@ -5387,32 +5387,26 @@ The typical use of this macro is to hand
 a label_ref or symbol_ref within an UNSPEC@.
 @end defmac
 
-@defmac LEGITIMIZE_ADDRESS (@var{x}, @var{oldx}, @var{mode}, @var{win})
-A C compound statement that attempts to replace @var{x} with a valid
-memory address for an operand of mode @var{mode}.  @var{win} will be a
-C statement label elsewhere in the code; the macro definition may use
-
-@smallexample
-GO_IF_LEGITIMATE_ADDRESS (@var{mode}, @var{x}, @var{win});
-@end smallexample
-
-@noindent
-to avoid further processing if the address has become legitimate.
+@deftypefn {Target Hook} rtx LEGITIMIZE_ADDRESS (rtx @var{x}, rtx @var{oldx}, enum machine_mode @var{mode})
+This hook is given an invalid memory address @var{x} for an
+operand of mode @var{mode} and should try to return a valid memory
+address.
 
 @findex break_out_memory_refs
 @var{x} will always be the result of a call to @code{break_out_memory_refs},
 and @var{oldx} will be the operand that was given to that function to produce
 @var{x}.
 
-The code generated by this macro should not alter the substructure of
+The code of the hook 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.
+should return the new @var{x}.
 
-It is not necessary for this macro to come up with a legitimate
-address.  The compiler has standard ways of doing so in all cases.  In
-fact, it is safe to omit this macro.  But often a
-machine-dependent strategy can generate better code.
-@end defmac
+It is not necessary for this hook to come up with a legitimate address.
+The compiler has standard ways of doing so in all cases.  In fact, it
+is safe to omit this hook or make it return @var{x} if it cannot find
+a valid way to legitimize the address.  But often a machine-dependent
+strategy can generate better code.
+@end deftypefn
 
 @defmac 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
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(revision 144857)
+++ gcc/targhooks.c	(working copy)
@@ -111,6 +111,13 @@ default_return_in_memory (const_tree typ
 }
 
 rtx
+default_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			    enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return x;
+}
+
+rtx
 default_expand_builtin_saveregs (void)
 {
   error ("__builtin_saveregs not supported by this target");
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	(revision 144857)
+++ gcc/targhooks.h	(working copy)
@@ -18,6 +18,7 @@ along with GCC; see the file COPYING3.  
 <http://www.gnu.org/licenses/>.  */
 
 extern void default_external_libcall (rtx);
+extern rtx default_legitimize_address (rtx, rtx, enum machine_mode);
 
 extern int default_unspec_may_trap_p (const_rtx, unsigned);
 
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	(revision 144857)
+++ gcc/defaults.h	(working copy)
@@ -870,10 +870,6 @@ along with GCC; see the file COPYING3.  
 #define SHIFT_COUNT_TRUNCATED 0
 #endif
 
-#ifndef LEGITIMIZE_ADDRESS
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
-#endif
-
 #ifndef LEGITIMATE_PIC_OPERAND_P
 #define LEGITIMATE_PIC_OPERAND_P(X) 1
 #endif
Index: gcc/target.h
===================================================================
--- gcc/target.h	(revision 144857)
+++ gcc/target.h	(working copy)
@@ -599,6 +599,10 @@ struct gcc_target
   /* True if X is considered to be commutative.  */
   bool (* commutative_p) (const_rtx, int);
 
+  /* Given an invalid address X for a given machine mode, try machine-specific
+     ways to make it legitimate.  Return X or an invalid address on failure.  */
+  rtx (* legitimize_address) (rtx, rtx, enum machine_mode);
+
   /* Given an address RTX, undo the effects of LEGITIMIZE_ADDRESS.  */
   rtx (* delegitimize_address) (rtx);
 
Index: gcc/explow.c
===================================================================
--- gcc/explow.c	(revision 144857)
+++ gcc/explow.c	(working copy)
@@ -446,7 +446,13 @@ memory_address (enum machine_mode mode, 
 	 in certain cases.  This is not necessary since the code
 	 below can handle all possible cases, but machine-dependent
 	 transformations can make better code.  */
-      LEGITIMIZE_ADDRESS (x, oldx, mode, done);
+      {
+        rtx orig_x = x;
+        x = targetm.legitimize_address (x, oldx, mode);
+	if (orig_x != x && memory_address_p (mode, x))
+	  goto done;
+	x = orig_x;
+      }
 
       /* PLUS and MULT can appear in special ways
 	 as the result of attempts to make an address usable for indexing.
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h	(revision 144857)
+++ gcc/target-def.h	(working copy)
@@ -484,6 +484,7 @@
 #define TARGET_CANNOT_FORCE_CONST_MEM hook_bool_rtx_false
 #define TARGET_CANNOT_COPY_INSN_P NULL
 #define TARGET_COMMUTATIVE_P hook_bool_const_rtx_commutative_p
+#define TARGET_LEGITIMIZE_ADDRESS default_legitimize_address
 #define TARGET_DELEGITIMIZE_ADDRESS hook_rtx_rtx_identity
 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_false
 #define TARGET_MIN_ANCHOR_OFFSET 0
@@ -863,6 +864,7 @@
   TARGET_CANNOT_FORCE_CONST_MEM,		\
   TARGET_CANNOT_COPY_INSN_P,			\
   TARGET_COMMUTATIVE_P,				\
+  TARGET_LEGITIMIZE_ADDRESS,			\
   TARGET_DELEGITIMIZE_ADDRESS,			\
   TARGET_USE_BLOCKS_FOR_CONSTANT_P,		\
   TARGET_MIN_ANCHOR_OFFSET,			\
Index: gcc/system.h
===================================================================
--- gcc/system.h	(revision 144857)
+++ gcc/system.h	(working copy)
@@ -681,7 +681,7 @@ extern void fancy_abort (const char *, i
 	MUST_PASS_IN_STACK FUNCTION_ARG_PASS_BY_REFERENCE               \
         VECTOR_MODE_SUPPORTED_P TARGET_SUPPORTS_HIDDEN 			\
 	FUNCTION_ARG_PARTIAL_NREGS ASM_OUTPUT_DWARF_DTPREL		\
-	ALLOCATE_INITIAL_VALUE
+	ALLOCATE_INITIAL_VALUE LEGITIMIZE_ADDRESS
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c	(revision 144857)
+++ gcc/config/alpha/alpha.c	(working copy)
@@ -917,8 +917,8 @@ get_tls_get_addr (void)
 /* Try machine-dependent ways of modifying an illegitimate address
    to be legitimate.  If we find one, return the new, valid address.  */
 
-rtx
-alpha_legitimize_address (rtx x, rtx scratch, enum machine_mode mode)
+static rtx
+alpha_legitimize_address_1 (rtx x, rtx scratch, enum machine_mode mode)
 {
   HOST_WIDE_INT addend;
 
@@ -1112,6 +1112,18 @@ alpha_legitimize_address (rtx x, rtx scr
   }
 }
 
+
+/* Try machine-dependent ways of modifying an illegitimate address
+   to be legitimate.  Return X or the new, valid address.  */
+
+static rtx
+alpha_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			  enum machine_mode mode)
+{
+  rtx new_x = alpha_legitimize_address_1 (x, NULL_RTX, mode);
+  return new_x ? new_x : x;
+}
+
 /* Primarily this is required for TLS symbols, but given that our move
    patterns *ought* to be able to handle any symbol at any time, we
    should never be spilling symbolic operands to the constant pool, ever.  */
@@ -2134,7 +2146,7 @@ alpha_expand_mov (enum machine_mode mode
   /* Allow legitimize_address to perform some simplifications.  */
   if (mode == Pmode && symbolic_operand (operands[1], mode))
     {
-      tmp = alpha_legitimize_address (operands[1], operands[0], mode);
+      tmp = alpha_legitimize_address_1 (operands[1], operands[0], mode);
       if (tmp)
 	{
 	  if (tmp == operands[0])
@@ -10726,6 +10738,9 @@ alpha_init_libfuncs (void)
 #undef TARGET_INIT_LIBFUNCS
 #define TARGET_INIT_LIBFUNCS alpha_init_libfuncs
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS alpha_legitimize_address
+
 #if TARGET_ABI_UNICOSMK
 #undef TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START unicosmk_file_start
Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	(revision 144857)
+++ gcc/config/alpha/alpha.h	(working copy)
@@ -1015,20 +1015,6 @@ do {						\
 } while (0)
 #endif
 
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.  */
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)			\
-do {								\
-  rtx new_x = alpha_legitimize_address (X, NULL_RTX, MODE);	\
-  if (new_x)							\
-    {								\
-      X = new_x;						\
-      goto WIN;							\
-    }								\
-} while (0)
-
 /* 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.  */
Index: gcc/config/alpha/alpha-protos.h
===================================================================
--- gcc/config/alpha/alpha-protos.h	(revision 144857)
+++ gcc/config/alpha/alpha-protos.h	(working copy)
@@ -39,7 +39,6 @@ extern rtx alpha_tablejump_best_label (r
 
 extern bool alpha_legitimate_constant_p (rtx);
 extern bool alpha_legitimate_address_p (enum machine_mode, rtx, int);
-extern rtx alpha_legitimize_address (rtx, rtx, enum machine_mode);
 extern rtx alpha_legitimize_reload_address (rtx, enum machine_mode,
 					    int, int, int);
 
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h	(revision 144857)
+++ gcc/config/frv/frv.h	(working copy)
@@ -2120,16 +2120,6 @@ __asm__("\n"								\
    will reload one or both registers only if neither labeling works.  */
 #define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
 
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)		\
-do {							\
-  rtx new_x = frv_legitimize_address (X, OLDX, MODE);	\
-  if (new_x)						\
-    { 							\
-      (X) = new_x; 					\
-      goto WIN; 					\
-    } 							\
-} while (0)
-
 #define FIND_BASE_TERM frv_find_base_term
 
 /* A C statement or compound statement with a conditional `goto LABEL;'
Index: gcc/config/frv/frv-protos.h
===================================================================
--- gcc/config/frv/frv-protos.h	(revision 144857)
+++ gcc/config/frv/frv-protos.h	(working copy)
@@ -49,7 +49,6 @@ extern int frv_initial_elimination_offse
 #ifdef RTX_CODE
 extern int frv_legitimate_address_p		(enum machine_mode, rtx,
 						 int, int, int);
-extern rtx frv_legitimize_address		(rtx, rtx, enum machine_mode);
 extern rtx frv_find_base_term			(rtx);
 
 #ifdef TREE_CODE
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c	(revision 144857)
+++ gcc/config/frv/frv.c	(working copy)
@@ -303,6 +303,7 @@ static int frv_check_constant_argument		
 static rtx frv_legitimize_target		(enum insn_code, rtx);
 static rtx frv_legitimize_argument		(enum insn_code, int, rtx);
 static rtx frv_legitimize_tls_address		(rtx, enum tls_model);
+static rtx frv_legitimize_address		(rtx, rtx, enum machine_mode);
 static rtx frv_expand_set_builtin		(enum insn_code, tree, rtx);
 static rtx frv_expand_unop_builtin		(enum insn_code, tree, rtx);
 static rtx frv_expand_binop_builtin		(enum insn_code, tree, rtx);
@@ -433,6 +434,9 @@ static bool frv_secondary_reload        
 #undef  TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE frv_issue_rate
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS frv_legitimize_address
+
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL frv_function_ok_for_sibcall
 #undef TARGET_CANNOT_FORCE_CONST_MEM
@@ -3628,7 +3632,7 @@ frv_legitimize_address (rtx x,
         return frv_legitimize_tls_address (x, model);
     }
 
-  return NULL_RTX;
+  return x;
 }
 \f
 /* Test whether a local function descriptor is canonical, i.e.,
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c	(revision 144857)
+++ gcc/config/s390/s390.c	(working copy)
@@ -3743,9 +3743,9 @@ emit_symbolic_move (rtx *operands)
    When -fpic is used, special handling is needed for symbolic references.
    See comments by legitimize_pic_address for details.  */
 
-rtx
-legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-		    enum machine_mode mode ATTRIBUTE_UNUSED)
+static rtx
+s390_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   rtx constant_term = const0_rtx;
 
@@ -9912,6 +9912,9 @@ s390_reorg (void)
 #undef TARGET_DELEGITIMIZE_ADDRESS
 #define TARGET_DELEGITIMIZE_ADDRESS s390_delegitimize_address
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS s390_legitimize_address
+
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY s390_return_in_memory
 
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h	(revision 144857)
+++ gcc/config/s390/s390.h	(working copy)
@@ -765,16 +765,6 @@ used in insn definitions or inline assem
 }
 #endif
 
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.  */
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)                          \
-{                                                                       \
-  (X) = legitimize_address (X, OLDX, MODE);                             \
-  if (memory_address_p (MODE, X))                                       \
-    goto WIN;                                                           \
-}
-
 /* 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.  */
Index: gcc/config/s390/s390-protos.h
===================================================================
--- gcc/config/s390/s390-protos.h	(revision 144857)
+++ gcc/config/s390/s390-protos.h	(working copy)
@@ -74,7 +74,6 @@ extern int legitimate_constant_p (rtx);
 extern bool legitimate_reload_constant_p (rtx);
 extern bool legitimate_address_p (enum machine_mode, rtx, int);
 extern rtx legitimize_pic_address (rtx, rtx);
-extern rtx legitimize_address (rtx, rtx, enum machine_mode);
 extern rtx legitimize_reload_address (rtx, enum machine_mode, int, int);
 extern enum reg_class s390_preferred_reload_class (rtx, enum reg_class);
 extern enum reg_class s390_secondary_input_reload_class (enum reg_class,
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c	(revision 144857)
+++ gcc/config/m32c/m32c.c	(working copy)
@@ -1954,33 +1954,33 @@ m32c_reg_ok_for_base_p (rtx x, int stric
    displacement range.  We deal with this by attempting to reload $fb
    itself into an address register; that seems to result in the best
    code.  */
-int
-m32c_legitimize_address (rtx * x ATTRIBUTE_UNUSED,
-			 rtx oldx ATTRIBUTE_UNUSED,
-			 enum machine_mode mode ATTRIBUTE_UNUSED)
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS m32c_legitimize_address
+static rtx
+m32c_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			 enum machine_mode mode)
 {
 #if DEBUG0
   fprintf (stderr, "m32c_legitimize_address for mode %s\n", mode_name[mode]);
-  debug_rtx (*x);
+  debug_rtx (x);
   fprintf (stderr, "\n");
 #endif
 
-  if (GET_CODE (*x) == PLUS
-      && GET_CODE (XEXP (*x, 0)) == REG
-      && REGNO (XEXP (*x, 0)) == FB_REGNO
-      && GET_CODE (XEXP (*x, 1)) == CONST_INT
-      && (INTVAL (XEXP (*x, 1)) < -128
-	  || INTVAL (XEXP (*x, 1)) > (128 - GET_MODE_SIZE (mode))))
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 0)) == REG
+      && REGNO (XEXP (x, 0)) == FB_REGNO
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && (INTVAL (XEXP (x, 1)) < -128
+	  || INTVAL (XEXP (x, 1)) > (128 - GET_MODE_SIZE (mode))))
     {
       /* reload FB to A_REGS */
       rtx temp = gen_reg_rtx (Pmode);
-      *x = copy_rtx (*x);
-      emit_insn (gen_rtx_SET (VOIDmode, temp, XEXP (*x, 0)));
-      XEXP (*x, 0) = temp;
-      return 1;
+      x = copy_rtx (x);
+      emit_insn (gen_rtx_SET (VOIDmode, temp, XEXP (x, 0)));
+      XEXP (x, 0) = temp;
     }
 
-  return 0;
+  return x;
 }
 
 /* Implements LEGITIMIZE_RELOAD_ADDRESS.  See comment above.  */
Index: gcc/config/m32c/m32c.h
===================================================================
--- gcc/config/m32c/m32c.h	(revision 144857)
+++ gcc/config/m32c/m32c.h	(working copy)
@@ -584,10 +584,6 @@ typedef struct m32c_cumulative_args
 
 /* #define FIND_BASE_TERM(X) when we do unspecs for symrefs */
 
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
-	if (m32c_legitimize_address(&(X),OLDX,MODE)) \
-	  goto WIN;
-
 #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
 	if (m32c_legitimize_reload_address(&(X),MODE,OPNUM,TYPE,IND_LEVELS)) \
 	  goto WIN;
Index: gcc/config/m32c/m32c-protos.h
===================================================================
--- gcc/config/m32c/m32c-protos.h	(revision 144857)
+++ gcc/config/m32c/m32c-protos.h	(working copy)
@@ -79,7 +79,6 @@ rtx  m32c_incoming_return_addr_rtx (void
 void m32c_initialize_trampoline (rtx, rtx, rtx);
 int  m32c_legitimate_address_p (MM, rtx, int);
 int  m32c_legitimate_constant_p (rtx);
-int  m32c_legitimize_address (rtx *, rtx, MM);
 int  m32c_legitimize_reload_address (rtx *, MM, int, int, int);
 rtx  m32c_libcall_value (MM);
 int  m32c_limit_reload_class (MM, int);
Index: gcc/config/spu/spu-protos.h
===================================================================
--- gcc/config/spu/spu-protos.h	(revision 144857)
+++ gcc/config/spu/spu-protos.h	(working copy)
@@ -55,7 +55,6 @@ extern int spu_constant_address_p (rtx x
 extern int spu_legitimate_constant_p (rtx x);
 extern int spu_legitimate_address (enum machine_mode mode, rtx x,
 				   int reg_ok_strict);
-extern rtx spu_legitimize_address (rtx x, rtx oldx, enum machine_mode mode);
 extern int spu_initial_elimination_offset (int from, int to);
 extern rtx spu_function_value (const_tree type, const_tree func);
 extern rtx spu_function_arg (int cum, enum machine_mode mode, tree type,
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 144857)
+++ gcc/config/spu/spu.c	(working copy)
@@ -135,6 +135,7 @@ static void spu_init_libfuncs (void);
 static bool spu_return_in_memory (const_tree type, const_tree fntype);
 static void fix_range (const char *);
 static void spu_encode_section_info (tree, rtx, int);
+static rtx spu_legitimize_address (rtx, rtx, enum machine_mode);
 static tree spu_builtin_mul_widen_even (tree);
 static tree spu_builtin_mul_widen_odd (tree);
 static tree spu_builtin_mask_for_load (void);
@@ -216,6 +217,9 @@ tree spu_builtin_types[SPU_BTI_MAX];
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE spu_unwind_word_mode
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS spu_legitimize_address
+
 /* The .8byte directive doesn't seem to work well for a 32 bit
    architecture. */
 #undef TARGET_ASM_UNALIGNED_DI_OP
@@ -3549,7 +3553,7 @@ spu_legitimate_address (enum machine_mod
    register.  */
 rtx
 spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-			enum machine_mode mode)
+			enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   rtx op0, op1;
   /* Make sure both operands are registers.  */
@@ -3572,10 +3576,8 @@ spu_legitimize_address (rtx x, rtx oldx 
       else if (GET_CODE (op1) != REG)
 	op1 = force_reg (Pmode, op1);
       x = gen_rtx_PLUS (Pmode, op0, op1);
-      if (spu_legitimate_address (mode, x, 0))
-	return x;
     }
-  return NULL_RTX;
+  return x;
 }
 
 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h	(revision 144857)
+++ gcc/config/spu/spu.h	(working copy)
@@ -427,15 +427,6 @@ targetm.resolve_overloaded_builtin = spu
 	goto ADDR;						\
     }
 
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
-  {  rtx result = spu_legitimize_address (X, OLDX, MODE);	\
-     if (result != NULL_RTX)					\
-       {							\
-	 (X) = result;						\
-	 goto WIN;						\
-       }							\
-  }
-
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
 
 #define LEGITIMATE_CONSTANT_P(X) spu_legitimate_constant_p(X)
Index: gcc/config/sparc/sparc-protos.h
===================================================================
--- gcc/config/sparc/sparc-protos.h	(revision 144857)
+++ gcc/config/sparc/sparc-protos.h	(working copy)
@@ -72,7 +72,6 @@ extern bool legitimate_pic_operand_p (rt
 extern int legitimate_address_p (enum machine_mode, rtx, int);
 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
 extern rtx legitimize_tls_address (rtx);
-extern rtx legitimize_address (rtx, rtx, enum machine_mode);
 extern void sparc_emit_call_insn (rtx, rtx);
 extern void sparc_defer_case_vector (rtx, rtx, int);
 extern bool sparc_expand_move (enum machine_mode, rtx *);
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(revision 144857)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -412,6 +412,7 @@ static bool sparc_strict_argument_naming
 static void sparc_va_start (tree, rtx);
 static tree sparc_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
 static bool sparc_vector_mode_supported_p (enum machine_mode);
+static rtx sparc_legitimize_address (rtx, rtx, enum machine_mode);
 static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
 				     enum machine_mode, const_tree, bool);
 static int sparc_arg_partial_bytes (CUMULATIVE_ARGS *,
@@ -492,6 +493,9 @@ static bool fpu_option_set = false;
 #undef TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS sparc_init_builtins
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS sparc_legitimize_address
+
 #undef TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN sparc_expand_builtin
 #undef TARGET_FOLD_BUILTIN
@@ -3372,10 +3376,13 @@ legitimize_pic_address (rtx orig, enum m
    OLDX is the address as it was before break_out_memory_refs was called.
    In some cases it is useful to look at this to decide what needs to be done.
 
-   MODE is the mode of the operand pointed to by X.  */
+   MODE is the mode of the operand pointed to by X.
+
+   On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG.  */
 
 rtx
-legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
+sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			  enum machine_mode mode)
 {
   rtx orig_x = x;
 
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	(revision 144857)
+++ gcc/config/sparc/sparc.h	(working copy)
@@ -1923,27 +1923,6 @@ do {									\
     }							\
 }
 \f
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.  */
-
-/* On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG.  */
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)	\
-{						\
-  (X) = legitimize_address (X, OLDX, MODE);	\
-  if (memory_address_p (MODE, X))		\
-    goto WIN;					\
-}
-
 /* 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.
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c	(revision 144857)
+++ gcc/config/m32r/m32r.c	(working copy)
@@ -70,6 +70,7 @@ static void  init_reg_tables (void);
 static void  block_move_call (rtx, rtx, rtx);
 static int   m32r_is_insn (rtx);
 const struct attribute_spec m32r_attribute_table[];
+static rtx   m32r_legitimize_address (rtx, rtx, enum machine_mode);
 static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
 static void  m32r_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void  m32r_output_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -95,6 +96,9 @@ static int m32r_arg_partial_bytes (CUMUL
 #undef  TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS m32r_legitimize_address
+
 #undef  TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
 #undef  TARGET_ASM_ALIGNED_SI_OP
@@ -1728,6 +1732,16 @@ m32r_legitimize_pic_address (rtx orig, r
 
   return orig;
 }
+
+static rtx
+m32r_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
+			 enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  if (flag_pic)
+    return m32r_legitimize_pic_address (x, NULL_RTX);
+  else
+    return x;
+}
 \f
 /* Nested function support.  */
 
Index: gcc/config/m32r/m32r.h
===================================================================
--- gcc/config/m32r/m32r.h	(revision 144857)
+++ gcc/config/m32r/m32r.h	(working copy)
@@ -1169,29 +1169,6 @@ L2:     .word STATIC
     }								\
   while (0)
 
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.  */
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)			 \
-  do								 \
-    {								 \
-      if (flag_pic)						 \
-	(X) = m32r_legitimize_pic_address (X, NULL_RTX);	 \
-      if (memory_address_p (MODE, X))				 \
-	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.  */
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)		\
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	(revision 144857)
+++ gcc/config/i386/i386.h	(working copy)
@@ -1824,34 +1824,6 @@ do {									\
 
 #define FIND_BASE_TERM(X) ix86_find_base_term (X)
 
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.
-
-   For the 80386, we handle X+REG by loading X into a register R and
-   using R+REG.  R will go in a general reg and indexing will be used.
-   However, if REG is a broken-out memory address or multiplication,
-   nothing needs to be done because REG can certainly go in a general reg.
-
-   When -fpic is used, special handling is needed for symbolic references.
-   See comments by legitimize_pic_address in i386.c for details.  */
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)				\
-do {									\
-  (X) = legitimize_address ((X), (OLDX), (MODE));			\
-  if (memory_address_p ((MODE), (X)))					\
-    goto WIN;								\
-} while (0)
-
 /* Nonzero if the constant value X is a legitimate general operand
    when generating PIC code.  It is given that flag_pic is on and
    that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h	(revision 144857)
+++ gcc/config/i386/i386-protos.h	(working copy)
@@ -57,7 +57,6 @@ extern bool constant_address_p (rtx);
 extern bool legitimate_pic_operand_p (rtx);
 extern int legitimate_pic_address_disp_p (rtx);
 extern int legitimate_address_p (enum machine_mode, rtx, int);
-extern rtx legitimize_address (rtx, rtx, enum machine_mode);
 
 extern void print_reg (rtx, int, FILE*);
 extern void print_operand (FILE*, rtx, int);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 144857)
+++ gcc/config/i386/i386.c	(working copy)
@@ -9620,7 +9620,7 @@ get_thread_pointer (int to_reg)
   return reg;
 }
 
-/* A subroutine of legitimize_address and ix86_expand_move.  FOR_MOV is
+/* A subroutine of ix86_legitimize_address and ix86_expand_move.  FOR_MOV is
    false if we expect this to be used for a memory address and true if
    we expect to load the address into a register.  */
 
@@ -9878,8 +9878,9 @@ legitimize_dllimport_symbol (rtx symbol,
    When -fpic is used, special handling is needed for symbolic references.
    See comments by legitimize_pic_address in i386.c for details.  */
 
-rtx
-legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
+static rtx
+ix86_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			 enum machine_mode mode)
 {
   int changed = 0;
   unsigned log;
@@ -29567,6 +29568,9 @@ ix86_enum_va_list (int idx, const char *
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS ix86_legitimize_address
+
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE ix86_attribute_table
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c	(revision 144857)
+++ gcc/config/sh/sh.c	(working copy)
@@ -245,6 +245,7 @@ static bool sh_rtx_costs (rtx, int, int,
 static int sh_address_cost (rtx, bool);
 static int sh_pr_n_sets (void);
 static rtx sh_allocate_initial_value (rtx);
+static rtx sh_legitimize_address (rtx, rtx, enum machine_mode);
 static int shmedia_target_regs_stack_space (HARD_REG_SET *);
 static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *);
 static int shmedia_target_regs_stack_adjust (HARD_REG_SET *);
@@ -374,6 +375,9 @@ static int sh2a_function_vector_p (tree)
 #undef TARGET_SCHED_INIT
 #define TARGET_SCHED_INIT sh_md_init
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS sh_legitimize_address
+
 #undef TARGET_CANNOT_MODIFY_JUMPS_P
 #define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p
 #undef TARGET_BRANCH_TARGET_REGISTER_CLASS
@@ -8866,6 +8870,60 @@ legitimize_pic_address (rtx orig, enum m
   return orig;
 }
 
+/* Try machine-dependent ways of modifying an illegitimate address
+   to be legitimate.  If we find one, return the new, valid address.
+   Otherwise, return X.
+
+   For the SH, if X is almost suitable for indexing, but the offset is
+   out of range, convert it into a normal form so that CSE has a chance
+   of reducing the number of address registers used.  */
+
+static rtx
+sh_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
+{
+  if (flag_pic)
+    x = legitimize_pic_address (oldx, mode, NULL_RTX);
+
+  if (GET_CODE (x) == PLUS
+      && (GET_MODE_SIZE (mode) == 4
+	  || GET_MODE_SIZE (mode) == 8)
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && BASE_REGISTER_RTX_P (XEXP (x, 0))
+      && ! TARGET_SHMEDIA
+      && ! ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && mode == DFmode)
+      && ! (TARGET_SH2E && mode == SFmode))
+    {
+      rtx index_rtx = XEXP (x, 1);
+      HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;
+      rtx sum;
+
+      /* On rare occasions, we might get an unaligned pointer
+	 that is indexed in a way to give an aligned address.
+	 Therefore, keep the lower two bits in offset_base.  */
+      /* Instead of offset_base 128..131 use 124..127, so that
+	 simple add suffices.  */
+      if (offset > 127)
+	offset_base = ((offset + 4) & ~60) - 4;
+      else
+	offset_base = offset & ~60;
+
+      /* Sometimes the normal form does not suit DImode.  We
+	 could avoid that by using smaller ranges, but that
+	 would give less optimized code when SImode is
+	 prevalent.  */
+      if (GET_MODE_SIZE (mode) + offset - offset_base <= 64)
+	{
+	  sum = expand_binop (Pmode, add_optab, XEXP (x, 0),
+			      GEN_INT (offset_base), NULL_RTX, 0,
+			      OPTAB_LIB_WIDEN);
+
+	  return gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));
+	}
+    }
+
+  return x;
+}
+
 /* Mark the use of a constant in the literal table. If the constant
    has multiple labels, make it unique.  */
 static rtx
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	(revision 144857)
+++ gcc/config/sh/sh.h	(working copy)
@@ -2450,68 +2450,6 @@ struct sh_args {
     }									\
 }
 \f
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.
-
-   For the SH, if X is almost suitable for indexing, but the offset is
-   out of range, convert it into a normal form so that cse has a chance
-   of reducing the number of address registers used.  */
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)			\
-{								\
-  if (flag_pic)							\
-    (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX);	\
-  if (GET_CODE (X) == PLUS					\
-      && (GET_MODE_SIZE (MODE) == 4				\
-	  || GET_MODE_SIZE (MODE) == 8)				\
-      && GET_CODE (XEXP ((X), 1)) == CONST_INT			\
-      && BASE_REGISTER_RTX_P (XEXP ((X), 0))			\
-      && ! TARGET_SHMEDIA					\
-      && ! ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode)			\
-      && ! (TARGET_SH2E && (MODE) == SFmode))			\
-    {								\
-      rtx index_rtx = XEXP ((X), 1);				\
-      HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;	\
-      rtx sum;							\
-								\
-      GO_IF_LEGITIMATE_INDEX ((MODE), index_rtx, WIN);		\
-      /* On rare occasions, we might get an unaligned pointer	\
-	 that is indexed in a way to give an aligned address.	\
-	 Therefore, keep the lower two bits in offset_base.  */ \
-      /* Instead of offset_base 128..131 use 124..127, so that	\
-	 simple add suffices.  */				\
-      if (offset > 127)						\
-	{							\
-	  offset_base = ((offset + 4) & ~60) - 4;		\
-	}							\
-      else							\
-	offset_base = offset & ~60;				\
-      /* Sometimes the normal form does not suit DImode.  We	\
-	 could avoid that by using smaller ranges, but that	\
-	 would give less optimized code when SImode is		\
-	 prevalent.  */						\
-      if (GET_MODE_SIZE (MODE) + offset - offset_base <= 64)	\
-	{							\
-	  sum = expand_binop (Pmode, add_optab, XEXP ((X), 0),	\
-			      GEN_INT (offset_base), NULL_RTX, 0, \
-			      OPTAB_LIB_WIDEN);			\
-                                                                \
-	  (X) = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base)); \
-	  goto WIN;						\
-	}							\
-    }								\
-}
-
 /* A C compound statement that attempts to replace X, which is an address
    that needs reloading, with a valid memory address for an operand of
    mode MODE.  WIN is a C statement label elsewhere in the code.
Index: gcc/config/avr/avr-protos.h
===================================================================
--- gcc/config/avr/avr-protos.h	(revision 144857)
+++ gcc/config/avr/avr-protos.h	(working copy)
@@ -96,7 +96,6 @@ extern const char *avr_out_sbxx_branch (
 
 extern enum reg_class preferred_reload_class (rtx x, enum reg_class rclass);
 extern int extra_constraint_Q (rtx x);
-extern rtx legitimize_address (rtx x, rtx oldx, enum machine_mode mode);
 extern int adjust_insn_length (rtx insn, int len);
 extern rtx avr_libcall_value (enum machine_mode mode);
 extern const char *output_reload_inhi (rtx insn, rtx *operands, int *len);
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	(revision 144857)
+++ gcc/config/avr/avr.c	(working copy)
@@ -62,6 +62,7 @@ static const char *cond_string (enum rtx
 static int avr_num_arg_regs (enum machine_mode, tree);
 
 static RTX_CODE compare_condition (rtx insn);
+static rtx avr_legitimize_address (rtx, rtx, enum machine_mode);
 static int compare_sign_p (rtx insn);
 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
@@ -346,6 +347,9 @@ int avr_case_values_threshold = 30000;
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address
+
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
 
@@ -1152,7 +1156,7 @@ legitimate_address_p (enum machine_mode 
    memory address for an operand of mode MODE  */
 
 rtx
-legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
+avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
 {
   x = oldx;
   if (TARGET_ALL_DEBUG)
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	(revision 144857)
+++ gcc/config/avr/avr.h	(working copy)
@@ -440,13 +440,6 @@ extern int avr_reg_order[];
 
 #define REG_OK_FOR_INDEX_P(X) 0
 
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)				\
-{									\
-  (X) = legitimize_address (X, OLDX, MODE);				\
-  if (memory_address_p (MODE, X))					\
-    goto WIN;								\
-}
-
 #define XEXP_(X,Y) (X)
 
 /* LEGITIMIZE_RELOAD_ADDRESS will allow register R26/27 to be used, where it
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c	(revision 144857)
+++ gcc/config/xtensa/xtensa.c	(working copy)
@@ -132,6 +132,7 @@ static rtx gen_conditional_move (rtx);
 static rtx fixup_subreg_mem (rtx);
 static struct machine_function * xtensa_init_machine_status (void);
 static rtx xtensa_legitimize_tls_address (rtx);
+static rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode);
 static bool xtensa_return_in_msb (const_tree);
 static void printx (FILE *, signed int);
 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -175,6 +176,9 @@ static const int reg_nonleaf_alloc_order
 #undef TARGET_DEFAULT_TARGET_FLAGS
 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD)
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS xtensa_legitimize_address
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS xtensa_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -1873,7 +1877,7 @@ xtensa_legitimize_address (rtx x,
 	}
     }
 
-  return NULL_RTX;
+  return x;
 }
 
 
Index: gcc/config/xtensa/xtensa.h
===================================================================
--- gcc/config/xtensa/xtensa.h	(revision 144857)
+++ gcc/config/xtensa/xtensa.h	(working copy)
@@ -810,17 +810,6 @@ typedef struct xtensa_args
    && GET_CODE (X) != LABEL_REF						\
    && GET_CODE (X) != CONST)
 
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)				\
-  do {									\
-    rtx new_x = xtensa_legitimize_address (X, OLDX, MODE);		\
-    if (new_x)								\
-      {									\
-	X = new_x;							\
-	goto WIN;							\
-      }									\
-  } while (0)
-
-
 /* Treat constant-pool references as "mode dependent" since they can
    only be accessed with SImode loads.  This works around a bug in the
    combiner where a constant pool reference is temporarily converted
Index: gcc/config/xtensa/xtensa-protos.h
===================================================================
--- gcc/config/xtensa/xtensa-protos.h	(revision 144857)
+++ gcc/config/xtensa/xtensa-protos.h	(working copy)
@@ -55,7 +55,6 @@ extern char *xtensa_emit_bit_branch (boo
 extern char *xtensa_emit_movcc (bool, bool, bool, rtx *);
 extern char *xtensa_emit_call (int, rtx *);
 extern bool xtensa_legitimate_address_p (enum machine_mode, rtx, bool);
-extern rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode);
 extern bool xtensa_tls_referenced_p (rtx);
 
 #ifdef TREE_CODE
Index: gcc/config/m68hc11/m68hc11-protos.h
===================================================================
--- gcc/config/m68hc11/m68hc11-protos.h	(revision 144857)
+++ gcc/config/m68hc11/m68hc11-protos.h	(working copy)
@@ -50,8 +50,6 @@ extern enum reg_class preferred_reload_c
 
 extern int m68hc11_go_if_legitimate_address (rtx, enum machine_mode, int);
 
-extern int m68hc11_legitimize_address (rtx*, rtx, enum machine_mode);
-
 extern void m68hc11_notice_update_cc (rtx, rtx);
 extern void m68hc11_notice_keep_cc (rtx);
 
Index: gcc/config/m68hc11/m68hc11.c
===================================================================
--- gcc/config/m68hc11/m68hc11.c	(revision 144857)
+++ gcc/config/m68hc11/m68hc11.c	(working copy)
@@ -789,14 +789,6 @@ m68hc11_go_if_legitimate_address (rtx op
   return result;
 }
 
-int
-m68hc11_legitimize_address (rtx *operand ATTRIBUTE_UNUSED,
-                            rtx old_operand ATTRIBUTE_UNUSED,
-                            enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return 0;
-}
-
 
 int
 m68hc11_reload_operands (rtx operands[])
Index: gcc/config/m68hc11/m68hc11.h
===================================================================
--- gcc/config/m68hc11/m68hc11.h	(revision 144857)
+++ gcc/config/m68hc11/m68hc11.h	(working copy)
@@ -1211,28 +1211,6 @@ extern unsigned char m68hc11_reg_valid_f
 #endif
 
 
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-  
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-  
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-  
-   It is always safe for this macro to do nothing.
-   It exists to recognize opportunities to optimize the output.  */
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)                     \
-{ rtx operand = (X);                                            \
-  if (m68hc11_legitimize_address (&operand, (OLDX), (MODE)))	\
-    {                                                           \
-      (X) = operand;                                            \
-      GO_IF_LEGITIMATE_ADDRESS (MODE,X,WIN);                    \
-    }                                                           \
-}
-
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.  */
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
Index: gcc/config/cris/cris.h
===================================================================
--- gcc/config/cris/cris.h	(revision 144857)
+++ gcc/config/cris/cris.h	(working copy)
@@ -1188,16 +1188,6 @@ struct cum_args {int regs;};
 # define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
 #endif
 
-/* For now, don't do anything.  GCC does a good job most often.
-
-    Maybe we could do something about gcc:s misbehavior when it
-   recalculates frame offsets for local variables, from fp+offs to
-   sp+offs.  The resulting address expression gets screwed up
-   sometimes, but I'm not sure that it may be fixed here, since it is
-   already split up in several instructions (Is this still true?).
-   FIXME: Check and adjust for gcc-2.9x.  */
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) {}
-
 /* Fix reloads known to cause suboptimal spilling.  */
 #define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, INDL, WIN)	\
   do									\
Index: gcc/config/iq2000/iq2000.h
===================================================================
--- gcc/config/iq2000/iq2000.h	(revision 144857)
+++ gcc/config/iq2000/iq2000.h	(working copy)
@@ -546,72 +546,6 @@ typedef struct iq2000_args
 
 #define REG_OK_FOR_INDEX_P(X) 0
 
-
-/* For the IQ2000, transform:
-
-	memory(X + <large int>)
-   into:
-	Y = <large int> & ~0x7fff;
-	Z = X + Y
-	memory (Z + (<large int> & 0x7fff));
-*/
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)				\
-{									\
-  rtx xinsn = (X);							\
-									\
-  if (TARGET_DEBUG_B_MODE)						\
-    {									\
-      GO_PRINTF ("\n========== LEGITIMIZE_ADDRESS\n");			\
-      GO_DEBUG_RTX (xinsn);						\
-    }									\
-									\
-  if (iq2000_check_split (X, MODE))		\
-    {									\
-      X = gen_rtx_LO_SUM (Pmode,					\
-			  copy_to_mode_reg (Pmode,			\
-					    gen_rtx_HIGH (Pmode, X)),	\
-			  X);						\
-      goto WIN;								\
-    }									\
-									\
-  if (GET_CODE (xinsn) == PLUS)						\
-    {									\
-      rtx xplus0 = XEXP (xinsn, 0);					\
-      rtx xplus1 = XEXP (xinsn, 1);					\
-      enum rtx_code code0 = GET_CODE (xplus0);				\
-      enum rtx_code code1 = GET_CODE (xplus1);				\
-									\
-      if (code0 != REG && code1 == REG)					\
-	{								\
-	  xplus0 = XEXP (xinsn, 1);					\
-	  xplus1 = XEXP (xinsn, 0);					\
-	  code0 = GET_CODE (xplus0);					\
-	  code1 = GET_CODE (xplus1);					\
-	}								\
-									\
-      if (code0 == REG && REG_MODE_OK_FOR_BASE_P (xplus0, MODE)		\
-	  && code1 == CONST_INT && !SMALL_INT (xplus1))			\
-	{								\
-	  rtx int_reg = gen_reg_rtx (Pmode);				\
-	  rtx ptr_reg = gen_reg_rtx (Pmode);				\
-									\
-	  emit_move_insn (int_reg,					\
-			  GEN_INT (INTVAL (xplus1) & ~ 0x7fff));	\
-									\
-	  emit_insn (gen_rtx_SET (VOIDmode,				\
-				  ptr_reg,				\
-				  gen_rtx_PLUS (Pmode, xplus0, int_reg))); \
-									\
-	  X = plus_constant (ptr_reg, INTVAL (xplus1) & 0x7fff);	\
-	  goto WIN;							\
-	}								\
-    }									\
-									\
-  if (TARGET_DEBUG_B_MODE)						\
-    GO_PRINTF ("LEGITIMIZE_ADDRESS could not fix.\n");			\
-}
-
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
 
 #define LEGITIMATE_CONSTANT_P(X) (1)
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c	(revision 144857)
+++ gcc/config/iq2000/iq2000.c	(working copy)
@@ -165,6 +165,7 @@ static void iq2000_setup_incoming_vararg
 static bool iq2000_rtx_costs          (rtx, int, int, int *, bool);
 static int  iq2000_address_cost       (rtx, bool);
 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
+static rtx  iq2000_legitimize_address (rtx, rtx, enum machine_mode);
 static bool iq2000_pass_by_reference  (CUMULATIVE_ARGS *, enum machine_mode,
 				       const_tree, bool);
 static int  iq2000_arg_partial_bytes  (CUMULATIVE_ARGS *, enum machine_mode,
@@ -186,6 +187,9 @@ static void iq2000_va_start	      (tree,
 #undef  TARGET_ASM_SELECT_SECTION
 #define TARGET_ASM_SELECT_SECTION	iq2000_select_section
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS	iq2000_legitimize_address
+
 /* The assembler supports switchable .bss sections, but
    iq2000_select_section doesn't yet make use of them.  */
 #undef  TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
@@ -3203,6 +3207,73 @@ print_operand (FILE *file, rtx op, int l
     output_addr_const (file, op);
 }
 
+
+/* For the IQ2000, transform:
+
+        memory(X + <large int>)
+   into:
+        Y = <large int> & ~0x7fff;
+        Z = X + Y
+        memory (Z + (<large int> & 0x7fff));
+*/
+
+rtx
+iq2000_legitimize_address (rtx xinsn, rtx old_x ATTRIBUTE_UNUSED,
+			   enum machine_mode mode)
+{
+  if (TARGET_DEBUG_B_MODE)
+    {
+      GO_PRINTF ("\n========== LEGITIMIZE_ADDRESS\n");
+      GO_DEBUG_RTX (xinsn);
+    }
+
+  if (iq2000_check_split (xinsn, mode))
+    {
+      return gen_rtx_LO_SUM (Pmode,
+                             copy_to_mode_reg (Pmode,
+                                               gen_rtx_HIGH (Pmode, xinsn)),
+                             xinsn);
+    }
+
+  if (GET_CODE (xinsn) == PLUS)
+    {
+      rtx xplus0 = XEXP (xinsn, 0);
+      rtx xplus1 = XEXP (xinsn, 1);
+      enum rtx_code code0 = GET_CODE (xplus0);
+      enum rtx_code code1 = GET_CODE (xplus1);
+
+      if (code0 != REG && code1 == REG)
+        {
+          xplus0 = XEXP (xinsn, 1);
+          xplus1 = XEXP (xinsn, 0);
+          code0 = GET_CODE (xplus0);
+          code1 = GET_CODE (xplus1);
+        }
+
+      if (code0 == REG && REG_MODE_OK_FOR_BASE_P (xplus0, mode)
+          && code1 == CONST_INT && !SMALL_INT (xplus1))
+        {
+          rtx int_reg = gen_reg_rtx (Pmode);
+          rtx ptr_reg = gen_reg_rtx (Pmode);
+
+          emit_move_insn (int_reg,
+                          GEN_INT (INTVAL (xplus1) & ~ 0x7fff));
+
+          emit_insn (gen_rtx_SET (VOIDmode,
+                                  ptr_reg,
+                                  gen_rtx_PLUS (Pmode, xplus0, int_reg)));
+
+          return plus_constant (ptr_reg, INTVAL (xplus1) & 0x7fff);
+        }
+    }
+
+  if (TARGET_DEBUG_B_MODE)
+    GO_PRINTF ("LEGITIMIZE_ADDRESS could not fix.\n");
+
+  return xinsn;
+}
+
+
 static bool
 iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total,
 		  bool speed ATTRIBUTE_UNUSED)
Index: gcc/config/mn10300/mn10300.c
===================================================================
--- gcc/config/mn10300/mn10300.c	(revision 144857)
+++ gcc/config/mn10300/mn10300.c	(working copy)
@@ -76,6 +76,7 @@ static void mn10300_file_start (void);
 static bool mn10300_return_in_memory (const_tree, const_tree);
 static rtx mn10300_builtin_saveregs (void);
 static void mn10300_va_start (tree, rtx);
+static rtx mn10300_legitimize_address (rtx, rtx, enum machine_mode);
 static bool mn10300_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
 				       const_tree, bool);
 static int mn10300_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
@@ -85,6 +86,9 @@ static int mn10300_arg_partial_bytes (CU
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS mn10300_legitimize_address
+
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS mn10300_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -1791,8 +1795,8 @@ symbolic_operand (register rtx op, enum 
    But on a few ports with segmented architectures and indexed addressing
    (mn10300, hppa) it is used to rewrite certain problematical addresses.  */
 rtx
-legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-		    enum machine_mode mode ATTRIBUTE_UNUSED)
+mn10300_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			    enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (flag_pic && ! legitimate_pic_operand_p (x))
     x = legitimize_pic_address (oldx, NULL_RTX);
Index: gcc/config/mn10300/mn10300.h
===================================================================
--- gcc/config/mn10300/mn10300.h	(revision 144857)
+++ gcc/config/mn10300/mn10300.h	(working copy)
@@ -694,24 +694,6 @@ do							\
 while (0)
 
 \f
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.  */
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)  \
-{ rtx orig_x = (X);				\
-  (X) = legitimize_address (X, OLDX, MODE);	\
-  if ((X) != orig_x && memory_address_p (MODE, X)) \
-    goto WIN; }
 
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.  */
Index: gcc/config/mn10300/mn10300-protos.h
===================================================================
--- gcc/config/mn10300/mn10300-protos.h	(revision 144857)
+++ gcc/config/mn10300/mn10300-protos.h	(working copy)
@@ -21,7 +21,6 @@ along with GCC; see the file COPYING3.  
 #ifdef RTX_CODE
 
 extern void mn10300_override_options (void);
-extern struct rtx_def *legitimize_address (rtx, rtx, enum machine_mode);
 extern rtx legitimize_pic_address (rtx, rtx);
 extern int legitimate_pic_operand_p (rtx);
 extern bool legitimate_address_p (enum machine_mode, rtx, int);
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	(revision 144857)
+++ gcc/config/m68k/m68k.c	(working copy)
@@ -146,6 +146,7 @@ static tree m68k_handle_fndecl_attribute
 static void m68k_compute_frame_layout (void);
 static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
 static bool m68k_ok_for_sibcall_p (tree, tree);
+static rtx m68k_legitimize_address (rtx, rtx, enum machine_mode);
 static bool m68k_rtx_costs (rtx, int, int, int *, bool);
 #if M68K_HONOR_TARGET_STRICT_ALIGNMENT
 static bool m68k_return_in_memory (const_tree, const_tree);
@@ -198,6 +199,9 @@ int m68k_last_compare_had_fp_operands;
 #undef TARGET_ASM_FILE_START_APP_OFF
 #define TARGET_ASM_FILE_START_APP_OFF true
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS m68k_legitimize_address
+
 #undef TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST m68k_sched_adjust_cost
 
@@ -1425,6 +1429,83 @@ m68k_legitimize_sibcall_address (rtx x)
   return replace_equiv_address (x, gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM));
 }
 
+/* Convert X to a legitimate address and return it if successful.  Otherwise
+   return X.
+
+   For the 68000, we handle X+REG by loading X into a register R and
+   using R+REG.  R will go in an address reg and indexing will be used.
+   However, if REG is a broken-out memory address or multiplication,
+   nothing needs to be done because REG can certainly go in an address reg.  */
+
+rtx
+m68k_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
+{
+  if (GET_CODE (x) == PLUS)
+    {
+      int ch = (x) != (oldx);
+      int copied = 0;
+
+#define COPY_ONCE(Y) if (!copied) { Y = copy_rtx (Y); copied = ch = 1; }
+
+      if (GET_CODE (XEXP (x, 0)) == MULT)
+	{
+	  COPY_ONCE (x);
+	  XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
+	}
+      if (GET_CODE (XEXP (x, 1)) == MULT)
+	{
+	  COPY_ONCE (x);
+	  XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
+	}
+      if (ch)
+	{
+          if (GET_CODE (XEXP (x, 1)) == REG
+	      && GET_CODE (XEXP (x, 0)) == REG)
+	    {
+	      if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT)
+	        {
+	          COPY_ONCE (x);
+	          x = force_operand (x, 0);
+	        }
+	      return x;
+	    }
+	  if (memory_address_p (mode, x))
+	    return x;
+	}
+      if (GET_CODE (XEXP (x, 0)) == REG
+	  || (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
+	      && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+	      && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode))
+	{
+	  rtx temp = gen_reg_rtx (Pmode);
+	  rtx val = force_operand (XEXP (x, 1), 0);
+	  emit_move_insn (temp, val);
+	  COPY_ONCE (x);
+	  XEXP (x, 1) = temp;
+	  if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT
+	      && GET_CODE (XEXP (x, 0)) == REG)
+	    x = force_operand (x, 0);
+	}
+      else if (GET_CODE (XEXP (x, 1)) == REG
+	       || (GET_CODE (XEXP (x, 1)) == SIGN_EXTEND
+		   && GET_CODE (XEXP (XEXP (x, 1), 0)) == REG
+		   && GET_MODE (XEXP (XEXP (x, 1), 0)) == HImode))
+	{
+	  rtx temp = gen_reg_rtx (Pmode);
+	  rtx val = force_operand (XEXP (x, 0), 0);
+	  emit_move_insn (temp, val);
+	  COPY_ONCE (x);
+	  XEXP (x, 0) = temp;
+	  if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT
+	      && GET_CODE (XEXP (x, 1)) == REG)
+	    x = force_operand (x, 0);
+	}
+    }
+
+  return x;
+}
+
+ 
 /* Output a dbCC; jCC sequence.  Note we do not handle the 
    floating point version of this sequence (Fdbcc).  We also
    do not handle alternative conditions when CC_NO_OVERFLOW is
Index: gcc/config/m68k/m68k.h
===================================================================
--- gcc/config/m68k/m68k.h	(revision 144857)
+++ gcc/config/m68k/m68k.h	(working copy)
@@ -769,53 +769,6 @@ __transfer_from_trampoline ()					\
 
 /* This address is OK as it stands.  */
 #define PIC_CASE_VECTOR_ADDRESS(index) index
-\f
-/* For the 68000, we handle X+REG by loading X into a register R and
-   using R+REG.  R will go in an address reg and indexing will be used.
-   However, if REG is a broken-out memory address or multiplication,
-   nothing needs to be done because REG can certainly go in an address reg.  */
-#define COPY_ONCE(Y) if (!copied) { Y = copy_rtx (Y); copied = ch = 1; }
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)   \
-{ register int ch = (X) != (OLDX);					\
-  if (GET_CODE (X) == PLUS)						\
-    { int copied = 0;							\
-      if (GET_CODE (XEXP (X, 0)) == MULT)				\
-	{ COPY_ONCE (X); XEXP (X, 0) = force_operand (XEXP (X, 0), 0);}	\
-      if (GET_CODE (XEXP (X, 1)) == MULT)				\
-	{ COPY_ONCE (X); XEXP (X, 1) = force_operand (XEXP (X, 1), 0);}	\
-      if (ch && GET_CODE (XEXP (X, 1)) == REG				\
-	  && GET_CODE (XEXP (X, 0)) == REG)				\
-	{ if (TARGET_COLDFIRE_FPU					\
-	      && GET_MODE_CLASS (MODE) == MODE_FLOAT)			\
-	    { COPY_ONCE (X); X = force_operand (X, 0);}			\
-	  goto WIN; }							\
-      if (ch) { GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN); }		\
-      if (GET_CODE (XEXP (X, 0)) == REG					\
-	       || (GET_CODE (XEXP (X, 0)) == SIGN_EXTEND		\
-		   && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG		\
-		   && GET_MODE (XEXP (XEXP (X, 0), 0)) == HImode))	\
-	{ register rtx temp = gen_reg_rtx (Pmode);			\
-	  register rtx val = force_operand (XEXP (X, 1), 0);		\
-	  emit_move_insn (temp, val);					\
-	  COPY_ONCE (X);						\
-	  XEXP (X, 1) = temp;						\
-	  if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT \
-	      && GET_CODE (XEXP (X, 0)) == REG)				\
-	    X = force_operand (X, 0);					\
-	  goto WIN; }							\
-      else if (GET_CODE (XEXP (X, 1)) == REG				\
-	       || (GET_CODE (XEXP (X, 1)) == SIGN_EXTEND		\
-		   && GET_CODE (XEXP (XEXP (X, 1), 0)) == REG		\
-		   && GET_MODE (XEXP (XEXP (X, 1), 0)) == HImode))	\
-	{ register rtx temp = gen_reg_rtx (Pmode);			\
-	  register rtx val = force_operand (XEXP (X, 0), 0);		\
-	  emit_move_insn (temp, val);					\
-	  COPY_ONCE (X);						\
-	  XEXP (X, 0) = temp;						\
-	  if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (MODE) == MODE_FLOAT \
-	      && GET_CODE (XEXP (X, 1)) == REG)				\
-	    X = force_operand (X, 0);					\
-	  goto WIN; }}}
 
 /* On the 68000, only predecrement and postincrement address depend thus
    (the amount of decrement or increment being the length of the operand).
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 144857)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -107,7 +107,6 @@ extern rtx create_TOC_reference (rtx);
 extern void rs6000_split_multireg_move (rtx, rtx);
 extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
 extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode);
-extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
 extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
 					     int, int, int, int *);
 extern int rs6000_legitimate_address (enum machine_mode, rtx, int);
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 144857)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -919,6 +919,7 @@ int easy_vector_constant (rtx, enum mach
 static bool rs6000_is_opaque_type (const_tree);
 static rtx rs6000_dwarf_register_span (rtx);
 static void rs6000_init_dwarf_reg_sizes_extra (tree);
+static rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
 static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
 static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static rtx rs6000_tls_get_addr (void);
@@ -1105,6 +1106,9 @@ static const char alt_reg_names[][8] =
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS rs6000_legitimize_address
+
 #undef  TARGET_SCHED_VARIABLE_ISSUE
 #define TARGET_SCHED_VARIABLE_ISSUE rs6000_variable_issue
 
@@ -3871,7 +3875,7 @@ rs6000_legitimize_address (rtx x, rtx ol
 				      || mode == DImode)))
     {
       if (mode == DImode)
-	return NULL_RTX;
+	return x;
       /* We accept [reg + reg] and [reg + OFFSET].  */
 
       if (GET_CODE (x) == PLUS)
@@ -3943,7 +3947,7 @@ rs6000_legitimize_address (rtx x, rtx ol
       return create_TOC_reference (x);
     }
   else
-    return NULL_RTX;
+    return x;
 }
 
 /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 144857)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1814,38 +1814,6 @@ typedef struct rs6000_args
     goto ADDR;							\
 }
 \f
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.
-
-   On RS/6000, first check for the sum of a register with a constant
-   integer that is out of range.  If so, generate code to add the
-   constant with the low-order 16 bits masked to the register and force
-   this result into another register (this can be done with `cau').
-   Then generate an address of REG+(CONST&0xffff), allowing for the
-   possibility of bit 16 being a one.
-
-   Then check for the sum of a register and something not constant, try to
-   load the other things into a register and return the sum.  */
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)			\
-{  rtx result = rs6000_legitimize_address (X, OLDX, MODE);	\
-   if (result != NULL_RTX)					\
-     {								\
-       (X) = result;						\
-       goto WIN;						\
-     }								\
-}
-
 /* 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.
Index: gcc/config/picochip/picochip.h
===================================================================
--- gcc/config/picochip/picochip.h	(revision 144857)
+++ gcc/config/picochip/picochip.h	(working copy)
@@ -507,10 +507,6 @@ extern const enum reg_class picochip_reg
 
 #endif /* !REG_OK_STRICT */
 
-/* extern struct rtx_def *picochip_legitimize_address */
-/* 	PARAMS ((struct rtx_def *, struct rtx_def *, int)); */
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN);
-
 /* Legitimize reload address tries machine dependent means of
    reloading addresses.  There seems to be a strange error in gcc,
    which necessitates this macro.  Consider:
Index: gcc/config/score/score3.c
===================================================================
--- gcc/config/score/score3.c	(revision 144857)
+++ gcc/config/score/score3.c	(working copy)
@@ -414,31 +414,28 @@ score3_split_symbol (rtx temp, rtx addr)
   return gen_rtx_LO_SUM (Pmode, high, addr);
 }
 
-/* This function is used to implement LEGITIMIZE_ADDRESS.  If *XLOC can
+/* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
    be legitimized in a way that the generic machinery might not expect,
-   put the new address in *XLOC and return true.  */
-int
-score3_legitimize_address (rtx *xloc)
+   return the new address.  */
+rtx
+score3_legitimize_address (rtx x)
 {
   enum score_symbol_type symbol_type;
 
-  if (score3_symbolic_constant_p (*xloc, &symbol_type)
+  if (score3_symbolic_constant_p (x, &symbol_type)
       && symbol_type == SYMBOL_GENERAL)
-    {
-      *xloc = score3_split_symbol (0, *xloc);
-      return 1;
-    }
+    return score3_split_symbol (0, x);
 
-  if (GET_CODE (*xloc) == PLUS
-      && GET_CODE (XEXP (*xloc, 1)) == CONST_INT)
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 1)) == CONST_INT)
     {
-      rtx reg = XEXP (*xloc, 0);
+      rtx reg = XEXP (x, 0);
       if (!score3_valid_base_register_p (reg, 0))
         reg = copy_to_mode_reg (Pmode, reg);
-      *xloc = score3_add_offset (reg, INTVAL (XEXP (*xloc, 1)));
-      return 1;
+      return score3_add_offset (reg, INTVAL (XEXP (x, 1)));
     }
-  return 0;
+
+  return x;
 }
 
 /* Fill INFO with information about a single argument.  CUM is the
Index: gcc/config/score/score7.c
===================================================================
--- gcc/config/score/score7.c	(revision 144857)
+++ gcc/config/score/score7.c	(working copy)
@@ -413,31 +413,27 @@ score7_split_symbol (rtx temp, rtx addr)
   return gen_rtx_LO_SUM (Pmode, high, addr);
 }
 
-/* This function is used to implement LEGITIMIZE_ADDRESS.  If *XLOC can
+/* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
    be legitimized in a way that the generic machinery might not expect,
-   put the new address in *XLOC and return true.  */
-int
-score7_legitimize_address (rtx *xloc)
+   return the new address.  */
+rtx
+score7_legitimize_address (rtx x)
 {
   enum score_symbol_type symbol_type;
 
-  if (score7_symbolic_constant_p (*xloc, &symbol_type)
+  if (score7_symbolic_constant_p (x, &symbol_type)
       && symbol_type == SYMBOL_GENERAL)
-    {
-      *xloc = score7_split_symbol (0, *xloc);
-      return 1;
-    }
+    return score7_split_symbol (0, x);
 
-  if (GET_CODE (*xloc) == PLUS
-      && GET_CODE (XEXP (*xloc, 1)) == CONST_INT)
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 1)) == CONST_INT)
     {
-      rtx reg = XEXP (*xloc, 0);
+      rtx reg = XEXP (x, 0);
       if (!score7_valid_base_register_p (reg, 0))
         reg = copy_to_mode_reg (Pmode, reg);
-      *xloc = score7_add_offset (reg, INTVAL (XEXP (*xloc, 1)));
-      return 1;
-    }
-  return 0;
+      return score7_add_offset (reg, INTVAL (XEXP (x, 1)));
+
+  return x;
 }
 
 /* Fill INFO with information about a single argument.  CUM is the
Index: gcc/config/score/score3.h
===================================================================
--- gcc/config/score/score3.h	(revision 144857)
+++ gcc/config/score/score3.h	(working copy)
@@ -78,7 +78,7 @@ extern void score3_output_mi_thunk (FILE
                                     HOST_WIDE_INT delta,
                                     HOST_WIDE_INT vcall_offset,
                                     tree function);
-extern int score3_legitimize_address (rtx *xloc);
+extern rtx score3_legitimize_address (rtx x);
 extern void
 score3_function_prologue (FILE *file,
                           HOST_WIDE_INT size ATTRIBUTE_UNUSED);
Index: gcc/config/score/score-protos.h
===================================================================
--- gcc/config/score/score-protos.h	(revision 144857)
+++ gcc/config/score/score-protos.h	(working copy)
@@ -72,7 +72,6 @@ extern enum reg_class score_preferred_re
 extern HOST_WIDE_INT score_initial_elimination_offset (int from, int to);
 extern void score_print_operand (FILE *file, rtx op, int letter);
 extern void score_print_operand_address (FILE *file, rtx addr);
-extern int score_legitimize_address (rtx *xloc);
 extern int score_arg_partial_bytes (CUMULATIVE_ARGS *cum,
                                     enum machine_mode mode,
                                     tree type, bool named);
Index: gcc/config/score/score7.h
===================================================================
--- gcc/config/score/score7.h	(revision 144857)
+++ gcc/config/score/score7.h	(working copy)
@@ -78,7 +78,7 @@ extern void score7_output_mi_thunk (FILE
                                     HOST_WIDE_INT delta,
                                     HOST_WIDE_INT vcall_offset,
                                     tree function);
-extern int score7_legitimize_address (rtx *xloc);
+extern rtx score7_legitimize_address (rtx x);
 extern void
 score7_function_prologue (FILE *file,
                           HOST_WIDE_INT size ATTRIBUTE_UNUSED);
Index: gcc/config/score/score.c
===================================================================
--- gcc/config/score/score.c	(revision 144857)
+++ gcc/config/score/score.c	(working copy)
@@ -68,6 +68,9 @@
 #undef TARGET_HANDLE_OPTION
 #define TARGET_HANDLE_OPTION            score_handle_option
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS	score_legitimize_address
+
 #undef  TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE         score_issue_rate
 
@@ -540,16 +543,17 @@ score_address_p (enum machine_mode mode,
   gcc_unreachable ();
 }
 
-/* This function is used to implement LEGITIMIZE_ADDRESS.  If *XLOC can
+/* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
    be legitimized in a way that the generic machinery might not expect,
-   put the new address in *XLOC and return true.  */
-int
-score_legitimize_address (rtx *xloc)
+   return the new address, else return X.  */
+static rtx
+score_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			  enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   if (TARGET_SCORE5 || TARGET_SCORE5U || TARGET_SCORE7 || TARGET_SCORE7D)
-    return score7_legitimize_address (xloc);
+    return score7_legitimize_address (x);
   else if (TARGET_SCORE3)
-    return score3_legitimize_address (xloc);
+    return score3_legitimize_address (x);
 
   gcc_unreachable ();
 }
Index: gcc/config/score/score.h
===================================================================
--- gcc/config/score/score.h	(revision 144857)
+++ gcc/config/score/score.h	(working copy)
@@ -776,12 +776,6 @@ typedef struct score_args
 
 #define REG_OK_FOR_INDEX_P(X) 0
 
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)   \
-  do {                                           \
-    if (score_legitimize_address (&(X)))         \
-      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.  */
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)       {}
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 144857)
+++ gcc/config/arm/arm.c	(working copy)
@@ -73,6 +73,8 @@ static int arm_address_register_rtx_p (r
 static int arm_legitimate_index_p (enum machine_mode, rtx, RTX_CODE, int);
 static int thumb2_legitimate_index_p (enum machine_mode, rtx, int);
 static int thumb1_base_register_rtx_p (rtx, enum machine_mode, int);
+static rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
+static rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
 inline static int thumb1_index_register_rtx_p (rtx, int);
 static int thumb_far_jump_used_p (void);
 static bool thumb_force_lr_save (void);
@@ -205,6 +207,9 @@ static bool arm_allocate_stack_slots_for
 #define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
 #endif
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS arm_legitimize_address
+
 #undef  TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE arm_attribute_table
 
@@ -4590,6 +4595,14 @@ legitimize_tls_address (rtx x, rtx reg)
 rtx
 arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
 {
+  if (!TARGET_ARM)
+    {
+      /* TODO: legitimize_address for Thumb2.  */
+      if (TARGET_THUMB2)
+        return x;
+      return thumb_legitimize_address (x, orig_x, mode);
+    }
+
   if (arm_tls_symbol_p (x))
     return legitimize_tls_address (x, NULL_RTX);
 
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	(revision 144857)
+++ gcc/config/arm/arm.h	(working copy)
@@ -2201,36 +2201,6 @@ typedef struct
     THUMB1_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
 
 \f
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.  */
-#define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	\
-do {							\
-  X = arm_legitimize_address (X, OLDX, MODE);		\
-} while (0)
-
-/* ??? Implement LEGITIMIZE_ADDRESS for thumb2.  */
-#define THUMB2_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	\
-do {							\
-} while (0)
-
-#define THUMB1_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	\
-do {							\
-  X = thumb_legitimize_address (X, OLDX, MODE);		\
-} while (0)
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)		\
-do {							\
-  if (TARGET_ARM)					\
-    ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);	\
-  else if (TARGET_THUMB2)				\
-    THUMB2_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);	\
-  else							\
-    THUMB1_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);	\
-							\
-  if (memory_address_p (MODE, X))			\
-    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.  */
 #define ARM_GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)  			\
Index: gcc/config/arm/arm-protos.h
===================================================================
--- gcc/config/arm/arm-protos.h	(revision 144857)
+++ gcc/config/arm/arm-protos.h	(working copy)
@@ -58,8 +58,6 @@ extern int arm_legitimate_address_p  (en
 extern int thumb1_legitimate_address_p (enum machine_mode, rtx, int);
 extern int thumb2_legitimate_address_p  (enum machine_mode, rtx, int);
 extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
-extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
-extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
 extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
 					    int);
 extern int arm_const_double_rtx (rtx);
Index: gcc/config/pa/pa-protos.h
===================================================================
--- gcc/config/pa/pa-protos.h	(revision 144857)
+++ gcc/config/pa/pa-protos.h	(working copy)
@@ -29,8 +29,6 @@ extern int following_call (rtx);
 extern int function_label_operand (rtx, enum machine_mode);
 extern int lhs_lshift_cint_operand (rtx, enum machine_mode);
 
-extern rtx hppa_legitimize_address (rtx, rtx, enum machine_mode);
-
 /* Define functions in pa.c and used in insn-output.c.  */
 
 extern const char *output_and (rtx *);
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c	(revision 144857)
+++ gcc/config/pa/pa.c	(working copy)
@@ -131,6 +131,7 @@ static bool pa_scalar_mode_supported_p (
 static bool pa_commutative_p (const_rtx x, int outer_code);
 static void copy_fp_args (rtx) ATTRIBUTE_UNUSED;
 static int length_fp_args (rtx) ATTRIBUTE_UNUSED;
+static rtx hppa_legitimize_address (rtx, rtx, enum machine_mode);
 static inline void pa_file_start_level (void) ATTRIBUTE_UNUSED;
 static inline void pa_file_start_space (int) ATTRIBUTE_UNUSED;
 static inline void pa_file_start_file (int) ATTRIBUTE_UNUSED;
@@ -228,6 +229,9 @@ static size_t n_deferred_plabels = 0;
 #undef TARGET_ASM_FUNCTION_EPILOGUE
 #define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS hppa_legitimize_address
+
 #undef TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST pa_adjust_cost
 #undef TARGET_SCHED_ADJUST_PRIORITY
Index: gcc/config/pa/pa.h
===================================================================
--- gcc/config/pa/pa.h	(revision 144857)
+++ gcc/config/pa/pa.h	(working copy)
@@ -1422,26 +1422,6 @@ do { 									\
 
 
 
-\f
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.  */
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	\
-{ rtx orig_x = (X);				\
-  (X) = hppa_legitimize_address (X, OLDX, MODE);	\
-  if ((X) != orig_x && memory_address_p (MODE, X)) \
-    goto WIN; }
-
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.  */
 
Index: gcc/config/mips/mips-protos.h
===================================================================
--- gcc/config/mips/mips-protos.h	(revision 144857)
+++ gcc/config/mips/mips-protos.h	(working copy)
@@ -196,7 +196,6 @@ extern rtx mips_pic_base_register (rtx);
 extern rtx mips_got_load (rtx, rtx, enum mips_symbol_type);
 extern bool mips_split_symbol (rtx, rtx, enum machine_mode, rtx *);
 extern rtx mips_unspec_address (rtx, enum mips_symbol_type);
-extern bool mips_legitimize_address (rtx *, enum machine_mode);
 extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT);
 extern bool mips_legitimize_move (enum machine_mode, rtx, rtx);
 
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	(revision 144857)
+++ gcc/config/mips/mips.c	(working copy)
@@ -2786,41 +2786,36 @@ mips_force_address (rtx x, enum machine_
   return x;
 }
 
-/* This function is used to implement LEGITIMIZE_ADDRESS.  If *XLOC can
+/* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
    be legitimized in a way that the generic machinery might not expect,
-   put the new address in *XLOC and return true.  MODE is the mode of
+   return a new address, otherwise return NULL.  MODE is the mode of
    the memory being accessed.  */
 
-bool
-mips_legitimize_address (rtx *xloc, enum machine_mode mode)
+static rtx
+mips_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+			 enum machine_mode mode)
 {
   rtx base, addr;
   HOST_WIDE_INT offset;
 
-  if (mips_tls_symbol_p (*xloc))
-    {
-      *xloc = mips_legitimize_tls_address (*xloc);
-      return true;
-    }
+  if (mips_tls_symbol_p (x))
+    return mips_legitimize_tls_address (x);
 
   /* See if the address can split into a high part and a LO_SUM.  */
-  if (mips_split_symbol (NULL, *xloc, mode, &addr))
-    {
-      *xloc = mips_force_address (addr, mode);
-      return true;
-    }
+  if (mips_split_symbol (NULL, x, mode, &addr))
+    return mips_force_address (addr, mode);
 
   /* Handle BASE + OFFSET using mips_add_offset.  */
-  mips_split_plus (*xloc, &base, &offset);
+  mips_split_plus (x, &base, &offset);
   if (offset != 0)
     {
       if (!mips_valid_base_register_p (base, mode, false))
 	base = copy_to_mode_reg (Pmode, base);
       addr = mips_add_offset (NULL, base, offset);
-      *xloc = mips_force_address (addr, mode);
-      return true;
+      return mips_force_address (addr, mode);
     }
-  return false;
+
+  return x;
 }
 
 /* Load VALUE into DEST.  TEMP is as for mips_force_temporary.  */
@@ -14251,6 +14246,9 @@ mips_order_regs_for_local_alloc (void)
 #undef TARGET_ASM_ALIGNED_DI_OP
 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
 
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS mips_legitimize_address
+
 #undef TARGET_ASM_FUNCTION_PROLOGUE
 #define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
 #undef TARGET_ASM_FUNCTION_EPILOGUE
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	(revision 144857)
+++ gcc/config/mips/mips.h	(working copy)
@@ -2499,13 +2499,6 @@ typedef struct mips_args {
 
 #define LEGITIMATE_CONSTANT_P(X) (mips_const_insns (X) > 0)
 
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)			\
-  do {								\
-    if (mips_legitimize_address (&(X), MODE))			\
-      goto WIN;							\
-  } while (0)
-
-
 /* A C statement or compound statement with a conditional `goto
    LABEL;' executed if memory address X (an RTX) can have different
    meanings depending on the machine mode of the memory reference it
Index: gcc/config/bfin/bfin-protos.h
===================================================================
--- gcc/config/bfin/bfin-protos.h	(revision 144857)
+++ gcc/config/bfin/bfin-protos.h	(working copy)
@@ -104,7 +104,6 @@ extern char *bfin_asm_long (void);
 extern char *bfin_asm_short (void);
 extern int log2constp (unsigned HOST_WIDE_INT);
 
-extern rtx legitimize_address (rtx, rtx, Mmode);
 extern bool bfin_legitimate_constant_p (rtx);
 extern int hard_regno_mode_ok (int, Mmode);
 extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);	  
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c	(revision 144857)
+++ gcc/config/bfin/bfin.c	(working copy)
@@ -1417,22 +1417,6 @@ bfin_return_addr_rtx (int count)
   return get_hard_reg_initial_val (Pmode, REG_RETS);
 }
 
-/* Try machine-dependent ways of modifying an illegitimate address X
-   to be legitimate.  If we find one, return the new, valid address,
-   otherwise return NULL_RTX.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE is the mode of the memory reference.  */
-
-rtx
-legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
-		    enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return NULL_RTX;
-}
-
 static rtx
 bfin_delegitimize_address (rtx orig_x)
 {
Index: gcc/config/bfin/bfin.h
===================================================================
--- gcc/config/bfin/bfin.h	(revision 144857)
+++ gcc/config/bfin/bfin.h	(working copy)
@@ -948,25 +948,6 @@ typedef struct {
   } while (0);
 #endif
 
-/* Try machine-dependent ways of modifying an illegitimate address
-   to be legitimate.  If we find one, return the new, valid address.
-   This macro is used in only one place: `memory_address' in explow.c.
-
-   OLDX is the address as it was before break_out_memory_refs was called.
-   In some cases it is useful to look at this to decide what needs to be done.
-
-   MODE and WIN are passed so that this macro can use
-   GO_IF_LEGITIMATE_ADDRESS.
-
-   It is always safe for this macro to do nothing.  It exists to recognize
-   opportunities to optimize the output.
- */
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)    \
-do {					       \
-   rtx _q = legitimize_address(X, OLDX, MODE); \
-   if (_q) { X = _q; goto WIN; }	       \
-} while (0)
-
 #define HAVE_POST_INCREMENT 1
 #define HAVE_POST_DECREMENT 1
 #define HAVE_PRE_DECREMENT  1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Hookize LEGITIMIZE_ADDRESS
  2009-04-17  7:03 [PATCH] Hookize LEGITIMIZE_ADDRESS Paolo Bonzini
@ 2009-04-17 10:12 ` Joseph S. Myers
  2009-04-19 19:39   ` Richard Sandiford
  2009-05-03  0:09 ` Ian Lance Taylor
  1 sibling, 1 reply; 5+ messages in thread
From: Joseph S. Myers @ 2009-04-17 10:12 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: GCC Patches, Michael Meissner

On Fri, 17 Apr 2009, Paolo Bonzini wrote:

> +@deftypefn {Target Hook} rtx LEGITIMIZE_ADDRESS (rtx @var{x}, rtx @var{oldx}, enum machine_mode @var{mode})

The hook is TARGET_LEGITIMIZE_ADDRESS, not LEGITIMIZE_ADDRESS.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Hookize LEGITIMIZE_ADDRESS
  2009-04-17 10:12 ` Joseph S. Myers
@ 2009-04-19 19:39   ` Richard Sandiford
  0 siblings, 0 replies; 5+ messages in thread
From: Richard Sandiford @ 2009-04-19 19:39 UTC (permalink / raw)
  To: Paolo Bonzini, GCC Patches

Thanks for doing this!

"Joseph S. Myers" <joseph@codesourcery.com> writes:
> On Fri, 17 Apr 2009, Paolo Bonzini wrote:
>
>> +@deftypefn {Target Hook} rtx LEGITIMIZE_ADDRESS (rtx @var{x}, rtx @var{oldx}, enum machine_mode @var{mode})
>
> The hook is TARGET_LEGITIMIZE_ADDRESS, not LEGITIMIZE_ADDRESS.

Same thing in the MIPS comment.  Also:

-/* This function is used to implement LEGITIMIZE_ADDRESS.  If *XLOC can
+/* This function is used to implement LEGITIMIZE_ADDRESS.  If X can
    be legitimized in a way that the generic machinery might not expect,
-   put the new address in *XLOC and return true.  MODE is the mode of
+   return a new address, otherwise return NULL.  MODE is the mode of
    the memory being accessed.  */

s/otherwise return NULL/otherwise return X/.  Although now that this
function has a standard interface -- rather than being an internal
implementation of a standard macro -- plain:

/* Implement TARGET_LEGITIMIZE_ADDRESS.  */

is probably better.  The MIPS parts are OK with that change.

Richard

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Hookize LEGITIMIZE_ADDRESS
  2009-04-17  7:03 [PATCH] Hookize LEGITIMIZE_ADDRESS Paolo Bonzini
  2009-04-17 10:12 ` Joseph S. Myers
@ 2009-05-03  0:09 ` Ian Lance Taylor
  2009-05-04 13:38   ` Paolo Bonzini
  1 sibling, 1 reply; 5+ messages in thread
From: Ian Lance Taylor @ 2009-05-03  0:09 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: GCC Patches, Michael Meissner

Paolo Bonzini <bonzini@gnu.org> writes:

> 2009-04-16  Paolo Bonzini  <bonzini@gnu.org>
>
> 	* doc/tm.texi (LEGITIMIZE_ADDRESS): Revise documentation.
>         * gcc/defaults.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/explow.c (memory_address): Use target hook.
>         * gcc/targhooks.c (default_legitimize_address): New.
>         * gcc/targhooks.h (default_legitimize_address): New.
>         * gcc/target.h (legitimize_address): New.
>         * gcc/target-def.h (TARGET_LEGITIMIZE_ADDRESS): New.
>         (TARGET_INITIALIZER): Include it.
>         * gcc/system.h (LEGITIMIZE_ADDRESS): Poison.
>
>         * config/bfin/bfin-protos.h (legitimize_address): Remove.
>         * config/bfin/bfin.c (legitimize_address): Remove.
>         * config/bfin/bfin.h (LEGITIMIZE_ADDRESS): Remove.
>         * config/m68hc11/m68hc11-protos.h (m68hc11_legitimize_address): Remove.
>         * config/m68hc11/m68hc11.c (m68hc11_legitimize_address): Remove.
>         * config/m68hc11/m68hc11.h (LEGITIMIZE_ADDRESS): Remove.
>
>         * gcc/config/arm/arm.h (LEGITIMIZE_ADDRESS, ARM_LEGITIMIZE_ADDRESS,
>         THUMB_LEGITIMIZE_ADDRESS, THUMB2_LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/s390/s390.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/m32c/m32c.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/sparc/sparc.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/m32r/m32r.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/i386/i386.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/sh/sh.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/avr/avr.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/m68hc11/m68hc11.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/iq2000/iq2000.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/mn10300/mn10300.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/m68k/m68k.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/score/score.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/pa/pa.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/mips/mips.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/alpha/alpha.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/frv/frv.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/spu/spu.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/xtensa/xtensa.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/cris/cris.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/rs6000/rs6000.h (LEGITIMIZE_ADDRESS): Delete.
>         * gcc/config/picochip/picochip.h (LEGITIMIZE_ADDRESS): Delete.
>
>         * gcc/config/s390/s390-protos.h (legitimize_address): Delete.
>         * gcc/config/m32c/m32c-protos.h (m32c_legitimize_address): Delete.
>         * gcc/config/sparc/sparc-protos.h (legitimize_address): Delete.
>         * gcc/config/i386/i386-protos.h (legitimize_address): Delete.
>         * gcc/config/avr/avr-protos.h (legitimize_address): Delete.
>         * gcc/config/mn10300/mn10300-protos.h (legitimize_address): Delete.
>         * gcc/config/score/score-protos.h (score_legitimize_address): Delete.
>         * gcc/config/arm/arm-protos.h (arm_legitimize_address,
>         (thumb_legitimize_address): Delete.
>         * gcc/config/pa/pa-protos.h (hppa_legitimize_address): Delete.
>         * gcc/config/mips/mips-protos.h (mips_legitimize_address): Delete.
>         * gcc/config/alpha/alpha-protos.h (alpha_legitimize_address): Delete.
>         * gcc/config/frv/frv-protos.h (frv_legitimize_address): Delete.
>         * gcc/config/spu/spu-protos.h (spu_legitimize_address): Delete.
>         * gcc/config/xtensa/xtensa-protos.h (xtensa_legitimize_address): Delete.
>         * gcc/config/rs6000/rs6000-protos.h (rs6000_legitimize_address): Delete.
>
>         * config/arm/arm.c (arm_legitimize_address): Maybe call Thumb version.
>         * config/m32c/m32c.c (m32c_legitimize_address): Standardize.
>         * config/m32r/m32r.c (m32r_legitimize_address): New.
>         * config/m68k/m68k.c (m68k_legitimize_address): New.
>         * config/score/score.c (score_legitimize_address): Standardize.
>         * config/score/score3.c (score3_legitimize_address): Standardize.
>         * config/score/score3.h (score3_legitimize_address): Adjust.
>         * config/score/score7.c (score7_legitimize_address): Standardize.
>         * config/score/score7.h (score7_legitimize_address): Adjust.
>         * config/sh/sh.c (sh_legitimize_address): New.
>         * config/iq2000/iq2000.c (iq2000_legitimize_address): New.
>
>         * gcc/config/s390/s390.c (legitimize_address): Rename to...
> 	(s390_legitimize_address): ... this.
>         * gcc/config/sparc/sparc.c (legitimize_address): Rename to...
>         (sparc_legitimize_address): ... this.
>         * gcc/config/i386/i386.c (legitimize_address): Rename to...
>         (ix86_legitimize_address): ... this.
>         * gcc/config/avr/avr.c (legitimize_address): Rename to...
>         (avr_legitimize_address): ... this.
>         * gcc/config/mn10300/mn10300.c (legitimize_address): Rename to...
>         (mn10300_legitimize_address): ... this.
>         * config/alpha/alpha.c (alpha_legitimize_address): Wrap...
>         (alpha_legitimize_address_1): ... the old alpha_legitimize_address.
>         (alpha_expand_mov): Adjust call.
>
>         * config/frv/frv.c (frv_legitimize_address): Return x on failure.
>         * config/spu/spu.c (spu_legitimize_address): Likewise.
>         * config/xtensa/xtensa.c (xtensa_legitimize_address): Likewise.
>         * config/rs6000/rs6000.c (rs6000_legitimize_address): Likewise.

This is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Hookize LEGITIMIZE_ADDRESS
  2009-05-03  0:09 ` Ian Lance Taylor
@ 2009-05-04 13:38   ` Paolo Bonzini
  0 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2009-05-04 13:38 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: GCC Patches, Michael Meissner

Ian Lance Taylor wrote:

> This is OK.

Committed, thanks.

Michael, how do you want to proceed for merging this to
named-addr-spaces branch?  I can take care of that if you wish, but only
after the GO_IF_LEGITIMATE_ADDRESS patch is reviewed and committed to trunk.

Paolo

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-05-04 13:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-17  7:03 [PATCH] Hookize LEGITIMIZE_ADDRESS Paolo Bonzini
2009-04-17 10:12 ` Joseph S. Myers
2009-04-19 19:39   ` Richard Sandiford
2009-05-03  0:09 ` Ian Lance Taylor
2009-05-04 13:38   ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).