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;
}