On Thu, Dec 17, 2015 at 12:33:22PM +0100, Richard Biener wrote:
> > @@ -1245,11 +1245,9 @@ static unsigned int
> >  get_int_cst_ext_nunits (tree type, const wide_int &cst)
> >  {
> >    gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type));
> > -  /* We need an extra zero HWI if CST is an unsigned integer with its
> > -     upper bit set, and if CST occupies a whole number of HWIs.  */
> > -  if (TYPE_UNSIGNED (type)
> > -      && wi::neg_p (cst)
> > -      && (cst.get_precision () % HOST_BITS_PER_WIDE_INT) == 0)
> > +  /* We need extra HWIs if CST is an unsigned integer with its
> > +     upper bit set.  */
> > +  if (TYPE_UNSIGNED (type) && wi::neg_p (cst))
> >      return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1;
> >    return cst.get_len ();
> >  }
> 
> I don't see why this is necessary - if there are enough bits to
> always have a zero MSB for unsigned types then we don't need an
> extra element.

But there aren't enough bits in that case.
Let's consider how is -2 casted to unsigned type with precision 64, 65, 127,
128 and 129 is encoded.
cst.get_len () is in each case 1, the first element is -2.
So, what get_int_cst_ext_nunits before my change does is that for
precision 64 and 128 return 2 and 3, for all other precisions (talking just
about < 129) returns 1.
So, before my patch we have:
precision       TREE_INT_CST_NUNITS     TREE_INT_CST_EXT_NUNITS         
TREE_INT_CST_ELT
64              1                       2                               -2, 0
65              1                       1                               -2
127             1                       1                               -2
128             1                       3                               -2, -1, 0
129             1                       1                               -2
and with the patch we have:
64              1                       2                               -2, 0
65              1                       2                               -2, 1
127             1                       2                               -2, 
-1ULL / 2
128             1                       3                               -2, -1, 0
129             1                       3                               -2, -1, 
1

Thus, before the patch there was nothing that in the ext units would tell
the users the value is actually large unsigned one rather than negative.
I really don't see what is so special on precisions divisible by
HOST_BITS_PER_WIDE_INT.  The > TREE_INT_CST_NUNITS elements aren't
guaranteed to be all 0s anyway, they are all -1s and for the precisions
divisible by HOST_BITS_PER_WIDE_INT the last one is 0.  That is what is
special on those, with my patch for the other precisions the last one is
simply always some power of two - 1 (other than -1).

Now, if the value is not in between maximum and maximum - 0x8000000000000000ULL
TREE_INT_CST_NUNITS will not be 1, but say 2 or more, and perhaps again
the len is still smaller than precision / HOST_BITS_PER_WIDE_INT + 1, but
if it is again negative, we want to have some way to add the ext elements
(a series of -1, followed by 0 or other power of two - 1 other than -1).

> 
> > @@ -1266,7 +1264,8 @@ build_new_int_cst (tree type, const wide
> >    if (len < ext_len)
> >      {
> >        --ext_len;
> > -      TREE_INT_CST_ELT (nt, ext_len) = 0;
> > +      TREE_INT_CST_ELT (nt, ext_len)
> > +   = zext_hwi (-1, cst.get_precision () % HOST_BITS_PER_WIDE_INT);
> 
> isn't this enough?

No.  This is the len < ext_len case, without the first hunk
if len < ext_len then cst.get_precision () % HOST_BITS_PER_WIDE_INT is
guaranteed to be 0, and thus zext_hwi will return 0.

        Jakub

Reply via email to