Commit c3266d10 by Richard Sandiford Committed by Richard Sandiford

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
parent fad2288b
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@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>
* combine.c (can_change_dest_mode): Handle polynomial * combine.c (can_change_dest_mode): Handle polynomial
REGMODE_NATURAL_SIZE. REGMODE_NATURAL_SIZE.
* expmed.c (store_bit_field_1): Likewise. * expmed.c (store_bit_field_1): Likewise.
...@@ -3694,8 +3694,9 @@ subreg_get_info (unsigned int xregno, machine_mode xmode, ...@@ -3694,8 +3694,9 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
gcc_assert (xregno < FIRST_PSEUDO_REGISTER); gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
unsigned int xsize = GET_MODE_SIZE (xmode); poly_uint64 xsize = GET_MODE_SIZE (xmode);
unsigned int ysize = GET_MODE_SIZE (ymode); poly_uint64 ysize = GET_MODE_SIZE (ymode);
bool rknown = false; bool rknown = false;
/* If the register representation of a non-scalar mode has holes in it, /* 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, ...@@ -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 /* As a consequence, we must be dealing with a constant number of
scalars, and thus a constant offset. */ scalars, and thus a constant offset. */
HOST_WIDE_INT coffset = offset.to_constant (); HOST_WIDE_INT coffset = offset.to_constant ();
HOST_WIDE_INT cysize = ysize.to_constant ();
nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode); nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
unsigned int nunits = GET_MODE_NUNITS (xmode); unsigned int nunits = GET_MODE_NUNITS (xmode);
scalar_mode xmode_unit = GET_MODE_INNER (xmode); scalar_mode xmode_unit = GET_MODE_INNER (xmode);
...@@ -3727,7 +3729,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode, ...@@ -3727,7 +3729,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
of each unit. */ of each unit. */
if ((coffset / GET_MODE_SIZE (xmode_unit) + 1 < nunits) if ((coffset / GET_MODE_SIZE (xmode_unit) + 1 < nunits)
&& (coffset / GET_MODE_SIZE (xmode_unit) && (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; info->representable_p = false;
rknown = true; rknown = true;
...@@ -3738,8 +3740,12 @@ subreg_get_info (unsigned int xregno, machine_mode xmode, ...@@ -3738,8 +3740,12 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
nregs_ymode = hard_regno_nregs (xregno, ymode); 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. */ /* 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; info->representable_p = true;
/* If this is a big endian paradoxical subreg, which uses more /* If this is a big endian paradoxical subreg, which uses more
...@@ -3761,20 +3767,19 @@ subreg_get_info (unsigned int xregno, machine_mode xmode, ...@@ -3761,20 +3767,19 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
/* If registers store different numbers of bits in the different /* If registers store different numbers of bits in the different
modes, we cannot generally form this subreg. */ modes, we cannot generally form this subreg. */
poly_uint64 regsize_xmode, regsize_ymode;
if (!HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode) if (!HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode)
&& !HARD_REGNO_NREGS_HAS_PADDING (xregno, ymode) && !HARD_REGNO_NREGS_HAS_PADDING (xregno, ymode)
&& (xsize % nregs_xmode) == 0 && multiple_p (xsize, nregs_xmode, &regsize_xmode)
&& (ysize % nregs_ymode) == 0) && multiple_p (ysize, nregs_ymode, &regsize_ymode))
{ {
int regsize_xmode = xsize / nregs_xmode;
int regsize_ymode = ysize / nregs_ymode;
if (!rknown if (!rknown
&& ((nregs_ymode > 1 && regsize_xmode > regsize_ymode) && ((nregs_ymode > 1 && maybe_gt (regsize_xmode, regsize_ymode))
|| (nregs_xmode > 1 && regsize_ymode > regsize_xmode))) || (nregs_xmode > 1 && maybe_gt (regsize_ymode, regsize_xmode))))
{ {
info->representable_p = false; info->representable_p = false;
info->nregs = CEIL (ysize, regsize_xmode); if (!can_div_away_from_zero_p (ysize, regsize_xmode, &info->nregs)
if (!can_div_trunc_p (offset, regsize_xmode, &info->offset)) || !can_div_trunc_p (offset, regsize_xmode, &info->offset))
/* Checked by validate_subreg. We must know at compile time /* Checked by validate_subreg. We must know at compile time
which inner registers are being accessed. */ which inner registers are being accessed. */
gcc_unreachable (); gcc_unreachable ();
...@@ -3800,7 +3805,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode, ...@@ -3800,7 +3805,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
HOST_WIDE_INT count; HOST_WIDE_INT count;
if (!rknown if (!rknown
&& WORDS_BIG_ENDIAN == REG_WORDS_BIG_ENDIAN && WORDS_BIG_ENDIAN == REG_WORDS_BIG_ENDIAN
&& regsize_xmode == regsize_ymode && known_eq (regsize_xmode, regsize_ymode)
&& constant_multiple_p (offset, regsize_ymode, &count)) && constant_multiple_p (offset, regsize_ymode, &count))
{ {
info->representable_p = true; info->representable_p = true;
...@@ -3837,8 +3842,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode, ...@@ -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. be exact, otherwise we don't know how to verify the constraint.
These conditions may be relaxed but subreg_regno_offset would These conditions may be relaxed but subreg_regno_offset would
need to be redesigned. */ need to be redesigned. */
gcc_assert ((xsize % num_blocks) == 0); poly_uint64 bytes_per_block = exact_div (xsize, num_blocks);
poly_uint64 bytes_per_block = xsize / num_blocks;
/* Get the number of the first block that contains the subreg and the byte /* Get the number of the first block that contains the subreg and the byte
offset of the subreg from the start of that block. */ offset of the subreg from the start of that block. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment