On Mon, Jun 27, 2011 at 3:25 PM, H.J. Lu <hjl.to...@gmail.com> wrote: > On Mon, Jun 27, 2011 at 3:19 PM, H.J. Lu <hjl.to...@gmail.com> wrote: >> On Mon, Jun 27, 2011 at 3:08 PM, Ulrich Weigand <uweig...@de.ibm.com> wrote: >>> H.J. Lu wrote: >>> >>>> reload generates: >>>> >>>> (insn 914 912 0 (set (reg:SI 0 ax) >>>> (plus:SI (subreg:SI (reg/v/f:DI 182 [ b ]) 0) >>>> (const_int 8 [0x8]))) 248 {*lea_1_x32} >>>> (nil)) >>>> >>>> from >>>> >>>> insn = emit_insn_if_valid_for_reload (gen_rtx_SET (VOIDmode, out, in)); >>> >>> Interesting. The pseudo should have been replaced by the >>> hard register (reg:DI 1) during the preceding call to >>> op0 = find_replacement (&XEXP (in, 0)); >>> (since reload 0 should have pushed a replacement record.) >>> >>> Interestingly enough, in the final output that replacement *is* >>> performed in the REG_EQUIV note: >>> >>> (insn 1023 1022 1024 34 (set (reg:SI 1 dx) >>> (plus:SI (reg:SI 1 dx) >>> (const_int 8 [0x8]))) spooles.c:291 248 {*lea_1_x32} >>> (expr_list:REG_EQUIV (plus:SI (subreg:SI (reg:DI 1 dx) 0) >>> (const_int 8 [0x8])) >>> (nil))) >>> >>> which is why I hadn't expected this to be a problem here. >>> >>> Can you try to find out why the find_replacement doesn't work >>> with your test case? >>> >> >> I will investigate. Could (reg:SI 1 dx) vs (subreg:SI (reg:DI 1 dx) 0) >> a problem? >> > > find_replacement never checks subreg: > > Breakpoint 3, find_replacement (loc=0x7ffff068ab00) > at /export/gnu/import/git/gcc-x32/gcc/reload.c:6411 > 6411 if (reloadreg && r->where == loc) > (reg:DI 0 ax) > (reg/v/f:DI 182 [ b ]) > (gdb) call debug_rtx (*loc) > (subreg:SI (reg/v/f:DI 182 [ b ]) 0) > (gdb) >
This seems to work. Does it make any senses? Thanks. -- H.J. --- diff --git a/gcc/reload.c b/gcc/reload.c index 3ad46b9..bdc47d3 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -6415,6 +6415,26 @@ find_replacement (rtx *loc) return reloadreg; } + else if (reloadreg + && REG_P (reloadreg) + && !r->subreg_loc + && GET_CODE (*loc) == SUBREG + && r->where == &SUBREG_REG (*loc)) + { + int offset; + + if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode) + reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg)); + + offset = (GET_MODE_SIZE (GET_MODE (reloadreg)) + - GET_MODE_SIZE (GET_MODE (*loc))); + + if (! BYTES_BIG_ENDIAN) + offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD; + else if (! WORDS_BIG_ENDIAN) + offset %= UNITS_PER_WORD; + return gen_rtx_SUBREG (GET_MODE (*loc), reloadreg, offset); + } else if (reloadreg && r->subreg_loc == loc) { /* RELOADREG must be either a REG or a SUBREG.