public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: Richard Biener <rguenther@suse.de>,
	gcc-patches@gcc.gnu.org, richard.sandiford@arm.com
Subject: Re: [PATCH] wide-int: Allow up to 16320 bits wide_int and change widest_int precision to 32640 bits [PR102989]
Date: Mon, 9 Oct 2023 20:28:31 +0200	[thread overview]
Message-ID: <ZSRGT6p9ZgoQTulA@tucnak> (raw)
In-Reply-To: <ZSQDpxzGx8uy9ec5@tucnak>

[-- Attachment #1: Type: text/plain, Size: 18119 bytes --]

On Mon, Oct 09, 2023 at 03:44:10PM +0200, Jakub Jelinek wrote:
> Thanks, just quick answers, will work on patch adjustments after trying to
> get rid of rwide_int (seems dwarf2out has very limited needs from it, just
> some routine to construct it in GCed memory (and never change afterwards)
> from const wide_int_ref & or so, and then working operator ==,
> get_precision, elt, get_len and get_val methods, so I think we could just
> have a struct dw_wide_int { unsigned int prec, len; HOST_WIDE_INT val[1]; };
> and perform the methods on it after converting to a storage ref.

Now in patch form (again, incremental).

> > Does the variable-length memcpy pay for itself?  If so, perhaps that's a
> > sign that we should have a smaller inline buffer for this class (say 2 HWIs).
> 
> Guess I'll try to see what results in smaller .text size.

I've left the memcpy changes into a separate patch (incremental, attached).
Seems that second patch results in .text growth by 16256 bytes (0.04%),
though I'd bet it probably makes compile time tiny bit faster because it
replaces an out of line memcpy (caused by variable length) with inlined one.

With even the third one it shrinks by 84544 bytes (0.21% down), but the
extra statistics patch then shows massive number of allocations after
running make check-gcc check-g++ check-gfortran for just a minute or two.
On the widest_int side, I see (first number from sort | uniq -c | sort -nr,
second the estimated or final len)
7289034 4
 173586 5
  21819 6
i.e. there are tons of widest_ints which need len 4 (or perhaps just
have it as upper estimation), maybe even 5 would be nice.
On the wide_int side, I see
 155291 576
(supposedly because of bound_wide_int, where we create wide_int_ref from
the 576-bit precision bound_wide_int and then create 576-bit wide_int when
using unary or binary operation on that).

So, perhaps we could get away with say WIDEST_INT_MAX_INL_ELTS of 5 or 6
instead of 9 but keep WIDE_INT_MAX_INL_ELTS at 9 (or whatever is computed
from MAX_BITSIZE_MODE_ANY_INT?).  Or keep it at 9 for both (i.e. without
the third patch).

--- gcc/poly-int.h.jj	2023-10-09 14:37:45.883940062 +0200
+++ gcc/poly-int.h	2023-10-09 17:05:26.629828329 +0200
@@ -96,7 +96,7 @@ struct poly_coeff_traits<T, wi::VAR_PREC
 };
 
 template<typename T>
-struct poly_coeff_traits<T, wi::CONST_PRECISION>
+struct poly_coeff_traits<T, wi::INL_CONST_PRECISION>
 {
   typedef WI_UNARY_RESULT (T) result;
   typedef int int_type;
@@ -110,14 +110,13 @@ struct poly_coeff_traits<T, wi::CONST_PR
 };
 
 template<typename T>
-struct poly_coeff_traits<T, wi::WIDEST_CONST_PRECISION>
+struct poly_coeff_traits<T, wi::CONST_PRECISION>
 {
   typedef WI_UNARY_RESULT (T) result;
   typedef int int_type;
   /* These types are always signed.  */
   static const int signedness = 1;
   static const int precision = wi::int_traits<T>::precision;
-  static const int inl_precision = wi::int_traits<T>::inl_precision;
   static const int rank = precision * 2 / CHAR_BIT;
 
   template<typename Arg>
--- gcc/double-int.h.jj	2023-01-02 09:32:22.747280053 +0100
+++ gcc/double-int.h	2023-10-09 17:06:03.446317336 +0200
@@ -440,7 +440,7 @@ namespace wi
   template <>
   struct int_traits <double_int>
   {
-    static const enum precision_type precision_type = CONST_PRECISION;
+    static const enum precision_type precision_type = INL_CONST_PRECISION;
     static const bool host_dependent_precision = true;
     static const unsigned int precision = HOST_BITS_PER_DOUBLE_INT;
     static unsigned int get_precision (const double_int &);
--- gcc/wide-int.h.jj	2023-10-09 16:06:39.326805176 +0200
+++ gcc/wide-int.h	2023-10-09 17:29:20.016951691 +0200
@@ -343,8 +343,8 @@ template <int N> class widest_int_storag
 
 typedef generic_wide_int <wide_int_storage> wide_int;
 typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int;
-typedef generic_wide_int <widest_int_storage <WIDE_INT_MAX_INL_PRECISION> > widest_int;
-typedef generic_wide_int <widest_int_storage <WIDE_INT_MAX_INL_PRECISION * 2> > widest2_int;
+typedef generic_wide_int <widest_int_storage <WIDEST_INT_MAX_PRECISION> > widest_int;
+typedef generic_wide_int <widest_int_storage <WIDEST_INT_MAX_PRECISION * 2> > widest2_int;
 
 /* wi::storage_ref can be a reference to a primitive type,
    so this is the conservatively-correct setting.  */
@@ -394,13 +394,13 @@ namespace wi
     /* The integer has a variable precision but no defined signedness.  */
     VAR_PRECISION,
 
-    /* The integer has a constant precision (known at GCC compile time)
-       and is signed.  */
-    CONST_PRECISION,
-
-    /* Like CONST_PRECISION, but with WIDEST_INT_MAX_PRECISION or larger
-       precision where not all elements of arrays are always present.  */
-    WIDEST_CONST_PRECISION
+    /* The integer has a constant precision (known at GCC compile time),
+       is signed and all elements are in inline buffer.  */
+    INL_CONST_PRECISION,
+
+    /* Like INL_CONST_PRECISION, but elements can be heap allocated for
+       larger lengths.  */
+    CONST_PRECISION
   };
 
   /* This class, which has no default implementation, is expected to
@@ -410,15 +410,10 @@ namespace wi
        Classifies the type of T.
 
      static const unsigned int precision;
-       Only defined if precision_type == CONST_PRECISION or
-       precision_type == WIDEST_CONST_PRECISION.  Specifies the
+       Only defined if precision_type == INL_CONST_PRECISION or
+       precision_type == CONST_PRECISION.  Specifies the
        precision of all integers of type T.
 
-     static const unsigned int inl_precision;
-       Only defined if precision_type == WIDEST_CONST_PRECISION.
-       Specifies precision which is represented in the inline
-       arrays.
-
      static const bool host_dependent_precision;
        True if the precision of T depends (or can depend) on the host.
 
@@ -441,10 +436,10 @@ namespace wi
   struct binary_traits;
 
   /* Specify the result type for each supported combination of binary
-     inputs.  Note that CONST_PRECISION, WIDEST_CONST_PRECISION and
+     inputs.  Note that INL_CONST_PRECISION, CONST_PRECISION and
      VAR_PRECISION cannot be mixed, in order to give stronger type
-     checking.  When both inputs are CONST_PRECISION or both are
-     WIDEST_CONST_PRECISION, they must have the same precision.  */
+     checking.  When both inputs are INL_CONST_PRECISION or both are
+     CONST_PRECISION, they must have the same precision.  */
   template <typename T1, typename T2>
   struct binary_traits <T1, T2, FLEXIBLE_PRECISION, FLEXIBLE_PRECISION>
   {
@@ -461,7 +456,7 @@ namespace wi
   };
 
   template <typename T1, typename T2>
-  struct binary_traits <T1, T2, FLEXIBLE_PRECISION, CONST_PRECISION>
+  struct binary_traits <T1, T2, FLEXIBLE_PRECISION, INL_CONST_PRECISION>
   {
     /* Spelled out explicitly (rather than through FIXED_WIDE_INT)
        so as not to confuse gengtype.  */
@@ -474,10 +469,10 @@ namespace wi
   };
 
   template <typename T1, typename T2>
-  struct binary_traits <T1, T2, FLEXIBLE_PRECISION, WIDEST_CONST_PRECISION>
+  struct binary_traits <T1, T2, FLEXIBLE_PRECISION, CONST_PRECISION>
   {
     typedef generic_wide_int < widest_int_storage
-			       <int_traits <T2>::inl_precision> > result_type;
+			       <int_traits <T2>::precision> > result_type;
     typedef result_type operator_result;
     typedef bool predicate_result;
     typedef result_type signed_shift_result_type;
@@ -493,7 +488,7 @@ namespace wi
   };
 
   template <typename T1, typename T2>
-  struct binary_traits <T1, T2, CONST_PRECISION, FLEXIBLE_PRECISION>
+  struct binary_traits <T1, T2, INL_CONST_PRECISION, FLEXIBLE_PRECISION>
   {
     /* Spelled out explicitly (rather than through FIXED_WIDE_INT)
        so as not to confuse gengtype.  */
@@ -506,10 +501,10 @@ namespace wi
   };
 
   template <typename T1, typename T2>
-  struct binary_traits <T1, T2, WIDEST_CONST_PRECISION, FLEXIBLE_PRECISION>
+  struct binary_traits <T1, T2, CONST_PRECISION, FLEXIBLE_PRECISION>
   {
     typedef generic_wide_int < widest_int_storage
-			       <int_traits <T1>::inl_precision> > result_type;
+			       <int_traits <T1>::precision> > result_type;
     typedef result_type operator_result;
     typedef bool predicate_result;
     typedef result_type signed_shift_result_type;
@@ -517,7 +512,7 @@ namespace wi
   };
 
   template <typename T1, typename T2>
-  struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION>
+  struct binary_traits <T1, T2, INL_CONST_PRECISION, INL_CONST_PRECISION>
   {
     STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision);
     /* Spelled out explicitly (rather than through FIXED_WIDE_INT)
@@ -531,11 +526,11 @@ namespace wi
   };
 
   template <typename T1, typename T2>
-  struct binary_traits <T1, T2, WIDEST_CONST_PRECISION, WIDEST_CONST_PRECISION>
+  struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION>
   {
     STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision);
     typedef generic_wide_int < widest_int_storage
-			       <int_traits <T1>::inl_precision> > result_type;
+			       <int_traits <T1>::precision> > result_type;
     typedef result_type operator_result;
     typedef bool predicate_result;
     typedef result_type signed_shift_result_type;
@@ -1191,8 +1186,7 @@ inline wide_int_storage::wide_int_storag
 {
   STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision);
   STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION);
-  STATIC_ASSERT (wi::int_traits<T>::precision_type
-		 != wi::WIDEST_CONST_PRECISION);
+  STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::INL_CONST_PRECISION);
   WIDE_INT_REF_FOR (T) xi (x);
   precision = xi.precision;
   if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
@@ -1246,8 +1240,7 @@ wide_int_storage::operator = (const T &x
 {
   STATIC_ASSERT (!wi::int_traits<T>::host_dependent_precision);
   STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::CONST_PRECISION);
-  STATIC_ASSERT (wi::int_traits<T>::precision_type
-		 != wi::WIDEST_CONST_PRECISION);
+  STATIC_ASSERT (wi::int_traits<T>::precision_type != wi::INL_CONST_PRECISION);
   WIDE_INT_REF_FOR (T) xi (x);
   if (UNLIKELY (precision != xi.precision))
     {
@@ -1391,7 +1384,7 @@ namespace wi
   template <int N>
   struct int_traits < fixed_wide_int_storage <N> >
   {
-    static const enum precision_type precision_type = CONST_PRECISION;
+    static const enum precision_type precision_type = INL_CONST_PRECISION;
     static const bool host_dependent_precision = false;
     static const bool is_sign_extended = true;
     static const bool needs_write_val_arg = false;
@@ -1504,7 +1497,7 @@ class GTY(()) widest_int_storage
 private:
   union
   {
-    HOST_WIDE_INT val[WIDE_INT_MAX_HWIS (N)];
+    HOST_WIDE_INT val[WIDE_INT_MAX_INL_ELTS];
     HOST_WIDE_INT *valp;
   } GTY((skip)) u;
   unsigned int len;
@@ -1536,13 +1529,11 @@ namespace wi
   template <int N>
   struct int_traits < widest_int_storage <N> >
   {
-    static const enum precision_type precision_type = WIDEST_CONST_PRECISION;
+    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 bool needs_write_val_arg = true;
-    static const unsigned int precision
-      = N / WIDE_INT_MAX_INL_PRECISION * WIDEST_INT_MAX_PRECISION;
-    static const unsigned int inl_precision = N;
+    static const unsigned int precision = N;
     template <typename T1, typename T2>
     static WIDEST_INT (N) get_binary_result (const T1 &, const T2 &);
     template <typename T1, typename T2>
@@ -1561,8 +1552,7 @@ inline widest_int_storage <N>::widest_in
   /* Check for type compatibility.  We don't want to initialize a
      widest integer from something like a wide_int.  */
   WI_BINARY_RESULT (T, WIDEST_INT (N)) *assertion ATTRIBUTE_UNUSED;
-  wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N / WIDE_INT_MAX_INL_PRECISION
-					    * WIDEST_INT_MAX_PRECISION));
+  wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N));
 }
 
 template <int N>
