poly_int: subreg_get_info
This patch makes subreg_get_info handle polynomial sizes. 2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * rtlanal.c (subreg_get_info): Handle polynomial mode sizes. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r256150
This commit is contained in:
parent
fad2288b4b
commit
c3266d10a4
2 changed files with 25 additions and 15 deletions
|
@ -1,3 +1,9 @@
|
|||
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
||||
* rtlanal.c (subreg_get_info): Handle polynomial mode sizes.
|
||||
|
||||
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
|
|
@ -3694,8 +3694,9 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
|
|||
|
||||
gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
|
||||
|
||||
unsigned int xsize = GET_MODE_SIZE (xmode);
|
||||
unsigned int ysize = GET_MODE_SIZE (ymode);
|
||||
poly_uint64 xsize = GET_MODE_SIZE (xmode);
|
||||
poly_uint64 ysize = GET_MODE_SIZE (ymode);
|
||||
|
||||
bool rknown = false;
|
||||
|
||||
/* If the register representation of a non-scalar mode has holes in it,
|
||||
|
@ -3707,6 +3708,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
|
|||
/* As a consequence, we must be dealing with a constant number of
|
||||
scalars, and thus a constant offset. */
|
||||
HOST_WIDE_INT coffset = offset.to_constant ();
|
||||
HOST_WIDE_INT cysize = ysize.to_constant ();
|
||||
nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
|
||||
unsigned int nunits = GET_MODE_NUNITS (xmode);
|
||||
scalar_mode xmode_unit = GET_MODE_INNER (xmode);
|
||||
|
@ -3727,7 +3729,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
|
|||
of each unit. */
|
||||
if ((coffset / GET_MODE_SIZE (xmode_unit) + 1 < nunits)
|
||||
&& (coffset / GET_MODE_SIZE (xmode_unit)
|
||||
!= ((coffset + ysize - 1) / GET_MODE_SIZE (xmode_unit))))
|
||||
!= ((coffset + cysize - 1) / GET_MODE_SIZE (xmode_unit))))
|
||||
{
|
||||
info->representable_p = false;
|
||||
rknown = true;
|
||||
|
@ -3738,8 +3740,12 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
|
|||
|
||||
nregs_ymode = hard_regno_nregs (xregno, ymode);
|
||||
|
||||
/* Subreg sizes must be ordered, so that we can tell whether they are
|
||||
partial, paradoxical or complete. */
|
||||
gcc_checking_assert (ordered_p (xsize, ysize));
|
||||
|
||||
/* Paradoxical subregs are otherwise valid. */
|
||||
if (!rknown && known_eq (offset, 0U) && ysize > xsize)
|
||||
if (!rknown && known_eq (offset, 0U) && maybe_gt (ysize, xsize))
|
||||
{
|
||||
info->representable_p = true;
|
||||
/* If this is a big endian paradoxical subreg, which uses more
|
||||
|
@ -3761,20 +3767,19 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
|
|||
|
||||
/* If registers store different numbers of bits in the different
|
||||
modes, we cannot generally form this subreg. */
|
||||
poly_uint64 regsize_xmode, regsize_ymode;
|
||||
if (!HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode)
|
||||
&& !HARD_REGNO_NREGS_HAS_PADDING (xregno, ymode)
|
||||
&& (xsize % nregs_xmode) == 0
|
||||
&& (ysize % nregs_ymode) == 0)
|
||||
&& multiple_p (xsize, nregs_xmode, ®size_xmode)
|
||||
&& multiple_p (ysize, nregs_ymode, ®size_ymode))
|
||||
{
|
||||
int regsize_xmode = xsize / nregs_xmode;
|
||||
int regsize_ymode = ysize / nregs_ymode;
|
||||
if (!rknown
|
||||
&& ((nregs_ymode > 1 && regsize_xmode > regsize_ymode)
|
||||
|| (nregs_xmode > 1 && regsize_ymode > regsize_xmode)))
|
||||
&& ((nregs_ymode > 1 && maybe_gt (regsize_xmode, regsize_ymode))
|
||||
|| (nregs_xmode > 1 && maybe_gt (regsize_ymode, regsize_xmode))))
|
||||
{
|
||||
info->representable_p = false;
|
||||
info->nregs = CEIL (ysize, regsize_xmode);
|
||||
if (!can_div_trunc_p (offset, regsize_xmode, &info->offset))
|
||||
if (!can_div_away_from_zero_p (ysize, regsize_xmode, &info->nregs)
|
||||
|| !can_div_trunc_p (offset, regsize_xmode, &info->offset))
|
||||
/* Checked by validate_subreg. We must know at compile time
|
||||
which inner registers are being accessed. */
|
||||
gcc_unreachable ();
|
||||
|
@ -3800,7 +3805,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
|
|||
HOST_WIDE_INT count;
|
||||
if (!rknown
|
||||
&& WORDS_BIG_ENDIAN == REG_WORDS_BIG_ENDIAN
|
||||
&& regsize_xmode == regsize_ymode
|
||||
&& known_eq (regsize_xmode, regsize_ymode)
|
||||
&& constant_multiple_p (offset, regsize_ymode, &count))
|
||||
{
|
||||
info->representable_p = true;
|
||||
|
@ -3837,8 +3842,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
|
|||
be exact, otherwise we don't know how to verify the constraint.
|
||||
These conditions may be relaxed but subreg_regno_offset would
|
||||
need to be redesigned. */
|
||||
gcc_assert ((xsize % num_blocks) == 0);
|
||||
poly_uint64 bytes_per_block = xsize / num_blocks;
|
||||
poly_uint64 bytes_per_block = exact_div (xsize, num_blocks);
|
||||
|
||||
/* Get the number of the first block that contains the subreg and the byte
|
||||
offset of the subreg from the start of that block. */
|
||||
|
|
Loading…
Add table
Reference in a new issue