On Thu, Oct 12, 2023 at 11:54:14AM +0100, Richard Sandiford wrote:
> Jakub Jelinek <ja...@redhat.com> writes:
> > @@ -2036,11 +2075,20 @@ wi::lrshift_large (HOST_WIDE_INT *val, c
> >                unsigned int xlen, unsigned int xprecision,
> >                unsigned int precision, unsigned int shift)
> >  {
> > -  unsigned int len = rshift_large_common (val, xval, xlen, xprecision, 
> > shift);
> > +  /* Work out how many blocks are needed to store the significant bits
> > +     (excluding the upper zeros or signs).  */
> > +  unsigned int blocks_needed = BLOCKS_NEEDED (xprecision - shift);
> > +  unsigned int len = blocks_needed;
> > +  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)
> > +      && len > xlen
> > +      && xval[xlen - 1] >= 0)
> > +    len = xlen;
> 
> I think here too it would be worth dropping the:
> 
>   UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)
> 
> part of the condition, since presumably the change should be safe
> regardless of that.

If so, there is also one spot in lshift_large as well.  So incrementally:

--- gcc/wide-int.cc     2023-10-11 14:41:23.719132402 +0200
+++ gcc/wide-int.cc     2023-10-11 14:41:23.719132402 +0200
@@ -2013,8 +2013,7 @@
 
   /* The whole-block shift fills with zeros.  */
   unsigned int len = BLOCKS_NEEDED (precision);
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
-    len = xlen + skip + 1;
+  len = MIN (xlen + skip + 1, len);
   for (unsigned int i = 0; i < skip; ++i)
     val[i] = 0;
 
@@ -2079,9 +2078,7 @@
      (excluding the upper zeros or signs).  */
   unsigned int blocks_needed = BLOCKS_NEEDED (xprecision - shift);
   unsigned int len = blocks_needed;
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)
-      && len > xlen
-      && xval[xlen - 1] >= 0)
+  if (len > xlen && xval[xlen - 1] >= 0)
     len = xlen;
 
   rshift_large_common (val, xval, xlen, shift, len);
@@ -2114,9 +2111,7 @@
   /* Work out how many blocks are needed to store the significant bits
      (excluding the upper zeros or signs).  */
   unsigned int blocks_needed = BLOCKS_NEEDED (xprecision - shift);
-  unsigned int len = blocks_needed;
-  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS) && len > xlen)
-    len = xlen;
+  unsigned int len = MIN (xlen, blocks_needed);
 
   rshift_large_common (val, xval, xlen, shift, len);
 
which I'll test soon.

> OK for thw wide-int parts with those changes.

Thanks.  What do you think about that
--- gcc/wide-int.h.jj   2023-10-11 12:05:47.718059477 +0200
+++ gcc/wide-int.h      2023-10-11 13:51:56.081552500 +0200
@@ -1635,6 +1635,8 @@ widest_int_storage <N>::write_val (unsig
       u.valp = XNEWVEC (HOST_WIDE_INT, l);
       return u.valp;
     }
+  else if (CHECKING_P && l < WIDE_INT_MAX_INL_ELTS)
+    u.val[l] = HOST_WIDE_INT_UC (0xbaaaaaaddeadbeef);
   return u.val;
 }
 
@@ -1650,6 +1652,9 @@ widest_int_storage <N>::set_len (unsigne
       memcpy (u.val, valp, l * sizeof (u.val[0]));
       XDELETEVEC (valp);
     }
+  else if (len && len < WIDE_INT_MAX_INL_ELTS)
+    gcc_checking_assert ((unsigned HOST_WIDE_INT) u.val[len]
+                        == HOST_WIDE_INT_UC (0xbaaaaaaddeadbeef));
   len = l;
   /* There are no excess bits in val[len - 1].  */
   STATIC_ASSERT (N % HOST_BITS_PER_WIDE_INT == 0);

part, shall that go into trunk as well or is that too much slowdown
for checking builds?

        Jakub

Reply via email to