Speaking in terms of a patch:

Index: tree.h
===================================================================
--- tree.h      (revision 203690)
+++ tree.h      (working copy)
@@ -5184,14 +5184,11 @@ wi::int_traits <const_tree>::decompose (
                          / HOST_BITS_PER_WIDE_INT);
   unsigned int xprecision = get_precision (x);
 
-  gcc_assert (precision >= xprecision);
+  gcc_checking_assert (precision >= xprecision && precision != 0);
 
-  /* Got to be careful of precision 0 values.  */
-  if (precision)
-    len = MIN (len, max_len);
   if (TYPE_SIGN (TREE_TYPE (x)) == UNSIGNED)
     {
-      unsigned int small_prec = precision & (HOST_BITS_PER_WIDE_INT - 1);
+      unsigned int small_prec = xprecision & (HOST_BITS_PER_WIDE_INT - 
1);
       if (small_prec)
        {
          /* We have to futz with this because the canonization for
@@ -5201,7 +5198,7 @@ wi::int_traits <const_tree>::decompose (
            {
              for (unsigned int i = 0; i < len - 1; i++)
                scratch[i] = val[i];
-             scratch[len - 1] = sext_hwi (val[len - 1], precision);
+             scratch[len - 1] = sext_hwi (val[len - 1], small_prec);
              return wi::storage_ref (scratch, len, precision);
            }
        }

the precision 0 thing is gone as far as I understand?

Also sign-extending the upper hwi must be done with precision % 
HOST_BITS_PER_WIDE_INT, no?  And it assumes that we only ever
have to extend the upper most HWI, thus 'len' is never too big.

I note that we immediately return in the above case, so

      if (precision < xprecision + HOST_BITS_PER_WIDE_INT)
        {
          len = wi::force_to_size (scratch, val, len, xprecision, 
precision, UNSIGNED);
          return wi::storage_ref (scratch, len, precision);
        }

applies only when the desired precision is a multiple of a HWI.
I assume it adds that extra zero word in case the MSB is set,
right?  I am confused about the condition written here and
how we look at precision and not xprecision when deciding how
to extend - given a 8-bit precision unsigned 0xff and precision == 64
we do not even consider sign-extending the value because we look
at precision and not xprecision.  Don't we need to look at
xprecision here?  After all an assert precision == xprecision
does not work in this routine.

Quickly execute.exp tested only.

To avoid code quality wreckage we have to implement a different way
of allocating the 'scratch' storage of wide_int_ref_storage
(well, ideally we wouldn't need it ...).  I thought of simply
allocating it via alloca (), but we need to do that in all
callers that build a wide_int_ref (eventually via a hidden
default arg).  But as that's a template specialization of
generic_wide_int ... so the option is to provide a function
wrapper inside wi:: for this, like

template <typename T>
wide_int_ref
wi::ref (const T &t, HOST_WIDE_INT *scratch = XALLOCAVEC (HOST_WIDE_INT, 
WIDE_INT_MAX_ELTS))
{
  return wide_int_ref (t, scratch);
}

and amend the storage constructors to get a scratch argument.

The reason for all this is that otherwise the wide_int_ref object
escapes when we pass the scratch storage to the workers in
int_traits <const_tree>.

Thanks,
Richard.

Reply via email to