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.

Reply via email to