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