PATCH [10/n]: Prepare x32: PR rtl-optimization/49114: Reload failed to handle (set reg:X (plus:X (subreg:X (reg:Y) 0) (const

H.J. Lu hjl.tools@gmail.com
Tue Jun 28 15:19:00 GMT 2011


On Tue, Jun 28, 2011 at 7:47 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Tue, Jun 28, 2011 at 7:24 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
>> 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.Weigand@de.ibm.com
>>
>
> 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.
>
> (gdb) bt
> #0  fancy_abort (file=0xe7d920 "/export/gnu/import/git/gcc-x32/gcc/rtlanal.c",
>    line=3235, function=0xe7d8c0 "subreg_get_info")
>    at /export/gnu/import/git/gcc-x32/gcc/diagnostic.c:892
> #1  0x0000000000888c8e in subreg_get_info (xregno=<optimized out>,
>    xmode=<optimized out>, offset=0, ymode=<optimized out>,
>    info=<optimized out>) at /export/gnu/import/git/gcc-x32/gcc/rtlanal.c:3235
> #2  0x0000000000888d4c in subreg_regno_offset (xregno=<optimized out>,
>    xmode=<optimized out>, offset=<optimized out>, ymode=<optimized out>)
>    at /export/gnu/import/git/gcc-x32/gcc/rtlanal.c:3387
> #3  0x0000000000868546 in find_replacement (loc=0x7ffff063ee80)
>    at /export/gnu/import/git/gcc-x32/gcc/reload.c:6372
> #4  0x00000000008685b8 in find_replacement (loc=0x7ffff063ba48)
>    at /export/gnu/import/git/gcc-x32/gcc/reload.c:6385
> #5  0x0000000000877182 in gen_reload (out=0x7ffff062be80, in=0x7ffff063ba40,
>    opnum=0, type=RELOAD_FOR_OPERAND_ADDRESS)
>    at /export/gnu/import/git/gcc-x32/gcc/reload1.c:8599
>
> since subreg_regno_offset only works on hard registers.
>

+         int offset;
+
+         if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
+           reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
+
+         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.

-- 
H.J.



More information about the Gcc-patches mailing list