When investigating the code-bloat / slowness of wide-ints I noticed
that when creating a wide_int_ref that operation (optionally, but
in practice almost always) gets a precision input that is ultimately
determined by get_*_result of the appropriate traits.  I don't
see code dealing with precision mismatches, but instead for
example sub:

wi::sub (const T1 &x, const T2 &y)
{
  WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y);
  unsigned int precision = get_precision (result);
  wide_int_ref xi (x, precision);
  wide_int_ref yi (y, precision);

and

template <typename T1, typename T2>
inline wide_int
wi::int_traits <wide_int_storage>::get_binary_result (const T1 &x, const 
T2 &y)
{
  /* This shouldn't be used for two flexible-precision inputs.  */
  STATIC_ASSERT (wi::int_traits <T1>::precision_type != FLEXIBLE_PRECISION
                 || wi::int_traits <T2>::precision_type != 
FLEXIBLE_PRECISION);
  if (wi::int_traits <T1>::precision_type == FLEXIBLE_PRECISION)
    return wide_int::create (wi::get_precision (y));
  else
    return wide_int::create (wi::get_precision (x));
}

suggest that we simply take the precision of 'x', even if for example
the precision of 'y' is larger.

I'd like to get rid of the precision argument to decompose (because
it complicates things and looks like a compound operation).

What was the reason to allow truncation / extension here (at least
the 'tree' decompose variant asserts that we don't truncate) given
that the canonical representation should guarantee "proper"
extension automagically?  (well, maybe I'm still not 100% familiar
with the wide-int representation)

I guess

Index: wide-int.h
===================================================================
--- wide-int.h  (revision 203690)
+++ wide-int.h  (working copy)
@@ -790,7 +790,8 @@ inline wide_int_ref_storage::wide_int_re
 template <typename T>
 inline wide_int_ref_storage::wide_int_ref_storage (const T &x,
                                                   unsigned int precision)
-  : storage_ref (wi::int_traits <T>::decompose (scratch, precision, x))
+  : storage_ref (wi::int_traits <T>::decompose (scratch,
+                                               wi::get_precision (x), x))
 {
 }

should tell me reasons enough ...?  But looking at 'sub' again,
what's the "users" way of specifying the desired precision for the
result?  Wasn't it that the precision of both operands were
supposed to match (apart from the "special" precisions which are
dealt with in the traits?)?  Ok, testsuite fails in obvious way
with the above, even with just short-cutting precision in the
tree decompose.  It seems that the RTX decompose can
assert that precision == get_precision (x), but not the tree
one.  That's weird.  The first ICE I get is via
wi::eq_p<tree_node const*, int> from integer_zerop.  Appearantly
we want precision 512 then because

unsigned int wi::get_binary_precision(const T1&, const T2&) [with T1 = 
const tree_node*, T2 = int] (const union tree_node * const & x, const int 
& y)
{
  unsigned int D.69052;
  struct generic_wide_int D.53828;

  D.53828 = wi::int_traits<fixed_wide_int_storage<512> 
>::get_binary_result<const tree_node*, int> (x, y); [return slot 
optimization]
  D.69052 = wi::get_precision<generic_wide_int<fixed_wide_int_storage<512> 
> > (&D.53828);
  return D.69052;

and

template <int N>
template <typename T1, typename T2>
inline FIXED_WIDE_INT (N)
wi::int_traits < fixed_wide_int_storage <N> >::
get_binary_result (const T1 &, const T2 &)
{
  return FIXED_WIDE_INT (N) ();
}

I'm sure eventually RTL will bomb here, too, asserting
precision == get_precision (x) in its decompose method.

Btw, in wi::int_traits <const_tree>::decompose you seem to assume
that only "small_prec" integers can have non-mode precision.  But
instead you can perfectly well have a 113 bit integer type via
bitfields and thus 113 bit integer operations.  Also...

  gcc_assert (precision >= xprecision);
...
  /* Got to be careful of precision 0 values.  */
  if (precision)
    len = MIN (len, max_len);
...
      if (precision < xprecision + HOST_BITS_PER_WIDE_INT)
        {

what's this all about?

Where exactly are we making use of the fact that wide-ints are
sign-extended (are they?)?  I think we should be able to drop
the re-canonicalization of tree constants given that we only
ever combine two tree constants or two rtx constants (hopefully).

Thanks,
Richard.

Reply via email to