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 patch checks SUBREG pointer if Pmode != ptr_mode. OK for trunk? Thanks. -- H.J. --- 2011-06-28 H.J. Lu <hongjiu...@intel.com> PR rtl-optimization/49114 * reload.c (find_replacement): Properly handle SUBREG pointers. diff --git a/gcc/reload.c b/gcc/reload.c index 3ad46b9..829e45b 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -6415,6 +6415,36 @@ find_replacement (rtx *loc) return reloadreg; } + else if (Pmode != ptr_mode + && !r->subreg_loc + && reloadreg + && (r->mode == Pmode || GET_MODE (reloadreg) == Pmode) + && REG_P (reloadreg) + && GET_CODE (*loc) == SUBREG + && REG_P (SUBREG_REG (*loc)) + && REG_POINTER (SUBREG_REG (*loc)) + && GET_MODE (*loc) == ptr_mode + && r->where == &SUBREG_REG (*loc)) + { + int offset; + + if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode) + reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg)); + + if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN) + && GET_MODE_SIZE (Pmode) > GET_MODE_SIZE (ptr_mode)) + { + offset = GET_MODE_SIZE (Pmode) - GET_MODE_SIZE (ptr_mode); + if (! BYTES_BIG_ENDIAN) + offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD; + else if (! WORDS_BIG_ENDIAN) + offset %= UNITS_PER_WORD; + } + else + offset = 0; + + return gen_rtx_SUBREG (ptr_mode, reloadreg, offset); + } else if (reloadreg && r->subreg_loc == loc) { /* RELOADREG must be either a REG or a SUBREG.