Hi, The ada bootstrap failure reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72827 occurs because of a latent bug in the powerpc back end. The immediate cause is dead store elimination removing two stores relative to the frame pointer that are not dead; however, DSE is tricked into doing this because we have temporarily adjusted the frame pointer prior to performing the loads. DSE relies on the frame pointer remaining constant to be able to infer stack stores that are dead.
The code responsible is in rs6000_split_multireg_move, which wants to form new addresses after reload/lra to use for the individual stores, but has to use only existing hard registers. Currently that code always modifies the register holding the base pointer, which is a bad idea when the base pointer is a register expected to remain fixed. This patch identifies those situations and causes the index register to be modified instead. (If the index register number is zero, indicating constant zero, we fall through to the existing code; it's ok to add zero to the fixed registers...) The diffs are a little munged due to indentation and line length adjustments; the change is just to add the code block labeled with commentary. We might someday want to rip up this logic and instead change secondary reload to allocate an extra register to be used during expansion. But to clear the bootstrap failure, a simple patch like this seems best. Bootstrapped and tested on powerpc64le-unknown-linux-gnu with the usual languages plus ada, with no regressions. Gnattools now builds properly during bootstrap. Is this ok for trunk, and eventually for backport to the 5 and 6 branches? Thanks, Bill 2016-08-30 Bill Schmidt <wschm...@linux.vnet.ibm.com> PR target/72827 * config/rs6000/rs6000.c (rs6000_split_multireg_move): Never modify the frame pointer or the stack pointer; instead, use the index register for temporary address generation. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 239871) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -24506,15 +24506,31 @@ rs6000_split_multireg_move (rtx dst, rtx src) && REG_P (basereg) && REG_P (offsetreg) && REGNO (basereg) != REGNO (offsetreg)); - if (REGNO (basereg) == 0) + /* We mustn't modify the stack pointer or frame pointer + as this will confuse dead store elimination. */ + if ((REGNO (basereg) == STACK_POINTER_REGNUM + || REGNO (basereg) == HARD_FRAME_POINTER_REGNUM) + && REGNO (offsetreg) != 0) { - rtx tmp = offsetreg; - offsetreg = basereg; - basereg = tmp; + emit_insn (gen_add3_insn (offsetreg, basereg, + offsetreg)); + restore_basereg = gen_sub3_insn (offsetreg, offsetreg, + basereg); + dst = replace_equiv_address (dst, offsetreg); } - emit_insn (gen_add3_insn (basereg, basereg, offsetreg)); - restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg); - dst = replace_equiv_address (dst, basereg); + else + { + if (REGNO (basereg) == 0) + { + rtx tmp = offsetreg; + offsetreg = basereg; + basereg = tmp; + } + emit_insn (gen_add3_insn (basereg, basereg, offsetreg)); + restore_basereg = gen_sub3_insn (basereg, basereg, + offsetreg); + dst = replace_equiv_address (dst, basereg); + } } } else if (GET_CODE (XEXP (dst, 0)) != LO_SUM)