https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94254
--- Comment #4 from rsandifo at gcc dot gnu.org <rsandifo at gcc dot gnu.org>
---
The cycling comes from reloading:
(insn 7 6 8 2 (set (reg:SD 122 [ a32 ])
(mem/c:SD (reg/f:DI 120) [1 a32+0 S4 A32]))
"gcc/testsuite/gcc.target/powerpc/pr39902-2.c":15:13 516 {movsd_hardfloat}
(expr_list:REG_DEAD (reg/f:DI 120)
(nil)))
r122 is assigned an FPR, and the power6 pattern doesn't provide
any alternatives that load from memory into FPRs, so we convert
this into a secondary memory reload.
Doing that for SDmode memory would cycle, but the rs6000 port has:
/* Implement TARGET_SECONDARY_RELOAD_NEEDED_MODE. For SDmode values we
need to use DDmode, in all other cases we can use the same mode. */
static machine_mode
rs6000_secondary_memory_needed_mode (machine_mode mode)
{
if (lra_in_progress && mode == SDmode)
return DDmode;
return mode;
}
which says that the move should happen in DDmode instead.
This means that the eventual FPR reload will happen in DDmode
rather than SDmode.
The problem is that rs6000_can_change_mode_class doesn't allow
FPRs to change from SDmode to DDmode:
if (from_size < 8 || to_size < 8)
return false;
So there seems to be a contradiction here: secondary memory
reloads for FPRs have to happen in DDmode rather than SDmode,
but FPRs aren't allowed to change to DDmode from SDmode.
Previously this worked because LRA ignored
rs6000_can_change_mode_class and changed the mode of the
FPR regardless. I guess that must have been the right
thing to do in context, but it would be good to pin down
exactly why the SD->DD mode change is OK for rs6000 in the
specific context of secondary memory reloads but not otherwise.