On Nov 18, 2014, at 1:52 PM, Jakub Jelinek <[email protected]> wrote:
> OImode/XImode on i?86/x86_64 are not <= MAX_BITSIZE_MODE_ANY_INT, because
> they are never used for integer arithmetics (and there is no way
> to represent all their values in RTL if not using CONST_WIDE_INT).
> As the following testcase shows, simplify_immed_subreg can be called
> with such modes though, e.g. trying to forward propagate a CONST_VECTOR
> (i?86/x86_64 handles all zeros and all ones as CONST_VECTORs that can appear
> in the IL directly) into a SUBREG_REG.
> The following patch instead of ICE handles the most common cases (all 0
> and all 1 CONST_VECTORs) and returns NULL otherwise.
>
> Before wide-int got merged, the testcase worked, though the code didn't
> bother checking anything, just created 0 or constm1_rtx for the two cases
> that could happen and if something else appeared, could just return what
> matched low TImode (or DImode for -m32).
tmp is sized for MAX_BITSIZE_MODE_ANY_INT, but, you remove the limiter for
units that keeps u in bounds. Doesn’t this access 32 bytes of OImode values in
a 16 byte data structure?
Next, from_arrary uses a wide_int, and this from the documentation applies:
All three flavors of wide_int are represented as a vector of
HOST_WIDE_INTs. The default and widest_int vectors contain enough elements
to hold a value of MAX_BITSIZE_MODE_ANY_INT bits. offset_int contains only
enough elements to hold ADDR_MAX_PRECISION bits. The values are stored
in the vector with the least significant HOST_BITS_PER_WIDE_INT bits
in element 0.
If you look at the code to from_arrary:
wide_int_storage::from_array (const HOST_WIDE_INT *val, unsigned int len,
unsigned int precision, bool need_canon_p)
{
wide_int result = wide_int::create (precision);
result.set_len (wi::from_array (result.write_val (), val, len, precision,
need_canon_p));
unsigned int
wi::from_array (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
unsigned int xlen, unsigned int precision, bool need_canon)
{
for (unsigned i = 0; i < xlen; i++)
val[i] = xval[i];
it just does a blind copy of all the xlen hunks which forms from units, and
units is:
int units
= (GET_MODE_BITSIZE (outer_submode) + HOST_BITS_PER_WIDE_INT - 1)
/ HOST_BITS_PER_WIDE_INT;
and GET_MODE_BITSIZE (outer_submode) is > MAX_BITSIZE_MODE_ANY_INT, right?
You can’t copy more bytes than the size of the destination has?