Patchwork [wide-int] Add a copy helper routine

login
register
mail settings
Submitter Richard Sandiford
Date Oct. 20, 2013, 10:35 a.m.
Message ID <87sivw44dn.fsf@talisman.default>
Download mbox | patch
Permalink /patch/284962/
State New
Headers show

Comments

Richard Sandiford - Oct. 20, 2013, 10:35 a.m.
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?

Thanks,
Richard
Richard Guenther - Oct. 20, 2013, 12:49 p.m.
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;
> }
>

Patch

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;
 }