poly_int: REGMODE_NATURAL_SIZE

This patch makes target-independent code that uses REGMODE_NATURAL_SIZE
treat it as a poly_int rather than a constant.

2018-01-03  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* combine.c (can_change_dest_mode): Handle polynomial
	REGMODE_NATURAL_SIZE.
	* expmed.c (store_bit_field_1): Likewise.
	* expr.c (store_constructor): Likewise.
	* emit-rtl.c (validate_subreg): Operate on polynomial mode sizes
	and polynomial REGMODE_NATURAL_SIZE.
	(gen_lowpart_common): Likewise.
	* reginfo.c (record_subregs_of_mode): Likewise.
	* rtlanal.c (read_modify_subreg_p): Likewise.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r256149
This commit is contained in:
Richard Sandiford 2018-01-03 07:17:33 +00:00 committed by Richard Sandiford
parent 07626e49a0
commit fad2288b4b
7 changed files with 69 additions and 32 deletions

View file

@ -1,3 +1,17 @@
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
REGMODE_NATURAL_SIZE.
* expmed.c (store_bit_field_1): Likewise.
* expr.c (store_constructor): Likewise.
* emit-rtl.c (validate_subreg): Operate on polynomial mode sizes
and polynomial REGMODE_NATURAL_SIZE.
(gen_lowpart_common): Likewise.
* reginfo.c (record_subregs_of_mode): Likewise.
* rtlanal.c (read_modify_subreg_p): Likewise.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>

View file

@ -2477,8 +2477,8 @@ can_change_dest_mode (rtx x, int added_sets, machine_mode mode)
/* Don't change between modes with different underlying register sizes,
since this could lead to invalid subregs. */
if (REGMODE_NATURAL_SIZE (mode)
!= REGMODE_NATURAL_SIZE (GET_MODE (x)))
if (maybe_ne (REGMODE_NATURAL_SIZE (mode),
REGMODE_NATURAL_SIZE (GET_MODE (x))))
return false;
regno = REGNO (x);

View file

