H.J. Lu wrote: > > find_replacement never checks subreg: > > > > Breakpoint 3, find_replacement (loc=3D0x7ffff068ab00) > > =A0 =A0at /export/gnu/import/git/gcc-x32/gcc/reload.c:6411 > > 6411 =A0 =A0 =A0 =A0 =A0if (reloadreg && r->where =3D=3D loc) > > (reg:DI 0 ax) > > (reg/v/f:DI 182 [ b ]) > > (gdb) call debug_rtx (*loc) > > (subreg:SI (reg/v/f:DI 182 [ b ]) 0) > > (gdb) > > > > This seems to work. Does it make any senses?
Ah, I see. This was supposed to be handled via the SUBREG_LOC member of the replacement struct. Unfortunately, it turns out that this is no longer reliably set these days ... At first I was concerned that this might also cause problems at the other location where replacements are processed, subst_reloads. However, it turns out that code in subst_reloads is dead these days anyway, as the reloadreg is *always* a REG, and never a SUBREG. Once that code (and similar code in find_replacement that tries to handle SUBREG reloadregs) is removed, the only remaining user of the SUBREG_LOC field is actually find_replacement. But here we're doing a recursive descent through an RTL anyway, so we always know we're replacing inside a SUBREG. This makes the whole SUBREG_LOC field obsolete. The patch below implements those changes (untested so far). Can you verify that this works for you as well? Thanks, Ulrich ChangeLog: * reload.c (struct replacement): Remove SUBREG_LOC member. (push_reload): Do not set it. (push_replacement): Likewise. (subst_reload): Remove dead code. (copy_replacements): Remove assertion. (copy_replacements_1): Do not handle SUBREG_LOC. (move_replacements): Likewise. (find_replacement): Remove dead code. Detect subregs via recursive descent instead of via SUBREG_LOC. Index: gcc/reload.c =================================================================== *** gcc/reload.c (revision 175580) --- gcc/reload.c (working copy) *************** static int replace_reloads; *** 158,165 **** struct replacement { rtx *where; /* Location to store in */ - rtx *subreg_loc; /* Location of SUBREG if WHERE is inside - a SUBREG; 0 otherwise. */ int what; /* which reload this is for */ enum machine_mode mode; /* mode it must have */ }; --- 158,163 ---- *************** push_reload (rtx in, rtx out, rtx *inloc *** 1496,1502 **** { struct replacement *r = &replacements[n_replacements++]; r->what = i; - r->subreg_loc = in_subreg_loc; r->where = inloc; r->mode = inmode; } --- 1494,1499 ---- *************** push_reload (rtx in, rtx out, rtx *inloc *** 1505,1511 **** struct replacement *r = &replacements[n_replacements++]; r->what = i; r->where = outloc; - r->subreg_loc = out_subreg_loc; r->mode = outmode; } } --- 1502,1507 ---- *************** push_replacement (rtx *loc, int reloadnu *** 1634,1640 **** struct replacement *r = &replacements[n_replacements++]; r->what = reloadnum; r->where = loc; - r->subreg_loc = 0; r->mode = mode; } } --- 1630,1635 ---- *************** subst_reloads (rtx insn) *** 6287,6319 **** if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode) reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode); ! /* If we are putting this into a SUBREG and RELOADREG is a ! SUBREG, we would be making nested SUBREGs, so we have to fix ! this up. Note that r->where == &SUBREG_REG (*r->subreg_loc). */ ! ! if (r->subreg_loc != 0 && GET_CODE (reloadreg) == SUBREG) ! { ! if (GET_MODE (*r->subreg_loc) ! == GET_MODE (SUBREG_REG (reloadreg))) ! *r->subreg_loc = SUBREG_REG (reloadreg); ! else ! { ! int final_offset = ! SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg); ! ! /* When working with SUBREGs the rule is that the byte ! offset must be a multiple of the SUBREG's mode. */ ! final_offset = (final_offset / ! GET_MODE_SIZE (GET_MODE (*r->subreg_loc))); ! final_offset = (final_offset * ! GET_MODE_SIZE (GET_MODE (*r->subreg_loc))); ! ! *r->where = SUBREG_REG (reloadreg); ! SUBREG_BYTE (*r->subreg_loc) = final_offset; ! } ! } ! else ! *r->where = reloadreg; } /* If reload got no reg and isn't optional, something's wrong. */ else --- 6282,6288 ---- if (GET_MODE (reloadreg) != r->mode && r->mode != VOIDmode) reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode); ! *r->where = reloadreg; } /* If reload got no reg and isn't optional, something's wrong. */ else *************** subst_reloads (rtx insn) *** 6327,6336 **** void copy_replacements (rtx x, rtx y) { - /* We can't support X being a SUBREG because we might then need to know its - location if something inside it was replaced. */ - gcc_assert (GET_CODE (x) != SUBREG); - copy_replacements_1 (&x, &y, n_replacements); } --- 6296,6301 ---- *************** copy_replacements_1 (rtx *px, rtx *py, i *** 6344,6367 **** const char *fmt; for (j = 0; j < orig_replacements; j++) ! { ! if (replacements[j].subreg_loc == px) ! { ! r = &replacements[n_replacements++]; ! r->where = replacements[j].where; ! r->subreg_loc = py; ! r->what = replacements[j].what; ! r->mode = replacements[j].mode; ! } ! else if (replacements[j].where == px) ! { ! r = &replacements[n_replacements++]; ! r->where = py; ! r->subreg_loc = 0; ! r->what = replacements[j].what; ! r->mode = replacements[j].mode; ! } ! } x = *px; y = *py; --- 6309,6321 ---- const char *fmt; for (j = 0; j < orig_replacements; j++) ! if (replacements[j].where == px) ! { ! r = &replacements[n_replacements++]; ! r->where = py; ! r->what = replacements[j].what; ! r->mode = replacements[j].mode; ! } x = *px; y = *py; *************** move_replacements (rtx *x, rtx *y) *** 6387,6399 **** int i; for (i = 0; i < n_replacements; i++) ! if (replacements[i].subreg_loc == x) ! replacements[i].subreg_loc = y; ! else if (replacements[i].where == x) ! { ! replacements[i].where = y; ! replacements[i].subreg_loc = 0; ! } } /* If LOC was scheduled to be replaced by something, return the replacement. --- 6341,6348 ---- int i; for (i = 0; i < n_replacements; i++) ! if (replacements[i].where == x) ! replacements[i].where = y; } /* If LOC was scheduled to be replaced by something, return the replacement. *************** find_replacement (rtx *loc) *** 6415,6446 **** return reloadreg; } ! else if (reloadreg && r->subreg_loc == loc) { ! /* RELOADREG must be either a REG or a SUBREG. ! ! ??? Is it actually still ever a SUBREG? If so, why? */ ! ! if (REG_P (reloadreg)) ! return gen_rtx_REG (GET_MODE (*loc), ! (REGNO (reloadreg) + ! subreg_regno_offset (REGNO (SUBREG_REG (*loc)), GET_MODE (SUBREG_REG (*loc)), SUBREG_BYTE (*loc), GET_MODE (*loc)))); - else if (GET_MODE (reloadreg) == GET_MODE (*loc)) - return reloadreg; - else - { - int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc); - - /* When working with SUBREGs the rule is that the byte - offset must be a multiple of the SUBREG's mode. */ - final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc))); - final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc))); - return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg), - final_offset); - } } } --- 6364,6378 ---- return reloadreg; } ! else if (reloadreg && GET_CODE (*loc) == SUBREG ! && r->where == &SUBREG_REG (*loc)) { ! return gen_rtx_REG (GET_MODE (*loc), ! (REGNO (reloadreg) ! + subreg_regno_offset (REGNO (SUBREG_REG (*loc)), GET_MODE (SUBREG_REG (*loc)), SUBREG_BYTE (*loc), GET_MODE (*loc)))); } } -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE ulrich.weig...@de.ibm.com