===================================================================
@@ -2474,8 +2474,8 @@ can_change_dest_mode (rtx x, int added_s
/* 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 (may_ne (REGMODE_NATURAL_SIZE (mode),
+ REGMODE_NATURAL_SIZE (GET_MODE (x))))
return false;
regno = REGNO (x);
===================================================================
@@ -778,7 +778,7 @@ store_bit_field_1 (rtx str_rtx, poly_uin
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_zero (bitnum)
&& must_eq (bitsize, GET_MODE_BITSIZE (GET_MODE (op0))))
{
===================================================================
@@ -6204,8 +6204,8 @@ store_constructor (tree exp, rtx target,
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))))
+ && must_le (GET_MODE_SIZE (GET_MODE (target)),
+ REGMODE_NATURAL_SIZE (GET_MODE (target))))
{
emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
cleared = 1;
===================================================================
@@ -924,8 +924,13 @@ gen_tmp_stack_mem (machine_mode mode, rt
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))
@@ -935,7 +940,7 @@ validate_subreg (machine_mode omode, mac
if (may_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)).
@@ -945,7 +950,7 @@ validate_subreg (machine_mode omode, mac
;
/* ??? 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 (must_ge (osize, regsize) && must_ge (isize, osize))
;
/* Allow component subregs of complex and vector. Though given the below
extraction rules, it's not always clear what that means. */
@@ -964,7 +969,7 @@ validate_subreg (machine_mode omode, mac
(subreg:SI (reg:DF) 0) isn't. */
else if (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode))
{
- if (! (isize == osize
+ if (! (must_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,
@@ -976,7 +981,7 @@ validate_subreg (machine_mode omode, mac
}
/* Paradoxical subregs must have offset zero. */
- if (osize > isize)
+ if (may_gt (osize, isize))
return known_zero (offset);
/* This is a normal subreg. Verify that the offset is representable. */
@@ -996,6 +1001,12 @@ validate_subreg (machine_mode omode, mac
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
@@ -1006,10 +1017,12 @@ validate_subreg (machine_mode omode, mac
Given that we've already checked the mode and offset alignment,
we only have to check subblock subregs here. */
- if (osize < regsize
+ if (may_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)
@@ -1548,39 +1561,43 @@ maybe_set_max_label_num (rtx_code_label
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)
+ && must_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 (may_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;
}
===================================================================
@@ -1294,10 +1294,14 @@ record_subregs_of_mode (rtx subreg, bool
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 (must_lt (size, GET_MODE_SIZE (shape.inner_mode)));
if (must_ge (shape.offset, size))
shape.offset -= size;
else
===================================================================
@@ -1395,13 +1395,15 @@ modified_in_p (const_rtx x, const_rtx in
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 (may_gt (isize, osize) && may_gt (isize, regsize));
}
/* Helper function for set_of. */