was Re: [PATCH] Change replace_rtx if from is a REG (PR target/70245, take 2) On Thu, Mar 17, 2016 at 11:07:03PM +1030, Alan Modra wrote: > By the look of what you posted in the bugzilla, the pattern is the > parallel emitted by rs6000_emit_savres_rtx. In that parallel, the > stack memory locations for register saves are described relative to > whatever frame_reg_rtx is in use, which may be r12. > rs6000_frame_related wants to translate the frame_reg_rtx into stack > pointer plus offset for debug info. > > The parallel matches save_gpregs_<mode>_r12 and similar in rs6000.md, > which emit a call to an out-of-line register save function. This > function actually takes r12 as a parameter, hence the (use (reg:P 12)) > in the pattern. > > rs6000_frame_related probably should just be replacing individual > SETs in the parallel using simplify_replace_rtx. Especially since > after calling replace_rtx, it already iterates over them to simplify.
Like this. Bootstrapped and regression tested powerpc64le-linux and powerpc64-linux. Modify SETs rather than using replace_rtx on the whole insn. Removes fragile hacks preventing USE and CLOBBER being modified. * config/rs6000/rs6000.c (rs6000_frame_related): Rewrite. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index fb522fb..67bcbc8 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -24712,7 +24712,7 @@ output_probe_stack_range (rtx reg1, rtx reg2) } /* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced - with (plus:P (reg 1) VAL), and with REG2 replaced with RREG if REG2 + with (plus:P (reg 1) VAL), and with REG2 replaced with REPL2 if REG2 is not NULL. It would be nice if dwarf2out_frame_debug_expr could deduce these equivalences by itself so it wasn't necessary to hold its hand so much. Don't be tempted to always supply d2_f_d_e with @@ -24722,22 +24722,28 @@ output_probe_stack_range (rtx reg1, rtx reg2) static rtx rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val, - rtx reg2, rtx rreg) + rtx reg2, rtx repl2) { - rtx real, temp; + rtx patt, repl; - if (REGNO (reg) == STACK_POINTER_REGNUM && reg2 == NULL_RTX) + repl = NULL_RTX; + if (REGNO (reg) == STACK_POINTER_REGNUM) + gcc_checking_assert (val == 0); + else + repl = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM), + GEN_INT (val)); + + patt = PATTERN (insn); + if (!repl && !reg2) { /* No need for any replacement. Just set RTX_FRAME_RELATED_P. */ int i; - gcc_checking_assert (val == 0); - real = PATTERN (insn); - if (GET_CODE (real) == PARALLEL) - for (i = 0; i < XVECLEN (real, 0); i++) - if (GET_CODE (XVECEXP (real, 0, i)) == SET) + if (GET_CODE (patt) == PARALLEL) + for (i = 0; i < XVECLEN (patt, 0); i++) + if (GET_CODE (XVECEXP (patt, 0, i)) == SET) { - rtx set = XVECEXP (real, 0, i); + rtx set = XVECEXP (patt, 0, i); /* If this PARALLEL has been emitted for out-of-line register save functions, or store multiple, then omit @@ -24752,79 +24758,49 @@ rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val, return insn; } - /* copy_rtx will not make unique copies of registers, so we need to - ensure we don't have unwanted sharing here. */ - if (reg == reg2) - reg = gen_raw_REG (GET_MODE (reg), REGNO (reg)); - - if (reg == rreg) - reg = gen_raw_REG (GET_MODE (reg), REGNO (reg)); - - real = copy_rtx (PATTERN (insn)); - - if (reg2 != NULL_RTX) - real = replace_rtx (real, reg2, rreg); - - if (REGNO (reg) == STACK_POINTER_REGNUM) - gcc_checking_assert (val == 0); - else - real = replace_rtx (real, reg, - gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, - STACK_POINTER_REGNUM), - GEN_INT (val))); - - /* We expect that 'real' is either a SET or a PARALLEL containing + /* We expect that 'patt' is either a SET or a PARALLEL containing SETs (and possibly other stuff). In a PARALLEL, all the SETs - are important so they all have to be marked RTX_FRAME_RELATED_P. */ + are important so they all have to be marked RTX_FRAME_RELATED_P. + Call simplify_replace_rtx on the SETs rather than the whole insn + so as to leave the other stuff alone (for example USE of r12). */ - if (GET_CODE (real) == SET) + if (GET_CODE (patt) == SET) { - rtx set = real; - - temp = simplify_rtx (SET_SRC (set)); - if (temp) - SET_SRC (set) = temp; - temp = simplify_rtx (SET_DEST (set)); - if (temp) - SET_DEST (set) = temp; - if (GET_CODE (SET_DEST (set)) == MEM) - { - temp = simplify_rtx (XEXP (SET_DEST (set), 0)); - if (temp) - XEXP (SET_DEST (set), 0) = temp; - } + if (repl) + patt = simplify_replace_rtx (patt, reg, repl); + if (reg2) + patt = simplify_replace_rtx (patt, reg2, repl2); } - else + else if (GET_CODE (patt) == PARALLEL) { int i; - gcc_assert (GET_CODE (real) == PARALLEL); - for (i = 0; i < XVECLEN (real, 0); i++) - if (GET_CODE (XVECEXP (real, 0, i)) == SET) + patt = shallow_copy_rtx (patt); + XVEC (patt, 0) = shallow_copy_rtvec (XVEC (patt, 0)); + + for (i = 0; i < XVECLEN (patt, 0); i++) + if (GET_CODE (XVECEXP (patt, 0, i)) == SET) { - rtx set = XVECEXP (real, 0, i); - - temp = simplify_rtx (SET_SRC (set)); - if (temp) - SET_SRC (set) = temp; - temp = simplify_rtx (SET_DEST (set)); - if (temp) - SET_DEST (set) = temp; - if (GET_CODE (SET_DEST (set)) == MEM) - { - temp = simplify_rtx (XEXP (SET_DEST (set), 0)); - if (temp) - XEXP (SET_DEST (set), 0) = temp; - } + rtx set = XVECEXP (patt, 0, i); + + if (repl) + set = simplify_replace_rtx (set, reg, repl); + if (reg2) + set = simplify_replace_rtx (set, reg2, repl2); + XVECEXP (patt, 0, i) = set; + /* Omit eh_frame info for any user-defined global regs. */ if (!REG_P (SET_SRC (set)) || !fixed_reg_p (REGNO (SET_SRC (set)))) RTX_FRAME_RELATED_P (set) = 1; } } + else + gcc_unreachable (); RTX_FRAME_RELATED_P (insn) = 1; - add_reg_note (insn, REG_FRAME_RELATED_EXPR, real); + if (repl || reg2) + add_reg_note (insn, REG_FRAME_RELATED_EXPR, patt); return insn; } -- Alan Modra Australia Development Lab, IBM