http://bugs.gentoo.org/257054 MIPS: smarter code for constant addresses http://gcc.gnu.org/ml/gcc/2008-11/msg00231.html --- a/gcc/config/mips/mips.c 2009-03-02 21:26:22.000000000 +0100 +++ b/gcc/config/mips/mips.c 2009-08-16 11:56:08.000000000 +0200 @@ -2795,7 +2795,7 @@ bool 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)) { @@ -2820,6 +2820,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; }