@@ -1570,7 +1560,7 @@ inline
 widest_int_storage <N>::widest_int_storage (const widest_int_storage &x)
 {
   len = x.len;
-  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     {
       u.valp = XNEWVEC (HOST_WIDE_INT, len);
       memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
@@ -1582,7 +1572,7 @@ widest_int_storage <N>::widest_int_stora
 template <int N>
 inline widest_int_storage <N>::~widest_int_storage ()
 {
-  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     XDELETEVEC (u.valp);
 }
 
@@ -1590,14 +1580,14 @@ template <int N>
 inline widest_int_storage <N>&
 widest_int_storage <N>::operator = (const widest_int_storage <N> &x)
 {
-  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     {
       if (this == &x)
 	return *this;
       XDELETEVEC (u.valp);
     }
   len = x.len;
-  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     {
       u.valp = XNEWVEC (HOST_WIDE_INT, len);
       memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
@@ -1615,11 +1605,10 @@ widest_int_storage <N>::operator = (cons
   /* Check for type compatibility.  We don't want to assign a
      widest integer from something like a wide_int.  */
   WI_BINARY_RESULT (T, WIDEST_INT (N)) *assertion ATTRIBUTE_UNUSED;
-  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     XDELETEVEC (u.valp);
   len = 0;
-  wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N / WIDE_INT_MAX_INL_PRECISION
-					    * WIDEST_INT_MAX_PRECISION));
+  wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N));
   return *this;
 }
 
