Message ID | 87sivw44dn.fsf@talisman.default |
---|---|
State | New |
Headers | show |
Richard Sandiford <rdsandiford@googlemail.com> wrote: >When the wi:: patch went in, Kenny rightly complained that there were >too many copy loops. This patch gets rid of an unnecessary loop in >wi::abs and consolidates the rest into a single function. Again, it >helps >the ::is_sign_extended patch. > >Tested on x86_64-linux-gnu. OK to install? Ok. Thanks, Richard. >Thanks, >Richard > > >Index: gcc/wide-int.h >=================================================================== >--- gcc/wide-int.h 2013-10-20 09:38:41.175501696 +0100 >+++ gcc/wide-int.h 2013-10-20 11:32:47.425353384 +0100 >@@ -347,6 +347,9 @@ typedef generic_wide_int <wide_int_ref_s > template <typename T1, typename T2> > unsigned int get_binary_precision (const T1 &, const T2 &); > >+ template <typename T1, typename T2> >+ void copy (T1 &, const T2 &); >+ > #define UNARY_PREDICATE \ > template <typename T> bool > #define UNARY_FUNCTION \ >@@ -870,10 +873,7 @@ inline wide_int_storage::wide_int_storag > STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision); > wide_int_ref xi (x); > precision = xi.precision; >- unsigned int l = xi.len; >- for (unsigned int i = 0; i < l; ++i) >- val[i] = xi.val[i]; >- set_len (l); >+ wi::copy (*this, xi); > } > > inline unsigned int >@@ -969,6 +969,21 @@ wi::int_traits <wide_int_storage>::get_b > return wide_int::create (wi::get_precision (x)); > } > >+/* Copy the contents of Y to X, but keeping X's current precision. */ >+template <typename T1, typename T2> >+void >+wi::copy (T1 &x, const T2 &y) >+{ >+ HOST_WIDE_INT *xval = x.write_val (); >+ const HOST_WIDE_INT *yval = y.get_val (); >+ unsigned int len = y.get_len (); >+ unsigned int i = 0; >+ do >+ xval[i] = yval[i]; >+ while (++i < len); >+ x.set_len (len); >+} >+ >/* An N-bit integer. Until we can use typedef templates, use this >instead. */ > #define FIXED_WIDE_INT(N) \ > generic_wide_int < fixed_wide_int_storage <N> > >@@ -1012,10 +1027,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; >- wide_int_ref xi (x, N); >- len = xi.len; >- for (unsigned int i = 0; i < len; ++i) >- val[i] = xi.val[i]; >+ wi::copy (*this, wide_int_ref (x, N)); > } > > template <int N> >@@ -1716,16 +1728,7 @@ wi::neg (const T &x, bool *overflow) > inline WI_UNARY_RESULT (T) > wi::abs (const T &x) > { >- if (neg_p (x)) >- return neg (x); >- >- WI_UNARY_RESULT_VAR (result, val, T, x); >- wide_int_ref xi (x, get_precision (result)); >- for (unsigned int i = 0; i < xi.len; ++i) >- val[i] = xi.val[i]; >- result.set_len (xi.len); >- >- return result; >+ return neg_p (x) ? neg (x) : x; > } > > /* Return the result of sign-extending the low OFFSET bits of X. */ >@@ -1760,9 +1763,7 @@ wi::zext (const T &x, unsigned int offse > maintain canonization. */ > if (offset >= precision) > { >- for (unsigned int i = 0; i < xi.len; ++i) >- val[i] = xi.val[i]; >- result.set_len (xi.len); >+ wi::copy (result, xi); > return result; > } > >@@ -1809,22 +1810,12 @@ wi::set_bit (const T &x, unsigned int bi > inline WI_BINARY_RESULT (T1, T2) > wi::min (const T1 &x, const T2 &y, signop sgn) > { >- WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y); >+ 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)) >- { >- wide_int_ref xi (x, precision); >- for (unsigned int i = 0; i < xi.len; ++i) >- val[i] = xi.val[i]; >- result.set_len (xi.len); >- } >+ wi::copy (result, wide_int_ref (x, precision)); > else >- { >- wide_int_ref yi (y, precision); >- for (unsigned int i = 0; i < yi.len; ++i) >- val[i] = yi.val[i]; >- result.set_len (yi.len); >- } >+ wi::copy (result, wide_int_ref (y, precision)); > return result; > } > >@@ -1850,22 +1841,12 @@ wi::umin (const T1 &x, const T2 &y) > inline WI_BINARY_RESULT (T1, T2) > wi::max (const T1 &x, const T2 &y, signop sgn) > { >- WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y); >+ 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)) >- { >- wide_int_ref xi (x, precision); >- for (unsigned int i = 0; i < xi.len; ++i) >- val[i] = xi.val[i]; >- result.set_len (xi.len); >- } >+ wi::copy (result, wide_int_ref (x, precision)); > else >- { >- wide_int_ref yi (y, precision); >- for (unsigned int i = 0; i < yi.len; ++i) >- val[i] = yi.val[i]; >- result.set_len (yi.len); >- } >+ wi::copy (result, wide_int_ref (y, precision)); > return result; > } >
Index: gcc/wide-int.h =================================================================== --- gcc/wide-int.h 2013-10-20 09:38:41.175501696 +0100 +++ gcc/wide-int.h 2013-10-20 11:32:47.425353384 +0100 @@ -347,6 +347,9 @@ typedef generic_wide_int <wide_int_ref_s template <typename T1, typename T2> unsigned int get_binary_precision (const T1 &, const T2 &); + template <typename T1, typename T2> + void copy (T1 &, const T2 &); + #define UNARY_PREDICATE \ template <typename T> bool #define UNARY_FUNCTION \ @@ -870,10 +873,7 @@ inline wide_int_storage::wide_int_storag STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision); wide_int_ref xi (x); precision = xi.precision; - unsigned int l = xi.len; - for (unsigned int i = 0; i < l; ++i) - val[i] = xi.val[i]; - set_len (l); + wi::copy (*this, xi); } inline unsigned int @@ -969,6 +969,21 @@ wi::int_traits <wide_int_storage>::get_b return wide_int::create (wi::get_precision (x)); } +/* Copy the contents of Y to X, but keeping X's current precision. */ +template <typename T1, typename T2> +void +wi::copy (T1 &x, const T2 &y) +{ + HOST_WIDE_INT *xval = x.write_val (); + const HOST_WIDE_INT *yval = y.get_val (); + unsigned int len = y.get_len (); + unsigned int i = 0; + do + xval[i] = yval[i]; + while (++i < len); + x.set_len (len); +} + /* An N-bit integer. Until we can use typedef templates, use this instead. */ #define FIXED_WIDE_INT(N) \ generic_wide_int < fixed_wide_int_storage <N> > @@ -1012,10 +1027,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; - wide_int_ref xi (x, N); - len = xi.len; - for (unsigned int i = 0; i < len; ++i) - val[i] = xi.val[i]; + wi::copy (*this, wide_int_ref (x, N)); } template <int N> @@ -1716,16 +1728,7 @@ wi::neg (const T &x, bool *overflow) inline WI_UNARY_RESULT (T) wi::abs (const T &x) { - if (neg_p (x)) - return neg (x); - - WI_UNARY_RESULT_VAR (result, val, T, x); - wide_int_ref xi (x, get_precision (result)); - for (unsigned int i = 0; i < xi.len; ++i) - val[i] = xi.val[i]; - result.set_len (xi.len); - - return result; + return neg_p (x) ? neg (x) : x; } /* Return the result of sign-extending the low OFFSET bits of X. */ @@ -1760,9 +1763,7 @@ wi::zext (const T &x, unsigned int offse maintain canonization. */ if (offset >= precision) { - for (unsigned int i = 0; i < xi.len; ++i) - val[i] = xi.val[i]; - result.set_len (xi.len); + wi::copy (result, xi); return result; } @@ -1809,22 +1810,12 @@ wi::set_bit (const T &x, unsigned int bi inline WI_BINARY_RESULT (T1, T2) wi::min (const T1 &x, const T2 &y, signop sgn) { - WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y); + 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)) - { - wide_int_ref xi (x, precision); - for (unsigned int i = 0; i < xi.len; ++i) - val[i] = xi.val[i]; - result.set_len (xi.len); - } + wi::copy (result, wide_int_ref (x, precision)); else - { - wide_int_ref yi (y, precision); - for (unsigned int i = 0; i < yi.len; ++i) - val[i] = yi.val[i]; - result.set_len (yi.len); - } + wi::copy (result, wide_int_ref (y, precision)); return result; } @@ -1850,22 +1841,12 @@ wi::umin (const T1 &x, const T2 &y) inline WI_BINARY_RESULT (T1, T2) wi::max (const T1 &x, const T2 &y, signop sgn) { - WI_BINARY_RESULT_VAR (result, val, T1, x, T2, y); + 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)) - { - wide_int_ref xi (x, precision); - for (unsigned int i = 0; i < xi.len; ++i) - val[i] = xi.val[i]; - result.set_len (xi.len); - } + wi::copy (result, wide_int_ref (x, precision)); else - { - wide_int_ref yi (y, precision); - for (unsigned int i = 0; i < yi.len; ++i) - val[i] = yi.val[i]; - result.set_len (yi.len); - } + wi::copy (result, wide_int_ref (y, precision)); return result; }