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:
parent
07626e49a0
commit
fad2288b4b
7 changed files with 69 additions and 32 deletions
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue