------- 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