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?

Reply via email to