@@ -1627,14 +1616,14 @@ template <int N>
 inline unsigned int
 widest_int_storage <N>::get_precision () const
 {
-  return N / WIDE_INT_MAX_INL_PRECISION * WIDEST_INT_MAX_PRECISION;
+  return N;
 }
 
 template <int N>
 inline const HOST_WIDE_INT *
 widest_int_storage <N>::get_val () const
 {
-  return UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT) ? u.valp : u.val;
+  return UNLIKELY (len > WIDE_INT_MAX_INL_ELTS) ? u.valp : u.val;
 }
 
 template <int N>
@@ -1648,10 +1637,10 @@ template <int N>
 inline HOST_WIDE_INT *
 widest_int_storage <N>::write_val (unsigned int l)
 {
-  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     XDELETEVEC (u.valp);
   len = l;
-  if (UNLIKELY (l > N / HOST_BITS_PER_WIDE_INT))
+  if (UNLIKELY (l > WIDE_INT_MAX_INL_ELTS))
     {
       u.valp = XNEWVEC (HOST_WIDE_INT, l);
       return u.valp;
@@ -1664,8 +1653,8 @@ inline void
 widest_int_storage <N>::set_len (unsigned int l, bool)
 {
   gcc_checking_assert (l <= len);
-  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT)
-      && l <= N / HOST_BITS_PER_WIDE_INT)
+  if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS)
+      && l <= WIDE_INT_MAX_INL_ELTS)
     {
       HOST_WIDE_INT *valp = u.valp;
       memcpy (u.val, valp, l * sizeof (u.val[0]));
@@ -1721,7 +1710,7 @@ inline unsigned int
 wi::int_traits < widest_int_storage <N> >::
 get_binary_precision (const T1 &, const T2 &)
 {
-  return N / WIDE_INT_MAX_INL_PRECISION * WIDEST_INT_MAX_PRECISION;
+  return N;
 }
 
 /* A reference to one element of a trailing_wide_ints structure.  */
@@ -2193,8 +2182,8 @@ template <typename T1, typename T2>
 inline unsigned int
 wi::get_binary_precision (const T1 &x, const T2 &y)
 {
-  return wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_precision (x,
-									   y);
+  using res_traits = wi::int_traits <WI_BINARY_RESULT (T1, T2)>;
+  return res_traits::get_binary_precision (x, y);
 }
 
 /* Copy the contents of Y to X, but keeping X's current precision.  */
@@ -2683,8 +2672,8 @@ wi::bswap (const T &x)
   WI_UNARY_RESULT_VAR (result, val, T, x);
   unsigned int precision = get_precision (result);
   WIDE_INT_REF_FOR (T) xi (x, precision);
-  if (result.needs_write_val_arg)
-    gcc_unreachable (); /* bswap on widest_int makes no sense.  */
+  static_assert (!result.needs_write_val_arg,
+		 "bswap on widest_int makes no sense");
   result.set_len (bswap_large (val, xi.val, xi.len, precision));
   return result;
 }
