------- Additional Comments From uweigand at gcc dot gnu dot org  2004-10-25 15:54 
-------
David Edelsohn wrote:

>One could view this problem as reload not obeying CANNOT_CHANGE_MODE_CLASS
>because it should not try to spill just the SImode SUBREG instead of creating a
>DImode temporary on the stack.  It needs to spill the entire result, not just
>the live portion.

Exactly, and that's what reload tries to do, at least initially.  Note that
push_reload checks CANNOT_CHANGE_MODE_CLASS, and correctly decides it needs
to reload in DImode.  That's why in the debug_reload output you see DImode
as the mode to perform the reload in.

Now, I haven't actually debugged this live; but from looking at the source
code what I assume is going wrong is the following:

Right at the end of reload, in gen_reload, there's this hunk of code:

  /* If IN is a paradoxical SUBREG, remove it and try to put the
     opposite SUBREG on OUT.  Likewise for a paradoxical SUBREG on OUT.  */
[snip]
  else if (GET_CODE (out) == SUBREG
           && (GET_MODE_SIZE (GET_MODE (out))
               > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
           && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (out)), in)) != 0)
    out = SUBREG_REG (out), in = tem;

This is most likely where the DImode reload is replaced by the SImode one.

Now, this should not happen if the resulting SUBREG on the input side
gets invalid, as it does in the current situation.  

Here, gen_lowpart_common calls simplify_gen_subreg which calls
simplify_subreg.  This last function has code to verify using
CANNOT_CHANGE_MODE_CLASS that no invalid mode change is being encoded
into a SUBREG.  However, in *simplify_gen_subreg*, that decision is
subsequently simply ignored:

  newx = simplify_subreg (outermode, op, innermode, byte);
  if (newx)
    return newx;

  if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode)
    return NULL_RTX;

  return gen_rtx_SUBREG (outermode, op, byte);

Note how the SUBREG is generated anyway.  I'm not quite sure what the
point of this code is; but I'd suggest somewhere here is the place that
needs to get fixed ...


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15286

Reply via email to