"H.J. Lu" <hjl.to...@gmail.com> writes: >>> LRA has >>> >>> if (REG_P (reg) && (ep = get_elimination (reg)) != NULL) >>> { >>> rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx; >>> >>> if (! replace_p) >>> { >>> offset += (ep->offset - ep->previous_offset); >>> offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src)); >>> } >>> >>> if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG) >>> to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), >>> to_rtx); >>> >>> Reload has >>> >>> rtx to_rtx = ep->to_rtx; >>> offset += ep->offset; >>> offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src)); >>> >>> if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG) >>> to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), >>> to_rtx); >>> >>> (gdb) call debug_rtx (ep->to_rtx) >>> (reg/f:DI 7 sp) >>> (gdb) call debug_rtx (ep->from_rtx) >>> (reg/f:DI 16 argp) >>> (gdb) >>> >>> gen_lowpart returns (reg/f:DI 7 sp) for reload and (reg:SI 16 argp) >>> for LRA. They are caused by >>> >>> if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM >>> /* We should convert arg register in LRA after the elimination >>> if it is possible. */ >>> && xregno == ARG_POINTER_REGNUM >>> && ! lra_in_progress) >>> return -1; >>> >>> It doesn't work in this case. >>> >> >> This testcase shows that LRA can't convert arg register after >> the elimination. >> > Here is a patch to remove ra_in_progress check for > ARG_POINTER_REGNUM. Tested on Linux.x86-64. > OK to install?
Thanks HJ. This looks good to me. As well as your testcase, I think it would be dangerous to reduce this kind of subreg during non-final elimination in cases where the argument pointer occupies more than one hard register (like avr IIRC). We could end up with something like ARG_POINTER_REGNUM+1, which wouldn't show up as an elimination register during the rest of LRA. It's important that we do get rid of the subreg during the final elimination stage, but I think alter_subreg already handles that case. Since this code is outside the LRA files: patch is OK if Vlad agrees. Richard