@@ -2697,8 +2686,8 @@ wi::bitreverse (const T &x)
   WI_UNARY_RESULT_VAR (result, val, T, x);
   unsigned int precision = get_precision (result);
   WIDE_INT_REF_FOR (T) xi (x, precision);
-  if (result.needs_write_val_arg)
-    gcc_unreachable (); /* bitreverse on widest_int makes no sense.  */
+  static_assert (!result.needs_write_val_arg,
+		 "bitreverse on widest_int makes no sense");
   result.set_len (bitreverse_large (val, xi.val, xi.len, precision));
   return result;
 }
@@ -3127,8 +3116,8 @@ wi::mul_high (const T1 &x, const T2 &y,
   unsigned int precision = get_precision (result);
   WIDE_INT_REF_FOR (T1) xi (x, precision);
   WIDE_INT_REF_FOR (T2) yi (y, precision);
-  if (result.needs_write_val_arg)
-    gcc_unreachable (); /* mul_high on widest_int doesn't make sense.  */
+  static_assert (!result.needs_write_val_arg,
+		 "mul_high on widest_int doesn't make sense");
   result.set_len (mul_internal (val, xi.val, xi.len,
 				yi.val, yi.len, precision,
 				sgn, 0, true));
--- gcc/tree.h.jj	2023-10-09 14:37:45.880940104 +0200
+++ gcc/tree.h	2023-10-09 17:04:47.138376452 +0200
@@ -6259,13 +6259,10 @@ namespace wi
   struct int_traits <extended_tree <N> >
   {
     static const enum precision_type precision_type
-      = N == ADDR_MAX_PRECISION ? CONST_PRECISION : WIDEST_CONST_PRECISION;
+      = N == ADDR_MAX_PRECISION ? INL_CONST_PRECISION : CONST_PRECISION;
     static const bool host_dependent_precision = false;
     static const bool is_sign_extended = true;
     static const unsigned int precision = N;
-    static const unsigned int inl_precision
-      = N == ADDR_MAX_PRECISION ? 0
-	     : N / WIDEST_INT_MAX_PRECISION * WIDE_INT_MAX_INL_PRECISION;
   };
 
   typedef extended_tree <WIDEST_INT_MAX_PRECISION> widest_extended_tree;

	Jakub

[-- Attachment #2: Q012sd --]
[-- Type: text/plain, Size: 2459 bytes --]

--- gcc/wide-int.h.jj	2023-10-09 17:48:45.027810111 +0200
+++ gcc/wide-int.h	2023-10-09 18:05:33.230847241 +0200
@@ -1196,15 +1196,12 @@ inline wide_int_storage::wide_int_storag
 
 inline wide_int_storage::wide_int_storage (const wide_int_storage &x)
 {
-  len = x.len;
-  precision = x.precision;
+  memcpy (this, &x, sizeof (wide_int_storage));
   if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
     {
       u.valp = XNEWVEC (HOST_WIDE_INT, CEIL (precision, HOST_BITS_PER_WIDE_INT));
       memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
     }
-  else if (LIKELY (precision))
-    memcpy (u.val, x.u.val, len * sizeof (HOST_WIDE_INT));
 }
 
 inline wide_int_storage::~wide_int_storage ()
@@ -1222,15 +1219,12 @@ wide_int_storage::operator = (const wide
 	return *this;
       XDELETEVEC (u.valp);
     }
-  len = x.len;
-  precision = x.precision;
+  memcpy (this, &x, sizeof (wide_int_storage));
   if (UNLIKELY (precision > WIDE_INT_MAX_INL_PRECISION))
     {
       u.valp = XNEWVEC (HOST_WIDE_INT, CEIL (precision, HOST_BITS_PER_WIDE_INT));
       memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
     }
-  else if (LIKELY (precision))
-    memcpy (u.val, x.u.val, len * sizeof (HOST_WIDE_INT));
   return *this;
 }
 
@@ -1559,14 +1553,12 @@ template <int N>
 inline
 widest_int_storage <N>::widest_int_storage (const widest_int_storage &x)
 {
-  len = x.len;
+  memcpy (this, &x, sizeof (widest_int_storage));
   if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     {
       u.valp = XNEWVEC (HOST_WIDE_INT, len);
       memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
     }
-  else
-    memcpy (u.val, x.u.val, len * sizeof (HOST_WIDE_INT));
 }
 
 template <int N>
@@ -1578,7 +1570,7 @@ inline widest_int_storage <N>::~widest_i
 
 template <int N>
 inline widest_int_storage <N>&
-widest_int_storage <N>::operator = (const widest_int_storage <N> &x)
+widest_int_storage <N>::operator = (const widest_int_storage &x)
 {
   if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     {
@@ -1586,14 +1578,12 @@ widest_int_storage <N>::operator = (cons
 	return *this;
       XDELETEVEC (u.valp);
     }
-  len = x.len;
+  memcpy (this, &x, sizeof (widest_int_storage));
   if (UNLIKELY (len > WIDE_INT_MAX_INL_ELTS))
     {
       u.valp = XNEWVEC (HOST_WIDE_INT, len);
       memcpy (u.valp, x.u.valp, len * sizeof (HOST_WIDE_INT));
     }
-  else
-    memcpy (u.val, x.u.val, len * sizeof (HOST_WIDE_INT));
   return *this;
 }
 

[-- Attachment #3: Q012se --]
[-- Type: text/plain, Size: 1687 bytes --]

--- gcc/wide-int.h.jj	2023-10-09 18:05:33.230847241 +0200
+++ gcc/wide-int.h	2023-10-09 19:35:04.283138460 +0200
@@ -233,17 +233,9 @@ along with GCC; see the file COPYING3.
    the same result as X + X; the precision of the shift amount Y
    can be arbitrarily different from X.  */
 
-/* The MAX_BITSIZE_MODE_ANY_INT is automatically generated by a very
-   early examination of the target's mode file.  The WIDE_INT_MAX_INL_ELTS
-   can accomodate at least 1 more bit so that unsigned numbers of that
-   mode can be represented as a signed value.  Note that it is still
-   possible to create fixed_wide_ints that have precisions greater than
-   MAX_BITSIZE_MODE_ANY_INT.  This can be useful when representing a
-   double-width multiplication result, for example.  */
-#define WIDE_INT_MAX_INL_ELTS \
-  ((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT) \
-   / HOST_BITS_PER_WIDE_INT)
-
+/* Number of bits that can be stored in inline arrays in wide_int or
+   widest_int.  */
+#define WIDE_INT_MAX_INL_ELTS 3
 #define WIDE_INT_MAX_INL_PRECISION \
   (WIDE_INT_MAX_INL_ELTS * HOST_BITS_PER_WIDE_INT)
 
--- gcc/cfgloop.h.jj	2023-10-09 17:48:35.620940437 +0200
+++ gcc/cfgloop.h	2023-10-09 19:50:18.006468381 +0200
@@ -44,7 +44,11 @@ enum iv_extend_code
   IV_UNKNOWN_EXTEND
 };
 
-typedef generic_wide_int <fixed_wide_int_storage <WIDE_INT_MAX_INL_PRECISION> >
+#define BOUND_WIDE_INT_MAX_PRECISION \
+  ((MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT) \
+   & ~(HOST_BITS_PER_WIDE_INT - 1))
+
+typedef generic_wide_int <fixed_wide_int_storage <BOUND_WIDE_INT_MAX_PRECISION> >
   bound_wide_int;
 
 /* The structure describing a bound on number of iterations of a loop.  */

  reply	other threads:[~2023-10-09 18:28 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-09 10:55 Jakub Jelinek
2023-10-09 12:54 ` Richard Sandiford
2023-10-09 13:44   ` Jakub Jelinek
2023-10-09 18:28     ` Jakub Jelinek [this message]
2023-10-10 17:41       ` Richard Sandiford
2023-10-10 18:13         ` Jakub Jelinek
2023-10-09 14:59 ` [PATCH] wide-int: Remove rwide_int, introduce dw_wide_int Jakub Jelinek
2023-10-10  9:30   ` Richard Biener
2023-10-10  9:49     ` Jakub Jelinek
2023-10-10 13:42     ` [PATCH] dwarf2out: Stop using wide_int in GC structures Jakub Jelinek
2023-10-10 13:43       ` Richard Biener
2023-10-11 16:47 [PATCH] wide-int: Allow up to 16320 bits wide_int and change widest_int precision to 32640 bits [PR102989] Jakub Jelinek
2023-10-12 10:54 ` Richard Sandiford
2023-10-12 11:10   ` Jakub Jelinek
2023-10-12 11:34     ` Richard Sandiford
2023-10-12 11:10 ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZSRGT6p9ZgoQTulA@tucnak \
    --to=jakub@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=rguenther@suse.de \
    --cc=richard.sandiford@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).