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

Reply via email to