This is PR68973 part 1, the fix for the regression of g++.dg/pr67211.C on powerpc64-linux -mcpu=power7, which turns out to be a reload problem.
Due to uses elsewhere in vsx instructions, reload chooses to put psuedo 185 in fr31, which can't be used as a base register in the following: (set (reg/f:DI 178) (mem/f:DI (pre_inc:DI (reg/f:DI 185)))) So find_reloads_address decides that the (pre_inc:DI (reg:DI 63)) needs reloading, and pushes a reload on the entire address expression. This is unfortunate because the rs6000 backend reload hooks don't look inside a pre_inc and thus don't arrange a secondary reload. Nor does the generic SECONDARY_MEMORY_NEEDED handling, which is only prepared to handle regs or subregs. So reload doesn't allocate the stack temp needed to copy between fprs and gprs on power7. Now it turns out that if find_reloads_address instead pushed a reload of just the (reg:DI 63), then SECONDARY_MEMORY_NEEDED would get a chance to do something. Furthermore, there is existing code in find_reloads_address to do just that for pre_inc, but only enabled for psuedos that don't get a hard reg. The following patch extends this to invalid hard regs. I could have implemented a fix in the rs6000 backend, but it seems likely that other targets may run into this problem. Bootstrapped and regression tested powerpc64le-linux and x86_64-linux. OK to apply? PR target/68973 * reloads.c (find_reloads_address_1): For pre/post-inc/dec with an invalid hard reg, reload just the reg not the entire pre/post-inc/dec address expression. diff --git a/gcc/reload.c b/gcc/reload.c index 6196e63..06426d9 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -5834,14 +5834,16 @@ find_reloads_address_1 (machine_mode mode, addr_space_t as, ? XEXP (x, 0) : reg_equiv_mem (regno)); enum insn_code icode = optab_handler (add_optab, GET_MODE (x)); - if (insn && NONJUMP_INSN_P (insn) && equiv - && memory_operand (equiv, GET_MODE (equiv)) + if (insn && NONJUMP_INSN_P (insn) #if HAVE_cc0 && ! sets_cc0_p (PATTERN (insn)) #endif - && ! (icode != CODE_FOR_nothing - && insn_operand_matches (icode, 0, equiv) - && insn_operand_matches (icode, 1, equiv)) + && (regno < FIRST_PSEUDO_REGISTER + || (equiv + && memory_operand (equiv, GET_MODE (equiv)) + && ! (icode != CODE_FOR_nothing + && insn_operand_matches (icode, 0, equiv) + && insn_operand_matches (icode, 1, equiv)))) /* Using RELOAD_OTHER means we emit this and the reload we made earlier in the wrong order. */ && !reloaded_inner_of_autoinc) -- Alan Modra Australia Development Lab, IBM