@ -894,8 +894,13 @@ bool
validate_subreg (machine_mode omode, machine_mode imode,
const_rtx reg, poly_uint64 offset)
{
unsigned int isize = GET_MODE_SIZE (imode);
unsigned int osize = GET_MODE_SIZE (omode);
poly_uint64 isize = GET_MODE_SIZE (imode);
poly_uint64 osize = GET_MODE_SIZE (omode);
/* The sizes must be ordered, so that we know whether the subreg
is partial, paradoxical or complete. */
if (!ordered_p (isize, osize))
return false;
/* All subregs must be aligned. */
if (!multiple_p (offset, osize))
@ -905,7 +910,7 @@ validate_subreg (machine_mode omode, machine_mode imode,
if (maybe_ge (offset, isize))
return false;
unsigned int regsize = REGMODE_NATURAL_SIZE (imode);
poly_uint64 regsize = REGMODE_NATURAL_SIZE (imode);
/* ??? This should not be here. Temporarily continue to allow word_mode
subregs of anything. The most common offender is (subreg:SI (reg:DF)).
@ -915,7 +920,7 @@ validate_subreg (machine_mode omode, machine_mode imode,
;
/* ??? Similarly, e.g. with (subreg:DF (reg:TI)). Though store_bit_field
is the culprit here, and not the backends. */
else if (osize >= regsize && isize >= osize)
else if (known_ge (osize, regsize) && known_ge (isize, osize))
;
/* Allow component subregs of complex and vector. Though given the below
extraction rules, it's not always clear what that means. */
@ -934,7 +939,7 @@ validate_subreg (machine_mode omode, machine_mode imode,
(subreg:SI (reg:DF) 0) isn't. */
else if (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode))
{
if (! (isize == osize
if (! (known_eq (isize, osize)
/* LRA can use subreg to store a floating point value in
an integer mode. Although the floating point and the
integer modes need the same number of hard registers,
@ -946,7 +951,7 @@ validate_subreg (machine_mode omode, machine_mode imode,
}
/* Paradoxical subregs must have offset zero. */
if (osize > isize)
if (maybe_gt (osize, isize))
return known_eq (offset, 0U);
/* This is a normal subreg. Verify that the offset is representable. */
@ -966,6 +971,12 @@ validate_subreg (machine_mode omode, machine_mode imode,
return subreg_offset_representable_p (regno, imode, offset, omode);
}
/* The outer size must be ordered wrt the register size, otherwise
we wouldn't know at compile time how many registers the outer
mode occupies. */
if (!ordered_p (osize, regsize))
return false;
/* For pseudo registers, we want most of the same checks. Namely:
Assume that the pseudo register will be allocated to hard registers
@ -976,10 +987,12 @@ validate_subreg (machine_mode omode, machine_mode imode,
Given that we've already checked the mode and offset alignment,
we only have to check subblock subregs here. */
if (osize < regsize
if (maybe_lt (osize, regsize)
&& ! (lra_in_progress && (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode))))
{
poly_uint64 block_size = MIN (isize, regsize);
/* It is invalid for the target to pick a register size for a mode
that isn't ordered wrt to the size of that mode. */
poly_uint64 block_size = ordered_min (isize, regsize);
unsigned int start_reg;
poly_uint64 offset_within_reg;
if (!can_div_trunc_p (offset, block_size, &start_reg, &offset_within_reg)
@ -1518,39 +1531,43 @@ maybe_set_max_label_num (rtx_code_label *x)
rtx
gen_lowpart_common (machine_mode mode, rtx x)
{
int msize = GET_MODE_SIZE (mode);
int xsize;
poly_uint64 msize = GET_MODE_SIZE (mode);
machine_mode innermode;
/* Unfortunately, this routine doesn't take a parameter for the mode of X,
so we have to make one up. Yuk. */
innermode = GET_MODE (x);
if (CONST_INT_P (x)
&& msize * BITS_PER_UNIT <= HOST_BITS_PER_WIDE_INT)
&& known_le (msize * BITS_PER_UNIT,
(unsigned HOST_WIDE_INT) HOST_BITS_PER_WIDE_INT))
innermode = int_mode_for_size (HOST_BITS_PER_WIDE_INT, 0).require ();
else if (innermode == VOIDmode)
innermode = int_mode_for_size (HOST_BITS_PER_DOUBLE_INT, 0).require ();
xsize = GET_MODE_SIZE (innermode);
gcc_assert (innermode != VOIDmode && innermode != BLKmode);
if (innermode == mode)
return x;
/* The size of the outer and inner modes must be ordered. */
poly_uint64 xsize = GET_MODE_SIZE (innermode);
if (!ordered_p (msize, xsize))
return 0;
if (SCALAR_FLOAT_MODE_P (mode))
{
/* Don't allow paradoxical FLOAT_MODE subregs. */
if (msize > xsize)
if (maybe_gt (msize, xsize))
return 0;
}
else
{
/* MODE must occupy no more of the underlying registers than X. */
unsigned int regsize = REGMODE_NATURAL_SIZE (innermode);
unsigned int mregs = CEIL (msize, regsize);
unsigned int xregs = CEIL (xsize, regsize);
if (mregs > xregs)
poly_uint64 regsize = REGMODE_NATURAL_SIZE (innermode);
unsigned int mregs, xregs;
if (!can_div_away_from_zero_p (msize, regsize, &mregs)
|| !can_div_away_from_zero_p (xsize, regsize, &xregs)
|| mregs > xregs)
return 0;
}

View file

@ -779,7 +779,7 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum,
In the latter case, use subreg on the rhs side, not lhs. */
rtx sub;
HOST_WIDE_INT regnum;
HOST_WIDE_INT regsize = REGMODE_NATURAL_SIZE (GET_MODE (op0));
poly_uint64 regsize = REGMODE_NATURAL_SIZE (GET_MODE (op0));
if (known_eq (bitnum, 0U)
&& known_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0))))
{

View file

@ -6279,8 +6279,8 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
a constant. But if more than one register is involved,
this probably loses. */
else if (REG_P (target) && TREE_STATIC (exp)
&& (GET_MODE_SIZE (GET_MODE (target))
<= REGMODE_NATURAL_SIZE (GET_MODE (target))))
&& known_le (GET_MODE_SIZE (GET_MODE (target)),
REGMODE_NATURAL_SIZE (GET_MODE (target))))
{
emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
cleared = 1;

View file

@ -1294,10 +1294,14 @@ record_subregs_of_mode (rtx subreg, bool partial_def)
subregs will be invalid.
This relies on the fact that we've already been passed
SUBREG with PARTIAL_DEF set to false. */
unsigned int size = MAX (REGMODE_NATURAL_SIZE (shape.inner_mode),
GET_MODE_SIZE (shape.outer_mode));
gcc_checking_assert (size < GET_MODE_SIZE (shape.inner_mode));
SUBREG with PARTIAL_DEF set to false.
The size of the outer mode must ordered wrt the size of the
inner mode's registers, since otherwise we wouldn't know at
compile time how many registers the outer mode occupies. */
poly_uint64 size = MAX (REGMODE_NATURAL_SIZE (shape.inner_mode),
GET_MODE_SIZE (shape.outer_mode));
gcc_checking_assert (known_lt (size, GET_MODE_SIZE (shape.inner_mode)));
if (known_ge (shape.offset, size))
shape.offset -= size;
else

View file

@ -1395,13 +1395,15 @@ modified_in_p (const_rtx x, const_rtx insn)
bool
read_modify_subreg_p (const_rtx x)
{
unsigned int isize, osize;
if (GET_CODE (x) != SUBREG)
return false;
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
return isize > osize
&& isize > REGMODE_NATURAL_SIZE (GET_MODE (SUBREG_REG (x)));
poly_uint64 isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
poly_uint64 osize = GET_MODE_SIZE (GET_MODE (x));
poly_uint64 regsize = REGMODE_NATURAL_SIZE (GET_MODE (SUBREG_REG (x)));
/* The inner and outer modes of a subreg must be ordered, so that we
can tell whether they're paradoxical or partial. */
gcc_checking_assert (ordered_p (isize, osize));
return (maybe_gt (isize, osize) && maybe_gt (isize, regsize));
}
/* Helper function for set_of. */