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.