https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118663

--- Comment #11 from Peter Bergner <bergner at gcc dot gnu.org> ---
(In reply to Peter Bergner from comment #10)
> Similarly for -O2 -m64 -mcpu={power6,power5,power4,...}, LRA goes into a
> infinite loop.
Adding a little info for Vlad.  The insn LRA is transforming is:

(insn 3 12 4 2 (set (reg/v:SD 118 [ src ])
        (reg:SD 120 [ src ])) "bug.i":4:1 583 {movsd_hardfloat}
     (expr_list:REG_DEAD (reg:SD 120 [ src ])
        (nil)))

...with pseudo 118 assigned to GPR 31 and pseudo 120 assigned to FPR 33. Pre
power7 does not have direct moves between the GPR and FPR regs, so we have to
copy it through memory.  Pre power7, we also do not have a 32-bit load/store to
copy the SDmode value out of the FPR reg, so we have to store it as a DDmode
value and then can load half of that back into a GPR using a 32-bit GPR load.

The change in behavior (for -O2 -m64 -mcpu=power6) occurs with this hunk:

@@ -4389,6 +4402,10 @@ curr_insn_transform (bool check_only_p)
       rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest;
       rld_mode = GET_MODE (rld);
       sec_mode = targetm.secondary_memory_needed_mode (rld_mode);
+      if (rld_mode != sec_mode
+         && (invalid_mode_reg_p (sec_mode, dest)
+             || invalid_mode_reg_p (sec_mode, src)))
+       sec_mode = rld_mode;
       new_reg = lra_create_new_reg (sec_mode, NULL_RTX, NO_REGS, NULL,
                                    "secondary");
       /* If the mode is changed, it should be wider.  */

With the test case, rld_mode is SDmode and our
secondary_memory_needed_mode(SDmode) returns DDmode for reasons described
above.  However, newly added code overrides our secondary_memory_needed_mode
and changes sec_mode back to SDmode which causes us to loop forever since LRA
doesn't make progress.

Reply via email to