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
--- 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;
 }
 
--- 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 via email to