H.J. Lu wrote:
> > it doesn't work;
> >
> > allocation.f: In function 'allocation':
> > allocation.f:1048:0: internal compiler error: in subreg_get_info, at
> > rtlanal.c:3235
> > Please submit a full bug report,
> > with preprocessed source if appropriate.
> > See <http://gcc.gnu.org/bugs.html> for instructions.

> > since subreg_regno_offset only works on hard registers.

Hmm, OK.  That look like another latent bug in the original code ...

> +         if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
> +           reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));

(As an aside, this is wrong; it's already wrong in the place where you
copied it from.  This should now use reload_adjust_reg_for_mode just
like subst_reload does.)

> +
> +         if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
> +             && GET_MODE_SIZE (Pmode) > GET_MODE_SIZE (ptr_mode))
> +           {
> +             offset = GET_MODE_SIZE (Pmode) - GET_MODE_SIZE (ptr_mode);
> +             if (! BYTES_BIG_ENDIAN)
> +               offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
> +             else if (! WORDS_BIG_ENDIAN)
> +               offset %= UNITS_PER_WORD;
> +           }
> +          else
> +            offset = 0;
> +
> +         return gen_rtx_SUBREG (ptr_mode, reloadreg, offset);
> 
> works for me.

This doesn't seem correct either, it completely ignores the SUBREG_BYTE
of the original SUBREG ...   Also, I don't quite see why this should
have anything special for Pmode / ptr_mode.

It seems simplest to just use simplify_gen_subreg here.  Can you try
the following version?

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.  Use reload_adjust_reg_for_mode.
        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)
*** 6411,6446 ****
        if (reloadreg && r->where == loc)
        {
          if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
!           reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
  
          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);
!           }
        }
      }
  
--- 6360,6378 ----
        if (reloadreg && r->where == loc)
        {
          if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
!           reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
  
          return reloadreg;
        }
!       else if (reloadreg && GET_CODE (*loc) == SUBREG
!              && r->where == &SUBREG_REG (*loc))
        {
!         if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
!           reloadreg = reload_adjust_reg_for_mode (reloadreg, r->mode);
  
!         return simplify_gen_subreg (GET_MODE (*loc), reloadreg,
!                                     GET_MODE (SUBREG_REG (*loc)),
!                                     SUBREG_BYTE (*loc));
        }
      }
  



-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  ulrich.weig...@de.ibm.com

Reply via email to