On Nov 18, 2014, at 1:52 PM, Jakub Jelinek <ja...@redhat.com> 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?