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

Reply via email to