On Sun, 20 Oct 2013, Richard Sandiford wrote: > Another follow-up to yesterday's patch. This one implements Richard's > suggestion of having an is_sign_extended trait to optimise cases where > excess upper bits are known to be signs rather than undefined. > > The uses so far are: > > * make to_shwi () equivalent to slow () > * turn eq_p into a simple loop > * avoid extensions in sign_mask () > * avoid extensions in set_len if the input was already sign-extended > > The first two are new (compared to wide-int svn) while the second two > partially undo the negative effects of yesterday's patch on is_sign_extended > values. > > E.g. > > bool > f (wide_int x, HOST_WIDE_INT y) > { > return x == y; > } > > now gives: > > xorl %eax, %eax > cmpl $1, 264(%rsp) > je .L27 > ret > .p2align 4,,10 > .p2align 3 > .L27: > cmpq 8(%rsp), %rdi > sete %al > ret > > And: > > wide_int > f (wide_int x, wide_int y) > { > return x == y; > } > > gives: > > movl 264(%rsp), %ecx > xorl %eax, %eax > cmpl 528(%rsp), %ecx > je .L42 > rep ret > .p2align 4,,10 > .p2align 3 > .L42: > xorl %eax, %eax > jmp .L38 > .p2align 4,,10 > .p2align 3 > .L44: > addl $1, %eax > cmpl %eax, %ecx > je .L43 > .L38: > movl %eax, %edx > movq 272(%rsp,%rdx,8), %rsi > cmpq %rsi, 8(%rsp,%rdx,8) > je .L44 > xorl %eax, %eax > ret > .p2align 4,,10 > .p2align 3 > .L43: > movl $1, %eax > ret > > (which is a bit poor -- "je .L42" trivially threads to "je. L38", > although that's probably only true after RA). > > The code for: > > bool > f (wide_int x, unsigned HOST_WIDE_INT y) > { > return x == y; > } > > still needs some work though... > > The lts_p sequences of wide_int are similar to the ones Mike posted. > > Tested on x86_64-linux-gnu. OK for wide-int?
Ok. Thanks, Richard. > Thanks, > Richard > > > Index: gcc/rtl.h > =================================================================== > --- gcc/rtl.h 2013-10-20 09:38:40.254493991 +0100 > +++ gcc/rtl.h 2013-10-20 09:39:28.169894855 +0100 > @@ -1410,6 +1410,7 @@ typedef std::pair <rtx, enum machine_mod > { > static const enum precision_type precision_type = VAR_PRECISION; > static const bool host_dependent_precision = false; > + static const bool is_sign_extended = true; > static unsigned int get_precision (const rtx_mode_t &); > static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, > const rtx_mode_t &); > Index: gcc/tree.h > =================================================================== > --- gcc/tree.h 2013-10-20 09:38:40.254493991 +0100 > +++ gcc/tree.h 2013-10-20 09:39:28.170894863 +0100 > @@ -5158,6 +5158,7 @@ #define ANON_AGGRNAME_FORMAT "__anon_%d" > { > static const enum precision_type precision_type = FLEXIBLE_PRECISION; > static const bool host_dependent_precision = false; > + static const bool is_sign_extended = false; > static unsigned int get_precision (const_tree); > static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, > const_tree); > Index: gcc/wide-int.h > =================================================================== > --- gcc/wide-int.h 2013-10-20 09:39:11.527755622 +0100 > +++ gcc/wide-int.h 2013-10-20 09:45:17.725820291 +0100 > @@ -335,8 +335,21 @@ #define WI_UNARY_RESULT_VAR(RESULT, VAL, > struct wide_int_storage; > typedef generic_wide_int <wide_int_storage> wide_int; > > +template <bool SE> > struct wide_int_ref_storage; > -typedef generic_wide_int <wide_int_ref_storage> wide_int_ref; > + > +typedef generic_wide_int <wide_int_ref_storage <false> > wide_int_ref; > + > +/* This can be used instead of wide_int_ref if the referenced value is > + known to have type T. It carries across properties of T's representation, > + such as whether excess upper bits in a HWI are defined, and can therefore > + help avoid redundant work. > + > + The macro could be replaced with a template typedef, once we're able > + to use those. */ > +#define WIDE_INT_REF_FOR(T) \ > + generic_wide_int \ > + <wide_int_ref_storage <wi::int_traits <T>::is_sign_extended> > > > /* Public functions for querying and operating on integers. */ > namespace wi > @@ -520,18 +533,6 @@ wi::storage_ref::get_val () const > return val; > } > > -namespace wi > -{ > - template <> > - struct int_traits <wi::storage_ref> > - { > - static const enum precision_type precision_type = VAR_PRECISION; > - /* wi::storage_ref can be a reference to a primitive type, > - so this is the conservatively-correct setting. */ > - static const bool host_dependent_precision = true; > - }; > -} > - > /* This class defines an integer type using the storage provided by the > template argument. The storage class must provide the following > functions: > @@ -626,6 +627,9 @@ #define INCDEC_OPERATOR(OP, DELTA) \ > #undef INCDEC_OPERATOR > > char *dump (char *) const; > + > + static const bool is_sign_extended > + = wi::int_traits <generic_wide_int <storage> >::is_sign_extended; > }; > > template <typename storage> > @@ -653,7 +657,11 @@ inline generic_wide_int <storage>::gener > generic_wide_int <storage>::to_shwi (unsigned int precision) const > { > if (precision == 0) > - precision = this->get_precision (); > + { > + if (is_sign_extended) > + return this->get_val ()[0]; > + precision = this->get_precision (); > + } > if (precision < HOST_BITS_PER_WIDE_INT) > return sext_hwi (this->get_val ()[0], precision); > else > @@ -692,11 +700,14 @@ generic_wide_int <storage>::to_short_add > generic_wide_int <storage>::sign_mask () const > { > unsigned int len = this->get_len (); > - unsigned int precision = this->get_precision (); > unsigned HOST_WIDE_INT high = this->get_val ()[len - 1]; > - int excess = len * HOST_BITS_PER_WIDE_INT - precision; > - if (excess > 0) > - high <<= excess; > + if (!is_sign_extended) > + { > + unsigned int precision = this->get_precision (); > + int excess = len * HOST_BITS_PER_WIDE_INT - precision; > + if (excess > 0) > + high <<= excess; > + } > return HOST_WIDE_INT (high) < 0 ? -1 : 0; > } > > @@ -781,6 +792,7 @@ decompose (HOST_WIDE_INT *, unsigned int > /* Provide the storage for a wide_int_ref. This acts like a read-only > wide_int, with the optimization that VAL is normally a pointer to > another integer's storage, so that no array copy is needed. */ > +template <bool SE> > struct wide_int_ref_storage : public wi::storage_ref > { > private: > @@ -799,17 +811,19 @@ struct wide_int_ref_storage : public wi: > /* Create a reference to integer X in its natural precision. Note > that the natural precision is host-dependent for primitive > types. */ > +template <bool SE> > template <typename T> > -inline wide_int_ref_storage::wide_int_ref_storage (const T &x) > +inline wide_int_ref_storage <SE>::wide_int_ref_storage (const T &x) > : storage_ref (wi::int_traits <T>::decompose (scratch, > wi::get_precision (x), x)) > { > } > > /* Create a reference to integer X in precision PRECISION. */ > +template <bool SE> > template <typename T> > -inline wide_int_ref_storage::wide_int_ref_storage (const T &x, > - unsigned int precision) > +inline wide_int_ref_storage <SE>::wide_int_ref_storage (const T &x, > + unsigned int precision) > : storage_ref (wi::int_traits <T>::decompose (scratch, precision, x)) > { > } > @@ -817,9 +831,14 @@ inline wide_int_ref_storage::wide_int_re > namespace wi > { > template <> > - struct int_traits <wide_int_ref_storage> > - : public int_traits <wi::storage_ref> > + template <bool SE> > + struct int_traits <wide_int_ref_storage <SE> > > { > + static const enum precision_type precision_type = VAR_PRECISION; > + /* wi::storage_ref can be a reference to a primitive type, > + so this is the conservatively-correct setting. */ > + static const bool host_dependent_precision = true; > + static const bool is_sign_extended = SE; > }; > } > > @@ -850,7 +869,7 @@ class GTY(()) wide_int_storage > const HOST_WIDE_INT *get_val () const; > unsigned int get_len () const; > HOST_WIDE_INT *write_val (); > - void set_len (unsigned int); > + void set_len (unsigned int, bool = false); > > static wide_int from (const wide_int_ref &, unsigned int, signop); > static wide_int from_array (const HOST_WIDE_INT *, unsigned int, > @@ -871,7 +890,7 @@ inline wide_int_storage::wide_int_storag > inline wide_int_storage::wide_int_storage (const T &x) > { > STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision); > - wide_int_ref xi (x); > + WIDE_INT_REF_FOR (T) xi (x); > precision = xi.precision; > wi::copy (*this, xi); > } > @@ -901,10 +920,10 @@ wide_int_storage::write_val () > } > > inline void > -wide_int_storage::set_len (unsigned int l) > +wide_int_storage::set_len (unsigned int l, bool is_sign_extended) > { > len = l; > - if (len * HOST_BITS_PER_WIDE_INT > precision) > + if (!is_sign_extended && len * HOST_BITS_PER_WIDE_INT > precision) > val[len - 1] = sext_hwi (val[len - 1], > precision % HOST_BITS_PER_WIDE_INT); > } > @@ -951,6 +970,7 @@ wide_int_storage::create (unsigned int p > static const enum precision_type precision_type = VAR_PRECISION; > /* Guaranteed by a static assert in the wide_int_storage constructor. */ > static const bool host_dependent_precision = false; > + static const bool is_sign_extended = true; > template <typename T1, typename T2> > static wide_int get_binary_result (const T1 &, const T2 &); > }; > @@ -981,7 +1001,7 @@ wi::copy (T1 &x, const T2 &y) > do > xval[i] = yval[i]; > while (++i < len); > - x.set_len (len); > + x.set_len (len, y.is_sign_extended); > } > > /* An N-bit integer. Until we can use typedef templates, use this instead. > */ > @@ -1006,7 +1026,7 @@ class GTY(()) fixed_wide_int_storage > const HOST_WIDE_INT *get_val () const; > unsigned int get_len () const; > HOST_WIDE_INT *write_val (); > - void set_len (unsigned int); > + void set_len (unsigned int, bool = false); > > static FIXED_WIDE_INT (N) from (const wide_int_ref &, signop); > static FIXED_WIDE_INT (N) from_array (const HOST_WIDE_INT *, unsigned int, > @@ -1027,7 +1047,7 @@ inline fixed_wide_int_storage <N>::fixed > /* Check for type compatibility. We don't want to initialize a > fixed-width integer from something like a wide_int. */ > WI_BINARY_RESULT (T, FIXED_WIDE_INT (N)) *assertion ATTRIBUTE_UNUSED; > - wi::copy (*this, wide_int_ref (x, N)); > + wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N)); > } > > template <int N> > @@ -1060,7 +1080,7 @@ fixed_wide_int_storage <N>::write_val () > > template <int N> > inline void > -fixed_wide_int_storage <N>::set_len (unsigned int l) > +fixed_wide_int_storage <N>::set_len (unsigned int l, bool) > { > len = l; > /* There are no excess bits in val[len - 1]. */ > @@ -1101,6 +1121,7 @@ fixed_wide_int_storage <N>::from_array ( > { > static const enum precision_type precision_type = CONST_PRECISION; > static const bool host_dependent_precision = false; > + static const bool is_sign_extended = true; > static const unsigned int precision = N; > template <typename T1, typename T2> > static FIXED_WIDE_INT (N) get_binary_result (const T1 &, const T2 &); > @@ -1190,6 +1211,7 @@ get_binary_result (const T1 &, const T2 > { > static const enum precision_type precision_type = FLEXIBLE_PRECISION; > static const bool host_dependent_precision = true; > + static const bool is_sign_extended = true; > static unsigned int get_precision (T); > static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, T); > }; > @@ -1316,6 +1338,7 @@ wi::two (unsigned int precision) > /* hwi_with_prec has an explicitly-given precision, rather than the > precision of HOST_WIDE_INT. */ > static const bool host_dependent_precision = false; > + static const bool is_sign_extended = true; > static unsigned int get_precision (const wi::hwi_with_prec &); > static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, > const wi::hwi_with_prec &); > @@ -1427,7 +1450,7 @@ wi::get_binary_precision (const T1 &x, c > inline bool > wi::fits_shwi_p (const T &x) > { > - wide_int_ref xi (x); > + WIDE_INT_REF_FOR (T) xi (x); > return xi.len == 1; > } > > @@ -1437,7 +1460,7 @@ wi::fits_shwi_p (const T &x) > inline bool > wi::fits_uhwi_p (const T &x) > { > - wide_int_ref xi (x); > + WIDE_INT_REF_FOR (T) xi (x); > if (xi.precision <= HOST_BITS_PER_WIDE_INT) > return true; > if (xi.len == 1) > @@ -1451,7 +1474,7 @@ wi::fits_uhwi_p (const T &x) > inline bool > wi::neg_p (const T &x, signop sgn) > { > - wide_int_ref xi (x); > + WIDE_INT_REF_FOR (T) xi (x); > if (sgn == UNSIGNED) > return false; > return xi.sign_mask () < 0; > @@ -1463,7 +1486,7 @@ wi::neg_p (const T &x, signop sgn) > inline HOST_WIDE_INT > wi::sign_mask (const T &x) > { > - wide_int_ref xi (x); > + WIDE_INT_REF_FOR (T) xi (x); > return xi.sign_mask (); > } > > @@ -1473,10 +1496,19 @@ wi::sign_mask (const T &x) > wi::eq_p (const T1 &x, const T2 &y) > { > unsigned int precision = get_binary_precision (x, y); > - if (precision == 0) > - return true; > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y, precision); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > + if (xi.is_sign_extended && yi.is_sign_extended) > + { > + if (xi.len != yi.len) > + return false; > + unsigned int i = 0; > + do > + if (xi.val[i] != yi.val[i]) > + return false; > + while (++i != xi.len); > + return true; > + } > if (precision <= HOST_BITS_PER_WIDE_INT) > { > unsigned HOST_WIDE_INT diff = xi.ulow () ^ yi.ulow (); > @@ -1502,8 +1534,8 @@ wi::lts_p (const T1 &x, const T2 &y) > // We have to be careful to not allow comparison to a large positive > // unsigned value like 0x8000000000000000, those would be encoded > // with a y.len == 2. > - wide_int_ref xi (x); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x); > + WIDE_INT_REF_FOR (T2) yi (y); > if (yi.precision <= HOST_BITS_PER_WIDE_INT > && yi.len == 1) > { > @@ -1527,8 +1559,8 @@ wi::lts_p (const T1 &x, const T2 &y) > inline bool > wi::ltu_p (const T1 &x, const T2 &y) > { > - wide_int_ref xi (x); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x); > + WIDE_INT_REF_FOR (T2) yi (y); > if (xi.precision <= HOST_BITS_PER_WIDE_INT > && yi.precision <= HOST_BITS_PER_WIDE_INT) > { > @@ -1639,8 +1671,8 @@ wi::ge_p (const T1 &x, const T2 &y, sign > inline int > wi::cmps (const T1 &x, const T2 &y) > { > - wide_int_ref xi (x); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x); > + WIDE_INT_REF_FOR (T2) yi (y); > if (xi.precision <= HOST_BITS_PER_WIDE_INT > && yi.precision <= HOST_BITS_PER_WIDE_INT) > { > @@ -1663,8 +1695,8 @@ wi::cmps (const T1 &x, const T2 &y) > inline int > wi::cmpu (const T1 &x, const T2 &y) > { > - wide_int_ref xi (x); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x); > + WIDE_INT_REF_FOR (T2) yi (y); > if (xi.precision <= HOST_BITS_PER_WIDE_INT > && yi.precision <= HOST_BITS_PER_WIDE_INT) > { > @@ -1699,7 +1731,7 @@ inline WI_UNARY_RESULT (T) > wi::bit_not (const T &x) > { > WI_UNARY_RESULT_VAR (result, val, T, x); > - wide_int_ref xi (x, get_precision (result)); > + WIDE_INT_REF_FOR (T) xi (x, get_precision (result)); > for (unsigned int i = 0; i < xi.len; ++i) > val[i] = ~xi.val[i]; > result.set_len (xi.len); > @@ -1738,12 +1770,12 @@ wi::sext (const T &x, unsigned int offse > { > WI_UNARY_RESULT_VAR (result, val, T, x); > unsigned int precision = get_precision (result); > - wide_int_ref xi (x, precision); > + WIDE_INT_REF_FOR (T) xi (x, precision); > > if (offset <= HOST_BITS_PER_WIDE_INT) > { > val[0] = sext_hwi (xi.ulow (), offset); > - result.set_len (1); > + result.set_len (1, true); > } > else > result.set_len (sext_large (val, xi.val, xi.len, precision, offset)); > @@ -1757,7 +1789,7 @@ wi::zext (const T &x, unsigned int offse > { > WI_UNARY_RESULT_VAR (result, val, T, x); > unsigned int precision = get_precision (result); > - wide_int_ref xi (x, precision); > + WIDE_INT_REF_FOR (T) xi (x, precision); > > /* This is not just an optimization, it is actually required to > maintain canonization. */ > @@ -1793,7 +1825,7 @@ wi::set_bit (const T &x, unsigned int bi > { > WI_UNARY_RESULT_VAR (result, val, T, x); > unsigned int precision = get_precision (result); > - wide_int_ref xi (x, precision); > + WIDE_INT_REF_FOR (T) xi (x, precision); > if (precision <= HOST_BITS_PER_WIDE_INT) > { > val[0] = xi.ulow () | ((unsigned HOST_WIDE_INT) 1 << bit); > @@ -1813,9 +1845,9 @@ wi::min (const T1 &x, const T2 &y, signo > WI_BINARY_RESULT_VAR (result, val ATTRIBUTE_UNUSED, T1, x, T2, y); > unsigned int precision = get_precision (result); > if (wi::le_p (x, y, sgn)) > - wi::copy (result, wide_int_ref (x, precision)); > + wi::copy (result, WIDE_INT_REF_FOR (T1) (x, precision)); > else > - wi::copy (result, wide_int_ref (y, precision)); > + wi::copy (result, WIDE_INT_REF_FOR (T2) (y, precision)); > return result; > } > > @@ -1844,9 +1876,9 @@ wi::max (const T1 &x, const T2 &y, signo > WI_BINARY_RESULT_VAR (result, val ATTRIBUTE_UNUSED, T1, x, T2, y); > unsigned int precision = get_precision (result); > if (wi::ge_p (x, y, sgn)) > - wi::copy (result, wide_int_ref (x, precision)); > + wi::copy (result, WIDE_INT_REF_FOR (T1) (x, precision)); > else > - wi::copy (result, wide_int_ref (y, precision)); > + wi::copy (result, WIDE_INT_REF_FOR (T2) (y, precision)); > return result; > } > > @@ -1873,16 +1905,17 @@ wi::bit_and (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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > + bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended; > if (xi.len + yi.len == 2) > { > val[0] = xi.ulow () & yi.ulow (); > - result.set_len (1); > + result.set_len (1, is_sign_extended); > } > else > result.set_len (and_large (val, xi.val, xi.len, yi.val, yi.len, > - precision)); > + precision), is_sign_extended); > return result; > } > > @@ -1893,16 +1926,17 @@ wi::bit_and_not (const T1 &x, const T2 & > { > 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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > + bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended; > if (xi.len + yi.len == 2) > { > val[0] = xi.ulow () & ~yi.ulow (); > - result.set_len (1); > + result.set_len (1, is_sign_extended); > } > else > result.set_len (and_not_large (val, xi.val, xi.len, yi.val, yi.len, > - precision)); > + precision), is_sign_extended); > return result; > } > > @@ -1913,16 +1947,17 @@ wi::bit_or (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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > + bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended; > if (xi.len + yi.len == 2) > { > val[0] = xi.ulow () | yi.ulow (); > - result.set_len (1); > + result.set_len (1, is_sign_extended); > } > else > result.set_len (or_large (val, xi.val, xi.len, > - yi.val, yi.len, precision)); > + yi.val, yi.len, precision), is_sign_extended); > return result; > } > > @@ -1933,16 +1968,17 @@ wi::bit_or_not (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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > + bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended; > if (xi.len + yi.len == 2) > { > val[0] = xi.ulow () | ~yi.ulow (); > - result.set_len (1); > + result.set_len (1, is_sign_extended); > } > else > result.set_len (or_not_large (val, xi.val, xi.len, yi.val, yi.len, > - precision)); > + precision), is_sign_extended); > return result; > } > > @@ -1953,16 +1989,17 @@ wi::bit_xor (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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > + bool is_sign_extended = xi.is_sign_extended && yi.is_sign_extended; > if (xi.len + yi.len == 2) > { > val[0] = xi.ulow () ^ yi.ulow (); > - result.set_len (1); > + result.set_len (1, is_sign_extended); > } > else > result.set_len (xor_large (val, xi.val, xi.len, > - yi.val, yi.len, precision)); > + yi.val, yi.len, precision), is_sign_extended); > return result; > } > > @@ -1973,12 +2010,12 @@ wi::add (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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > if (precision <= HOST_BITS_PER_WIDE_INT) > { > val[0] = xi.ulow () + yi.ulow (); > - result.set_len (1); > + result.set_len (1, xi.is_sign_extended && yi.is_sign_extended); > } > else > result.set_len (add_large (val, xi.val, xi.len, > @@ -1995,8 +2032,8 @@ wi::add (const T1 &x, const T2 &y, signo > { > 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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > if (precision <= HOST_BITS_PER_WIDE_INT) > { > unsigned HOST_WIDE_INT xl = xi.ulow (); > @@ -2027,8 +2064,8 @@ 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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > if (precision <= HOST_BITS_PER_WIDE_INT) > { > val[0] = xi.ulow () - yi.ulow (); > @@ -2049,8 +2086,8 @@ wi::sub (const T1 &x, const T2 &y, signo > { > 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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > if (precision <= HOST_BITS_PER_WIDE_INT) > { > unsigned HOST_WIDE_INT xl = xi.ulow (); > @@ -2080,8 +2117,8 @@ wi::mul (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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > if (precision <= HOST_BITS_PER_WIDE_INT) > { > val[0] = xi.ulow () * yi.ulow (); > @@ -2101,8 +2138,8 @@ wi::mul (const T1 &x, const T2 &y, signo > { > 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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > result.set_len (mul_internal (val, xi.val, xi.len, > yi.val, yi.len, precision, > sgn, overflow, false, false)); > @@ -2135,8 +2172,8 @@ wi::mul_high (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); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y, precision); > result.set_len (mul_internal (val, xi.val, xi.len, > yi.val, yi.len, precision, > sgn, 0, true, false)); > @@ -2152,8 +2189,8 @@ wi::div_trunc (const T1 &x, const T2 &y, > { > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > quotient.set_len (divmod_internal (quotient_val, 0, 0, xi.val, xi.len, > precision, > @@ -2188,8 +2225,8 @@ wi::div_floor (const T1 &x, const T2 &y, > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > quotient.set_len (divmod_internal (quotient_val, > @@ -2230,8 +2267,8 @@ wi::div_ceil (const T1 &x, const T2 &y, > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > quotient.set_len (divmod_internal (quotient_val, > @@ -2255,8 +2292,8 @@ wi::div_round (const T1 &x, const T2 &y, > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > quotient.set_len (divmod_internal (quotient_val, > @@ -2299,8 +2336,8 @@ wi::divmod_trunc (const T1 &x, const T2 > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > quotient.set_len (divmod_internal (quotient_val, > @@ -2322,8 +2359,8 @@ wi::mod_trunc (const T1 &x, const T2 &y, > { > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (remainder); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > divmod_internal (0, &remainder_len, remainder_val, > @@ -2362,8 +2399,8 @@ wi::mod_floor (const T1 &x, const T2 &y, > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > quotient.set_len (divmod_internal (quotient_val, > @@ -2398,8 +2435,8 @@ wi::mod_ceil (const T1 &x, const T2 &y, > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > quotient.set_len (divmod_internal (quotient_val, > @@ -2424,8 +2461,8 @@ wi::mod_round (const T1 &x, const T2 &y, > WI_BINARY_RESULT_VAR (quotient, quotient_val, T1, x, T2, y); > WI_BINARY_RESULT_VAR (remainder, remainder_val, T1, x, T2, y); > unsigned int precision = get_precision (quotient); > - wide_int_ref xi (x, precision); > - wide_int_ref yi (y); > + WIDE_INT_REF_FOR (T1) xi (x, precision); > + WIDE_INT_REF_FOR (T2) yi (y); > > unsigned int remainder_len; > quotient.set_len (divmod_internal (quotient_val, > @@ -2499,7 +2536,7 @@ wi::lshift (const T &x, const wide_int_r > { > WI_UNARY_RESULT_VAR (result, val, T, x); > unsigned int precision = get_precision (result); > - wide_int_ref xi (x, precision); > + WIDE_INT_REF_FOR (T) xi (x, precision); > unsigned int shift = trunc_shift (y, bitsize, precision); > /* Handle the simple cases quickly. */ > if (shift >= precision) > @@ -2527,7 +2564,7 @@ wi::lrshift (const T &x, const wide_int_ > WI_UNARY_RESULT_VAR (result, val, T, x); > /* Do things in the precision of the input rather than the output, > since the result can be no larger than that. */ > - wide_int_ref xi (x); > + WIDE_INT_REF_FOR (T) xi (x); > unsigned int shift = trunc_shift (y, bitsize, xi.precision); > /* Handle the simple cases quickly. */ > if (shift >= xi.precision) > @@ -2555,7 +2592,7 @@ wi::arshift (const T &x, const wide_int_ > WI_UNARY_RESULT_VAR (result, val, T, x); > /* Do things in the precision of the input rather than the output, > since the result can be no larger than that. */ > - wide_int_ref xi (x); > + WIDE_INT_REF_FOR (T) xi (x); > unsigned int shift = trunc_shift (y, bitsize, xi.precision); > /* Handle the simple case quickly. */ > if (shift >= xi.precision) > @@ -2566,7 +2603,7 @@ wi::arshift (const T &x, const wide_int_ > else if (xi.precision <= HOST_BITS_PER_WIDE_INT) > { > val[0] = sext_hwi (xi.ulow () >> shift, xi.precision - shift); > - result.set_len (1); > + result.set_len (1, true); > } > else > result.set_len (arshift_large (val, xi.val, xi.len, xi.precision, > @@ -2641,7 +2678,7 @@ wi::extract_uhwi (const T &x, unsigned i > unsigned precision = get_precision (x); > if (precision < bitpos + width) > precision = bitpos + width; > - wide_int_ref xi (x, precision); > + WIDE_INT_REF_FOR (T) xi (x, precision); > > /* Handle this rare case after the above, so that we assert about > bogus BITPOS values. */ > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend