Richard Sandiford <[EMAIL PROTECTED]> writes:
> Manuel Lauss <[EMAIL PROTECTED]> writes:
>> Admittedly my understanding of mips assembly is not yet very advanced, am I
>> missing something or is this a bug?
>
> Well, it's a missed optimisation, certainly.  Fortunately,
> it's conceptually fairly easy to fix.

FWIW, I've attached a patch against GCC 4.4 below.  Tested on
mipsisa64-elfoabi.

I don't think it's appropriate to apply the patch at this stage
in the development cycle, so I'll hold it back for GCC 4.5.
I'll add some testcases then too.

Richard


gcc/
        * config/mips/mips.c (mips_legitimize_address): Handle illegitimate
        CONST_INT addresses.

Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c      2008-11-22 21:33:49.000000000 +0000
+++ gcc/config/mips/mips.c      2008-11-22 21:34:07.000000000 +0000
@@ -2796,7 +2796,7 @@ mips_force_address (rtx x, enum machine_
 mips_legitimize_address (rtx *xloc, enum machine_mode mode)
 {
   rtx base, addr;
-  HOST_WIDE_INT offset;
+  HOST_WIDE_INT intval, high, offset;
 
   if (mips_tls_symbol_p (*xloc))
     {
@@ -2821,6 +2821,33 @@ mips_legitimize_address (rtx *xloc, enum
       *xloc = mips_force_address (addr, mode);
       return true;
     }
+
+  /* Handle references to constant addresses by loading the high part
+     into a register and using an offset for the low part.  */
+  if (GET_CODE (base) == CONST_INT)
+    {
+      intval = INTVAL (base);
+      high = trunc_int_for_mode (CONST_HIGH_PART (intval), Pmode);
+      offset = CONST_LOW_PART (intval);
+      /* Ignore cases in which a positive address would be accessed by a
+        negative offset from a negative address.  The required wraparound
+        does not occur for 32-bit addresses on 64-bit targets, and it is
+        very unlikely that such an access would occur in real code anyway.
+
+        If the low offset is not legitimate for MODE, prefer to load
+        the constant normally, instead of using mips_force_address on
+        the legitimized address.  The latter option would cause us to
+        use (D)ADDIU unconditionally, but LUI/ORI is more efficient
+        than LUI/ADDIU on some targets.  */
+      if ((intval < 0 || high > 0)
+         && mips_valid_offset_p (GEN_INT (offset), mode))
+       {
+         base = mips_force_temporary (NULL, GEN_INT (high));
+         *xloc = plus_constant (base, offset);
+         return true;
+       }
+    }
+
   return false;
 }
 

Reply via email to