https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102989

--- Comment #38 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I guess there are other options.
If we could make wide_int/widest_int non-POD, one option would be to turn their
storage into a union of the normal small case we use now everywhere (i.e. fixed
one) and one where the val array is not stored directly in the storage but
pointed to by some pointer.
E.g.
class GTY(()) wide_int_storage
{
private:
  HOST_WIDE_INT val[WIDE_INT_MAX_ELTS];
  unsigned int len;
  unsigned int precision;
could be
private:
  union { HOST_WIDE_INT val[WIDE_INT_MAX_ELTS]; HOST_WIDE_INT *valp; };
  unsigned int len;
  unsigned int precision;
and decide which one is which based on len > WIDE_INT_MAX_ELTS or something
similar.
Or, if we can't affort to make it non-POD, perhaps valp would refer to obstack
destroyed at the end of each pass or something similar.
Another problem is with INTEGER_CST (note, if we lower this stuff before
expansion hopefully we wouldn't need something similar for rtxes).
Currently INTEGER_CST has:
    /* The number of HOST_WIDE_INTs in an INTEGER_CST.  */
    struct {
      /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
         its native precision.  */
      unsigned char unextended;

      /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to
         wider precisions based on its TYPE_SIGN.  */
      unsigned char extended;

      /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
         offset_int precision, with smaller integers being extended
         according to their TYPE_SIGN.  This is equal to one of the two
         fields above but is cached for speed.  */            
      unsigned char offset;                                   
    } int_length;
Now, this obviously limits the largest representable constants to 0xFF
HOST_WIDE_INTs,
i.e. at most 16320 bits.  We have 8 spare bits there, so one possibility would
be to add a flag there and if that flag is true, ignore
int_length.{unextended,extended,offset} fields and instead stick that info
somewhere into the val array.
Or kill TREE_INT_CST_OFFSET_NUNITS (replace it with
TREE_INT_CST_EXT_NUNITS (t) <= OFFSET_INT_ELTS ? TREE_INT_CST_EXT_NUNITS (t) :
TREE_INT_CST_NUNITS (t)) and turn unextended/extended into unsigned short.
Then we can handle at most _BitInt(4194240), slightly more than 2 times lower
than
what LLVM chose, I guess that would be still acceptable.

Reply via email to