Hi!

On Tue, Aug 29, 2023 at 05:09:52PM +0200, Jakub Jelinek via Gcc-patches wrote:
> On Tue, Aug 29, 2023 at 11:42:48AM +0100, Richard Sandiford wrote:
> > > I'll note tree-ssa-loop-niter.cc also uses GMP in some cases, widest_int
> > > is really trying to be poor-mans GMP by limiting the maximum precision.
> > 
> > I'd characterise widest_int as "a wide_int that is big enough to hold
> > all supported integer types, without losing sign information".  It's
> > not big enough to do arbitrary arithmetic without losing precision
> > (in the way that GMP is).
> > 
> > If the new limit on integer sizes is 65535 bits for all targets,
> > then I think that means that widest_int needs to become a 65536-bit type.
> > (But not with all bits represented all the time, of course.)
> 
> If the widest_int storage would be dependent on the len rather than
> precision for how it is stored, then I think we'd need a new method which
> would be called at the start of filling the limbs where we'd tell how many
> limbs there would be (i.e. what will set_len be called with later on), and
> do nothing for all storages but the new widest_int_storage.

So, I've spent some time on this.  While wide_int is in the patch a 
fixed/variable
number of limbs (aka len) storage depending on precision (precision >
WIDE_INT_MAX_PRECISION means heap allocated limb array, otherwise it is
inline), widest_int has always very large precision
(WIDEST_INT_MAX_PRECISION, currently defined to the INTEGER_CST imposed
limitation of 255 64-bit limbs) but uses inline array for length
corresponding up to WIDE_INT_MAX_PRECISION bits and for larger one uses
similarly to wide_int a heap allocated array of limbs.
These changes make both wide_int and widest_int obviously non-POD, not
trivially default constructible, nor trivially copy constructible, trivially
destructible, trivially copyable, so not a good fit for GC and some vec
operations.
One common use of wide_int in GC structures was in dwarf2out.{h,cc}; but as
large _BitInt constants don't appear in RTL, we really don't need such large
precisions there.
So, for wide_int the patch introduces rwide_int, restricted wide_int, which
acts like the old wide_int (except that it is now trivially default
constructible and has assertions precision isn't set above
WIDE_INT_MAX_PRECISION).
For widest_int, the nastiness is that because it always has huge precision
of 16320 right now,
a) we need to be told upfront in wide-int.h before calling the large
   value internal functions in wide-int.cc how many elements we'll need for
   the result (some reasonable upper estimate is fine)
b) various of the wide-int.cc functions were lazy and assumed precision is
   small enough and often used up to that many elements, which is
   undesirable; so, it now tries to decreas that and use xi.len etc. based
   estimates instead if possible (sometimes only if precision is above
   WIDE_INT_MAX_PRECISION)
c) with the higher precision, behavior changes for lrshift (-1, 2) etc. or
   unsigned division with dividend having most significant bit set in
   widest_int - while such values were considered to be above or equal to
   1 << (WIDE_INT_MAX_PRECISION - 2), now they are with
   WIDEST_INT_MAX_PRECISION and so much larger; but lrshift on widest_int
   is I think only done in ccp and I'd strongly hope that we treat the
   values as unsigned and so usually much smaller length; so it is just
   when we call wi::lrshift (-1, 2) or similar that results change.
I've noticed that for wide_int or widest_int references even simple
operations like eq_p liked to allocate and immediately free huge buffers,
which was caused by wide_int doing allocation on creation with a particular
precision and e.g. get_binary_precision running into that.  So, I've
duplicated that to avoid the allocations when all we need is just a
precision.

The patch below doesn't actually build anymore since the vec.h asserts
(which point to useful stuff though), so temporarily I've applied it also
with
--- gcc/vec.h.xx        2023-09-28 12:56:09.055786055 +0200
+++ gcc/vec.h   2023-09-28 13:15:31.760487111 +0200
@@ -1197,7 +1197,7 @@ template<typename T, typename A>
 inline void
 vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
 {
-  static_assert (vec_detail::is_trivially_copyable_or_pair <T>::value, "");
+//  static_assert (vec_detail::is_trivially_copyable_or_pair <T>::value, "");
   if (length () > 1)
     gcc_qsort (address (), length (), sizeof (T), cmp);
 }
@@ -1422,7 +1422,7 @@ template<typename T>
 void
 gt_ggc_mx (vec<T, va_gc> *v)
 {
-  static_assert (std::is_trivially_destructible <T>::value, "");
+//  static_assert (std::is_trivially_destructible <T>::value, "");
   extern void gt_ggc_mx (T &);
   for (unsigned i = 0; i < v->length (); i++)
     gt_ggc_mx ((*v)[i]);
hack.  The two spots that trigger are tree-ssa-loop-niter.cc doing qsort on
widest_int vector (to be exact, swapping elements in the vector of
widest_int or wide_int by memcpy actually would work, the reason it has
non-trivial destructor and copy assignment/copy constructor is to make sure
distinct objects have (if needed) distinct heap allocations and that those
are freed in the end, but the bitwise memcpy swapping preserves that), and
omp_general.cc using two widest_int members in a GC structure.  For some
reason, a more important problem isn't diagnosed, loop and nb_iter_bound
structs (also GC) having widest_int members (first one 2, second one just
one).  And then there is e.g. another issue with slsr, which allocates
structs containing widest_int in obstack, not expecting it would need to
construct those (and where to destruct them).  Also, ipa_bits contains
2 widest_int members in GC allocated structure.  Actually the reason
is quite obvious, my assert has been added just for GC vec of non-trivially
destructible types, neither loop, nor ipa_bits are used in vectors.  Bet
we should make wide_int_storage and widest_int_storage GTY ((user)) and
just declare but don't define the handlers or something similar.

And, now the question is what to do about this.  I guess for omp_general
I could just use generic_wide_int <fixed_wide_int_storage <1024> > or
something similar, after all the widest_int wasn't really great when it
had maximum precision of WIDE_INT_MAX_PRECISION, different values on
different targets, it has very few uses and is easy to change (thinking
about this, makes me wonder what we do for offloading if offload host
has different WIDE_INT_MAX_PRECISION from offload target).

But the more important question is what to do about loop/niters analysis.
I think for number of iteration analysis it might be ok to punt somehow
(if there is a way to tell that number of iterations is unknown) if we
get some bound which is too large to be expressible in some reasonably small
fixed precision (whether it is WIDE_INT_MAX_PRECISION, or something
different is a question).  We could either introduce yet another widest_int
like storage which would have still WIDEST_INT_MAX_PRECISION precision, but
would ICE if length is set to something above its fixed width.  One problem
is that the write_val estimations are often just conservatively larger and
could trigger even if the value fits in the end.  Or we could use
generic_wide_int <fixed_wide_int_storage <WIDE_INT_MAX_PRECISION> > (perhaps
call that rwidest_int), the drawback would be that it would be slightly harder
to use as it has different precision from widest_int, we'd need to do some
from on it or the like.  Plus I really don't know the niters code to know
how to punt.

ipa_bits is even worse, because unlike niter analysis, I think it is very
much desirable to support IPA VRP of all supported _BitInt sizes.  Shall
we perhaps use trailing_wide_int storage in there, or conditionally
rwidest_int vs. INTEGER_CSTs for stuff that doesn't fit, something else?

What about slsr?  This is after bitint lowering, so it shouldn't be
performing opts on larger BITINT_TYPEs and so could also go with the
rwidest_int.

With the above vec.h hack the short (in number of lines, otherwise
it is large, each 16319 bit decimal constant is huge) testcase below works,
but even make check-gcc RUNTESTFLAGS=dg.exp=bitint* (i.e. the compile only
tests) show some ICEs, some of them due to widest_int in loop, others in
slsr, others to be debugged.

As for the qsort in niters, if we change niters to use some rwidest_int,
either fixed or something new, then the sorting problem could go away.
Another option would be to rename vec_detail::is_trivially_copyable_or_pair
trait to say vec_detail::is_qsort_sortable and allow code to amend that
trait on a type by type basis when needed after analysing it works correctly
for some further type (like wide_int or widest_int).  But am not sure it
would work if widest-int.h is included before vec.h etc.

Your thoughts on all of this?

--- gcc/wide-int.h.jj   2023-09-27 10:37:39.456836804 +0200
+++ gcc/wide-int.h      2023-09-28 14:55:40.059632413 +0200
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.
    other longer storage GCC representations (rtl and tree).
 
    The actual precision of a wide_int depends on the flavor.  There
-   are three predefined flavors:
+   are four predefined flavors:
 
      1) wide_int (the default).  This flavor does the math in the
      precision of its input arguments.  It is assumed (and checked)
@@ -53,6 +53,10 @@ along with GCC; see the file COPYING3.
      multiply, division, shifts, comparisons, and operations that need
      overflow detected), the signedness must be specified separately.
 
+     For precisions up to WIDE_INT_MAX_PRECISION, it uses an inline
+     buffer in the type, for larger precisions up to WIDEST_INT_MAX_PRECISION
+     it uses a pointer to heap allocated buffer.
+
      2) offset_int.  This is a fixed-precision integer that can hold
      any address offset, measured in either bits or bytes, with at
      least one extra sign bit.  At the moment the maximum address
@@ -76,11 +80,15 @@ along with GCC; see the file COPYING3.
        wi::leu_p (a, b) as a more efficient short-hand for
        "a >= 0 && a <= b". ]
 
+     3) rwide_int.  Restricted wide_int.  This is similar to
+     wide_int, but maximum possible precision is WIDE_INT_MAX_PRECISION
+     and it always uses an inline buffer.  offset_int and rwide_int are
+     GC-friendly, wide_int and widest_int are not.
+
      3) widest_int.  This representation is an approximation of
      infinite precision math.  However, it is not really infinite
      precision math as in the GMP library.  It is really finite
-     precision math where the precision is 4 times the size of the
-     largest integer that the target port can represent.
+     precision math where the precision is WIDEST_INT_MAX_PRECISION.
 
      Like offset_int, widest_int is wider than all the values that
      it needs to represent, so the integers are logically signed.
@@ -242,6 +250,13 @@ along with GCC; see the file COPYING3.
 
 #define WIDE_INT_MAX_PRECISION (WIDE_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT)
 
+/* Precision of widest_int and largest _BitInt precision + 1 we can
+   support.  */
+#define WIDEST_INT_MAX_ELTS 255
+#define WIDEST_INT_MAX_PRECISION (WIDEST_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT)
+
+STATIC_ASSERT (WIDE_INT_MAX_ELTS < WIDEST_INT_MAX_ELTS);
+
 /* This is the max size of any pointer on any machine.  It does not
    seem to be as easy to sniff this out of the machine description as
    it is for MAX_BITSIZE_MODE_ANY_INT since targets may support
@@ -307,17 +322,19 @@ along with GCC; see the file COPYING3.
 #define WI_BINARY_RESULT_VAR(RESULT, VAL, T1, X, T2, Y) \
   WI_BINARY_RESULT (T1, T2) RESULT = \
     wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_result (X, Y); \
-  HOST_WIDE_INT *VAL = RESULT.write_val ()
+  HOST_WIDE_INT *VAL = RESULT.write_val (0)
 
 /* Similar for the result of a unary operation on X, which has type T.  */
 #define WI_UNARY_RESULT_VAR(RESULT, VAL, T, X) \
   WI_UNARY_RESULT (T) RESULT = \
     wi::int_traits <WI_UNARY_RESULT (T)>::get_binary_result (X, X); \
-  HOST_WIDE_INT *VAL = RESULT.write_val ()
+  HOST_WIDE_INT *VAL = RESULT.write_val (0)
 
 template <typename T> class generic_wide_int;
 template <int N> class fixed_wide_int_storage;
 class wide_int_storage;
+class rwide_int_storage;
+template <int N> class widest_int_storage;
 
 /* An N-bit integer.  Until we can use typedef templates, use this instead.  */
 #define FIXED_WIDE_INT(N) \
@@ -325,10 +342,9 @@ class wide_int_storage;
 
 typedef generic_wide_int <wide_int_storage> wide_int;
 typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int;
-typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION) widest_int;
-/* Spelled out explicitly (rather than through FIXED_WIDE_INT)
-   so as not to confuse gengtype.  */
-typedef generic_wide_int < fixed_wide_int_storage <WIDE_INT_MAX_PRECISION * 2> 
> widest2_int;
+typedef generic_wide_int <rwide_int_storage> rwide_int;
+typedef generic_wide_int <widest_int_storage <WIDE_INT_MAX_PRECISION> > 
widest_int;
+typedef generic_wide_int <widest_int_storage <WIDE_INT_MAX_PRECISION * 2> > 
widest2_int;
 
 /* wi::storage_ref can be a reference to a primitive type,
    so this is the conservatively-correct setting.  */
@@ -380,7 +396,11 @@ namespace wi
 
     /* The integer has a constant precision (known at GCC compile time)
        and is signed.  */
-    CONST_PRECISION
+    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
   };
 
   /* This class, which has no default implementation, is expected to
@@ -390,9 +410,15 @@ namespace wi
        Classifies the type of T.
 
      static const unsigned int precision;
-       Only defined if precision_type == CONST_PRECISION.  Specifies the
+       Only defined if precision_type == CONST_PRECISION or
+       precision_type == WIDEST_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.
 
@@ -415,9 +441,10 @@ namespace wi
   struct binary_traits;
 
   /* Specify the result type for each supported combination of binary
-     inputs.  Note that CONST_PRECISION and VAR_PRECISION cannot be
-     mixed, in order to give stronger type checking.  When both inputs
-     are CONST_PRECISION, they must have the same precision.  */
+     inputs.  Note that CONST_PRECISION, WIDEST_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.  */
   template <typename T1, typename T2>
   struct binary_traits <T1, T2, FLEXIBLE_PRECISION, FLEXIBLE_PRECISION>
   {
@@ -447,6 +474,17 @@ namespace wi
   };
 
   template <typename T1, typename T2>
+  struct binary_traits <T1, T2, FLEXIBLE_PRECISION, WIDEST_CONST_PRECISION>
+  {
+    typedef generic_wide_int < widest_int_storage
+                              <int_traits <T2>::inl_precision> > result_type;
+    typedef result_type operator_result;
+    typedef bool predicate_result;
+    typedef result_type signed_shift_result_type;
+    typedef bool signed_predicate_result;
+  };
+
+  template <typename T1, typename T2>
   struct binary_traits <T1, T2, VAR_PRECISION, FLEXIBLE_PRECISION>
   {
     typedef wide_int result_type;
@@ -468,6 +506,17 @@ namespace wi
   };
 
   template <typename T1, typename T2>
+  struct binary_traits <T1, T2, WIDEST_CONST_PRECISION, FLEXIBLE_PRECISION>
+  {
+    typedef generic_wide_int < widest_int_storage
+                              <int_traits <T1>::inl_precision> > result_type;
+    typedef result_type operator_result;
+    typedef bool predicate_result;
+    typedef result_type signed_shift_result_type;
+    typedef bool signed_predicate_result;
+  };
+
+  template <typename T1, typename T2>
   struct binary_traits <T1, T2, CONST_PRECISION, CONST_PRECISION>
   {
     STATIC_ASSERT (int_traits <T1>::precision == int_traits <T2>::precision);
@@ -482,6 +531,18 @@ namespace wi
   };
 
   template <typename T1, typename T2>
+  struct binary_traits <T1, T2, WIDEST_CONST_PRECISION, WIDEST_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;
+    typedef result_type operator_result;
+    typedef bool predicate_result;
+    typedef result_type signed_shift_result_type;
+    typedef bool signed_predicate_result;
+  };
+
+  template <typename T1, typename T2>
   struct binary_traits <T1, T2, VAR_PRECISION, VAR_PRECISION>
   {
     typedef wide_int result_type;
@@ -709,8 +770,10 @@ wi::storage_ref::get_val () const
    Although not required by generic_wide_int itself, writable storage
    classes can also provide the following functions:
 
-   HOST_WIDE_INT *write_val ()
-     Get a modifiable version of get_val ()
+   HOST_WIDE_INT *write_val (unsigned int)
+     Get a modifiable version of get_val ().  The argument should be
+     upper estimation for LEN (ignored by all storages but
+     widest_int_storage).
 
    unsigned int set_len (unsigned int len)
      Set the value returned by get_len () to LEN.  */
@@ -777,6 +840,8 @@ public:
 
   static const bool is_sign_extended
     = wi::int_traits <generic_wide_int <storage> >::is_sign_extended;
+  static const bool needs_write_val_arg
+    = wi::int_traits <generic_wide_int <storage> >::needs_write_val_arg;
 };
 
 template <typename storage>
@@ -1049,6 +1114,7 @@ namespace wi
     static const enum precision_type precision_type = VAR_PRECISION;
     static const bool host_dependent_precision = HDP;
     static const bool is_sign_extended = SE;
+    static const bool needs_write_val_arg = false;
   };
 }
 
@@ -1065,7 +1131,11 @@ namespace wi
 class GTY(()) wide_int_storage
 {
 private:
-  HOST_WIDE_INT val[WIDE_INT_MAX_ELTS];
+  union
+  {
+    HOST_WIDE_INT val[WIDE_INT_MAX_ELTS];
+    HOST_WIDE_INT *valp;
+  } GTY((skip)) u;
   unsigned int len;
   unsigned int precision;
 
@@ -1073,14 +1143,17 @@ public:
   wide_int_storage ();
   template <typename T>
   wide_int_storage (const T &);
+  wide_int_storage (const wide_int_storage &);
+  ~wide_int_storage ();
 
   /* The standard generic_wide_int storage methods.  */
   unsigned int get_precision () const;
   const HOST_WIDE_INT *get_val () const;
   unsigned int get_len () const;
-  HOST_WIDE_INT *write_val ();
+  HOST_WIDE_INT *write_val (unsigned int);
   void set_len (unsigned int, bool = false);
 
+  wide_int_storage &operator = (const wide_int_storage &);
   template <typename T>
   wide_int_storage &operator = (const T &);
 
@@ -1099,12 +1172,15 @@ namespace wi
     /* 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;
+    static const bool needs_write_val_arg = false;
     template <typename T1, typename T2>
     static wide_int get_binary_result (const T1 &, const T2 &);
+    template <typename T1, typename T2>
+    static unsigned int get_binary_precision (const T1 &, const T2 &);
   };
 }
 
-inline wide_int_storage::wide_int_storage () {}
+inline wide_int_storage::wide_int_storage () : precision (0) {}
 
 /* Initialize the storage from integer X, in its natural precision.
    Note that we do not allow integers with host-dependent precision
@@ -1113,21 +1189,75 @@ inline wide_int_storage::wide_int_storag
 template <typename T>
 inline wide_int_storage::wide_int_storage (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>::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);
   WIDE_INT_REF_FOR (T) xi (x);
   precision = xi.precision;
+  if (UNLIKELY (precision > WIDE_INT_MAX_PRECISION))
+    u.valp = XNEWVEC (HOST_WIDE_INT, CEIL (precision, HOST_BITS_PER_WIDE_INT));
   wi::copy (*this, xi);
 }
 
+inline wide_int_storage::wide_int_storage (const wide_int_storage &x)
+{
+  len = x.len;
+  precision = x.precision;
+  if (UNLIKELY (precision > WIDE_INT_MAX_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
+    memcpy (u.val, x.u.val, len * sizeof (HOST_WIDE_INT));
+}
+
+inline wide_int_storage::~wide_int_storage ()
+{
+  if (UNLIKELY (precision > WIDE_INT_MAX_PRECISION))
+    XDELETEVEC (u.valp);
+}
+
+inline wide_int_storage&
+wide_int_storage::operator = (const wide_int_storage &x)
+{
+  if (UNLIKELY (precision > WIDE_INT_MAX_PRECISION))
+    {
+      if (this == &x)
+       return *this;
+      XDELETEVEC (u.valp);
+    }
+  len = x.len;
+  precision = x.precision;
+  if (UNLIKELY (precision > WIDE_INT_MAX_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
+    memcpy (u.val, x.u.val, len * sizeof (HOST_WIDE_INT));
+  return *this;
+}
+
 template <typename T>
 inline wide_int_storage&
 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>::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);
   WIDE_INT_REF_FOR (T) xi (x);
-  precision = xi.precision;
+  if (UNLIKELY (precision != xi.precision))
+    {
+      if (UNLIKELY (precision > WIDE_INT_MAX_PRECISION))
+       XDELETEVEC (u.valp);
+      precision = xi.precision;
+      if (UNLIKELY (precision > WIDE_INT_MAX_PRECISION))
+       u.valp = XNEWVEC (HOST_WIDE_INT,
+                         CEIL (precision, HOST_BITS_PER_WIDE_INT));
+    }
   wi::copy (*this, xi);
   return *this;
 }
@@ -1141,7 +1271,7 @@ wide_int_storage::get_precision () const
 inline const HOST_WIDE_INT *
 wide_int_storage::get_val () const
 {
-  return val;
+  return UNLIKELY (precision > WIDE_INT_MAX_PRECISION) ? u.valp : u.val;
 }
 
 inline unsigned int
@@ -1151,9 +1281,9 @@ wide_int_storage::get_len () const
 }
 
 inline HOST_WIDE_INT *
-wide_int_storage::write_val ()
+wide_int_storage::write_val (unsigned int)
 {
-  return val;
+  return UNLIKELY (precision > WIDE_INT_MAX_PRECISION) ? u.valp : u.val;
 }
 
 inline void
@@ -1161,8 +1291,10 @@ wide_int_storage::set_len (unsigned int
 {
   len = l;
   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);
+    {
+      HOST_WIDE_INT &v = write_val (len)[len - 1];
+      v = sext_hwi (v, precision % HOST_BITS_PER_WIDE_INT);
+    }
 }
 
 /* Treat X as having signedness SGN and convert it to a PRECISION-bit
@@ -1172,7 +1304,7 @@ wide_int_storage::from (const wide_int_r
                        signop sgn)
 {
   wide_int result = wide_int::create (precision);
-  result.set_len (wi::force_to_size (result.write_val (), x.val, x.len,
+  result.set_len (wi::force_to_size (result.write_val (x.len), x.val, x.len,
                                     x.precision, precision, sgn));
   return result;
 }
@@ -1185,7 +1317,7 @@ wide_int_storage::from_array (const HOST
                              unsigned int precision, bool need_canon_p)
 {
   wide_int result = wide_int::create (precision);
-  result.set_len (wi::from_array (result.write_val (), val, len, precision,
+  result.set_len (wi::from_array (result.write_val (len), val, len, precision,
                                  need_canon_p));
   return result;
 }
@@ -1196,6 +1328,9 @@ wide_int_storage::create (unsigned int p
 {
   wide_int x;
   x.precision = precision;
+  if (UNLIKELY (precision > WIDE_INT_MAX_PRECISION))
+    x.u.valp = XNEWVEC (HOST_WIDE_INT,
+                       CEIL (precision, HOST_BITS_PER_WIDE_INT));
   return x;
 }
 
@@ -1212,6 +1347,194 @@ wi::int_traits <wide_int_storage>::get_b
     return wide_int::create (wi::get_precision (x));
 }
 
+template <typename T1, typename T2>
+inline unsigned int
+wi::int_traits <wide_int_storage>::get_binary_precision (const T1 &x,
+                                                        const T2 &y)
+{
+  /* This shouldn't be used for two flexible-precision inputs.  */
+  STATIC_ASSERT (wi::int_traits <T1>::precision_type != FLEXIBLE_PRECISION
+                || wi::int_traits <T2>::precision_type != FLEXIBLE_PRECISION);
+  if (wi::int_traits <T1>::precision_type == FLEXIBLE_PRECISION)
+    return wi::get_precision (y);
+  else
+    return wi::get_precision (x);
+}
+
+/* The storage used by rwide_int.  */
+class GTY(()) rwide_int_storage
+{
+private:
+  HOST_WIDE_INT val[WIDE_INT_MAX_ELTS];
+  unsigned int len;
+  unsigned int precision;
+
+public:
+  rwide_int_storage () = default;
+  template <typename T>
+  rwide_int_storage (const T &);
+
+  /* The standard generic_rwide_int storage methods.  */
+  unsigned int get_precision () const;
+  const HOST_WIDE_INT *get_val () const;
+  unsigned int get_len () const;
+  HOST_WIDE_INT *write_val (unsigned int);
+  void set_len (unsigned int, bool = false);
+
+  template <typename T>
+  rwide_int_storage &operator = (const T &);
+
+  static rwide_int from (const wide_int_ref &, unsigned int, signop);
+  static rwide_int from_array (const HOST_WIDE_INT *, unsigned int,
+                              unsigned int, bool = true);
+  static rwide_int create (unsigned int);
+};
+
+namespace wi
+{
+  template <>
+  struct int_traits <rwide_int_storage>
+  {
+    static const enum precision_type precision_type = VAR_PRECISION;
+    /* Guaranteed by a static assert in the rwide_int_storage constructor.  */
+    static const bool host_dependent_precision = false;
+    static const bool is_sign_extended = true;
+    static const bool needs_write_val_arg = false;
+    template <typename T1, typename T2>
+    static rwide_int get_binary_result (const T1 &, const T2 &);
+    template <typename T1, typename T2>
+    static unsigned int get_binary_precision (const T1 &, const T2 &);
+  };
+}
+
+/* Initialize the storage from integer X, in its natural precision.
+   Note that we do not allow integers with host-dependent precision
+   to become rwide_ints; rwide_ints must always be logically independent
+   of the host.  */
+template <typename T>
+inline rwide_int_storage::rwide_int_storage (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);
+  WIDE_INT_REF_FOR (T) xi (x);
+  precision = xi.precision;
+  gcc_assert (precision <= WIDE_INT_MAX_PRECISION);
+  wi::copy (*this, xi);
+}
+
+template <typename T>
+inline rwide_int_storage&
+rwide_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);
+  WIDE_INT_REF_FOR (T) xi (x);
+  precision = xi.precision;
+  gcc_assert (precision <= WIDE_INT_MAX_PRECISION);
+  wi::copy (*this, xi);
+  return *this;
+}
+
+inline unsigned int
+rwide_int_storage::get_precision () const
+{
+  return precision;
+}
+
+inline const HOST_WIDE_INT *
+rwide_int_storage::get_val () const
+{
+  return val;
+}
+
+inline unsigned int
+rwide_int_storage::get_len () const
+{
+  return len;
+}
+
+inline HOST_WIDE_INT *
+rwide_int_storage::write_val (unsigned int)
+{
+  return val;
+}
+
+inline void
+rwide_int_storage::set_len (unsigned int l, bool is_sign_extended)
+{
+  len = l;
+  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);
+}
+
+/* Treat X as having signedness SGN and convert it to a PRECISION-bit
+   number.  */
+inline rwide_int
+rwide_int_storage::from (const wide_int_ref &x, unsigned int precision,
+                        signop sgn)
+{
+  rwide_int result = rwide_int::create (precision);
+  result.set_len (wi::force_to_size (result.write_val (x.len), x.val, x.len,
+                                    x.precision, precision, sgn));
+  return result;
+}
+
+/* Create a rwide_int from the explicit block encoding given by VAL and
+   LEN.  PRECISION is the precision of the integer.  NEED_CANON_P is
+   true if the encoding may have redundant trailing blocks.  */
+inline rwide_int
+rwide_int_storage::from_array (const HOST_WIDE_INT *val, unsigned int len,
+                              unsigned int precision, bool need_canon_p)
+{
+  rwide_int result = rwide_int::create (precision);
+  result.set_len (wi::from_array (result.write_val (len), val, len, precision,
+                                 need_canon_p));
+  return result;
+}
+
+/* Return an uninitialized rwide_int with precision PRECISION.  */
+inline rwide_int
+rwide_int_storage::create (unsigned int precision)
+{
+  rwide_int x;
+  gcc_assert (precision <= WIDE_INT_MAX_PRECISION);
+  x.precision = precision;
+  return x;
+}
+
+template <typename T1, typename T2>
+inline rwide_int
+wi::int_traits <rwide_int_storage>::get_binary_result (const T1 &x,
+                                                      const T2 &y)
+{
+  /* This shouldn't be used for two flexible-precision inputs.  */
+  STATIC_ASSERT (wi::int_traits <T1>::precision_type != FLEXIBLE_PRECISION
+                || wi::int_traits <T2>::precision_type != FLEXIBLE_PRECISION);
+  if (wi::int_traits <T1>::precision_type == FLEXIBLE_PRECISION)
+    return rwide_int::create (wi::get_precision (y));
+  else
+    return rwide_int::create (wi::get_precision (x));
+}
+
+template <typename T1, typename T2>
+inline unsigned int
+wi::int_traits <rwide_int_storage>::get_binary_precision (const T1 &x,
+                                                         const T2 &y)
+{
+  /* This shouldn't be used for two flexible-precision inputs.  */
+  STATIC_ASSERT (wi::int_traits <T1>::precision_type != FLEXIBLE_PRECISION
+                || wi::int_traits <T2>::precision_type != FLEXIBLE_PRECISION);
+  if (wi::int_traits <T1>::precision_type == FLEXIBLE_PRECISION)
+    return wi::get_precision (y);
+  else
+    return wi::get_precision (x);
+}
+
 /* The storage used by FIXED_WIDE_INT (N).  */
 template <int N>
 class GTY(()) fixed_wide_int_storage
@@ -1221,7 +1544,7 @@ private:
   unsigned int len;
 
 public:
-  fixed_wide_int_storage ();
+  fixed_wide_int_storage () = default;
   template <typename T>
   fixed_wide_int_storage (const T &);
 
@@ -1229,7 +1552,7 @@ public:
   unsigned int get_precision () const;
   const HOST_WIDE_INT *get_val () const;
   unsigned int get_len () const;
-  HOST_WIDE_INT *write_val ();
+  HOST_WIDE_INT *write_val (unsigned int);
   void set_len (unsigned int, bool = false);
 
   static FIXED_WIDE_INT (N) from (const wide_int_ref &, signop);
@@ -1245,15 +1568,15 @@ namespace wi
     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 = false;
     static const unsigned int precision = N;
     template <typename T1, typename T2>
     static FIXED_WIDE_INT (N) get_binary_result (const T1 &, const T2 &);
+    template <typename T1, typename T2>
+    static unsigned int get_binary_precision (const T1 &, const T2 &);
   };
 }
 
-template <int N>
-inline fixed_wide_int_storage <N>::fixed_wide_int_storage () {}
-
 /* Initialize the storage from integer X, in precision N.  */
 template <int N>
 template <typename T>
@@ -1288,7 +1611,7 @@ fixed_wide_int_storage <N>::get_len () c
 
 template <int N>
 inline HOST_WIDE_INT *
-fixed_wide_int_storage <N>::write_val ()
+fixed_wide_int_storage <N>::write_val (unsigned int)
 {
   return val;
 }
@@ -1308,7 +1631,7 @@ inline FIXED_WIDE_INT (N)
 fixed_wide_int_storage <N>::from (const wide_int_ref &x, signop sgn)
 {
   FIXED_WIDE_INT (N) result;
-  result.set_len (wi::force_to_size (result.write_val (), x.val, x.len,
+  result.set_len (wi::force_to_size (result.write_val (x.len), x.val, x.len,
                                     x.precision, N, sgn));
   return result;
 }
@@ -1323,7 +1646,7 @@ fixed_wide_int_storage <N>::from_array (
                                        bool need_canon_p)
 {
   FIXED_WIDE_INT (N) result;
-  result.set_len (wi::from_array (result.write_val (), val, len,
+  result.set_len (wi::from_array (result.write_val (len), val, len,
                                  N, need_canon_p));
   return result;
 }
@@ -1337,6 +1660,244 @@ get_binary_result (const T1 &, const T2
   return FIXED_WIDE_INT (N) ();
 }
 
+template <int N>
+template <typename T1, typename T2>
+inline unsigned int
+wi::int_traits < fixed_wide_int_storage <N> >::
+get_binary_precision (const T1 &, const T2 &)
+{
+  return N;
+}
+
+#define WIDEST_INT(N) generic_wide_int < widest_int_storage <N> >
+
+/* The storage used by widest_int.  */
+template <int N>
+class GTY(()) widest_int_storage
+{
+private:
+  union
+  {
+    HOST_WIDE_INT val[WIDE_INT_MAX_HWIS (N)];
+    HOST_WIDE_INT *valp;
+  } GTY((skip)) u;
+  unsigned int len;
+
+public:
+  widest_int_storage ();
+  widest_int_storage (const widest_int_storage &);
+  template <typename T>
+  widest_int_storage (const T &);
+  ~widest_int_storage ();
+  widest_int_storage &operator = (const widest_int_storage &);
+  template <typename T>
+  inline widest_int_storage& operator = (const T &);
+
+  /* The standard generic_wide_int storage methods.  */
+  unsigned int get_precision () const;
+  const HOST_WIDE_INT *get_val () const;
+  unsigned int get_len () const;
+  HOST_WIDE_INT *write_val (unsigned int);
+  void set_len (unsigned int, bool = false);
+
+  static WIDEST_INT (N) from (const wide_int_ref &, signop);
+  static WIDEST_INT (N) from_array (const HOST_WIDE_INT *, unsigned int,
+                                   bool = true);
+};
+
+namespace wi
+{
+  template <int N>
+  struct int_traits < widest_int_storage <N> >
+  {
+    static const enum precision_type precision_type = WIDEST_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_PRECISION * WIDEST_INT_MAX_PRECISION;
+    static const unsigned int inl_precision = N;
+    template <typename T1, typename T2>
+    static WIDEST_INT (N) get_binary_result (const T1 &, const T2 &);
+    template <typename T1, typename T2>
+    static unsigned int get_binary_precision (const T1 &, const T2 &);
+  };
+}
+
+template <int N>
+inline widest_int_storage <N>::widest_int_storage () : len (0) {}
+
+/* Initialize the storage from integer X, in precision N.  */
+template <int N>
+template <typename T>
+inline widest_int_storage <N>::widest_int_storage (const T &x) : len (0)
+{
+  /* 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_PRECISION
+                                           * WIDEST_INT_MAX_PRECISION));
+}
+
+template <int N>
+inline
+widest_int_storage <N>::widest_int_storage (const widest_int_storage <N> &x)
+{
+  len = x.len;
+  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+    {
+      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>
+inline widest_int_storage <N>::~widest_int_storage ()
+{
+  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+    XDELETEVEC (u.valp);
+}
+
+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 (this == &x)
+       return *this;
+      XDELETEVEC (u.valp);
+    }
+  len = x.len;
+  if (UNLIKELY (len > N / HOST_BITS_PER_WIDE_INT))
+    {
+      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;
+}
+
+template <int N>
+template <typename T>
+inline widest_int_storage <N>&
+widest_int_storage <N>::operator = (const T &x)
+{
+  /* 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))
+    XDELETEVEC (u.valp);
+  len = 0;
+  wi::copy (*this, WIDE_INT_REF_FOR (T) (x, N / WIDE_INT_MAX_PRECISION
+                                           * WIDEST_INT_MAX_PRECISION));
+  return *this;
+}
+
+template <int N>
+inline unsigned int
+widest_int_storage <N>::get_precision () const
+{
+  return N / WIDE_INT_MAX_PRECISION * WIDEST_INT_MAX_PRECISION;
+}
+
+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;
+}
+
+template <int N>
+inline unsigned int
+widest_int_storage <N>::get_len () const
+{
+  return len;
+}
+
+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))
+    XDELETEVEC (u.valp);
+  len = l;
+  if (UNLIKELY (l > N / HOST_BITS_PER_WIDE_INT))
+    {
+      u.valp = XNEWVEC (HOST_WIDE_INT, l);
+      return u.valp;
+    }
+  return u.val;
+}
+
+template <int N>
+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)
+    {
+      HOST_WIDE_INT *valp = u.valp;
+      memcpy (u.val, valp, len * sizeof (u.val[0]));
+      XDELETEVEC (valp);
+    }
+  len = l;
+  /* There are no excess bits in val[len - 1].  */
+  STATIC_ASSERT (N % HOST_BITS_PER_WIDE_INT == 0);
+}
+
+/* Treat X as having signedness SGN and convert it to an N-bit number.  */
+template <int N>
+inline WIDEST_INT (N)
+widest_int_storage <N>::from (const wide_int_ref &x, signop sgn)
+{
+  WIDEST_INT (N) result;
+  unsigned int exp_len = x.len;
+  unsigned int prec = result.get_precision ();
+  if (sgn == UNSIGNED && prec > x.precision && x.val[x.len - 1] < 0)
+    exp_len = CEIL (x.precision, HOST_BITS_PER_WIDE_INT) + 1;
+  result.set_len (wi::force_to_size (result.write_val (exp_len), x.val, x.len,
+                                    x.precision, prec, sgn));
+  return result;
+}
+
+/* Create a WIDEST_INT (N) from the explicit block encoding given by
+   VAL and LEN.  NEED_CANON_P is true if the encoding may have redundant
+   trailing blocks.  */
+template <int N>
+inline WIDEST_INT (N)
+widest_int_storage <N>::from_array (const HOST_WIDE_INT *val,
+                                   unsigned int len,
+                                   bool need_canon_p)
+{
+  WIDEST_INT (N) result;
+  result.set_len (wi::from_array (result.write_val (len), val, len,
+                                 result.get_precision (), need_canon_p));
+  return result;
+}
+
+template <int N>
+template <typename T1, typename T2>
+inline WIDEST_INT (N)
+wi::int_traits < widest_int_storage <N> >::
+get_binary_result (const T1 &, const T2 &)
+{
+  return WIDEST_INT (N) ();
+}
+
+template <int N>
+template <typename T1, typename T2>
+inline unsigned int
+wi::int_traits < widest_int_storage <N> >::
+get_binary_precision (const T1 &, const T2 &)
+{
+  return N / WIDE_INT_MAX_PRECISION * WIDEST_INT_MAX_PRECISION;
+}
+
 /* A reference to one element of a trailing_wide_ints structure.  */
 class trailing_wide_int_storage
 {
@@ -1359,7 +1920,7 @@ public:
   unsigned int get_len () const;
   unsigned int get_precision () const;
   const HOST_WIDE_INT *get_val () const;
-  HOST_WIDE_INT *write_val ();
+  HOST_WIDE_INT *write_val (unsigned int);
   void set_len (unsigned int, bool = false);
 
   template <typename T>
@@ -1445,7 +2006,7 @@ trailing_wide_int_storage::get_val () co
 }
 
 inline HOST_WIDE_INT *
-trailing_wide_int_storage::write_val ()
+trailing_wide_int_storage::write_val (unsigned int)
 {
   return m_val;
 }
@@ -1528,6 +2089,7 @@ namespace wi
     static const enum precision_type precision_type = FLEXIBLE_PRECISION;
     static const bool host_dependent_precision = true;
     static const bool is_sign_extended = true;
+    static const bool needs_write_val_arg = false;
     static unsigned int get_precision (T);
     static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int, T);
   };
@@ -1699,6 +2261,7 @@ namespace wi
        precision of HOST_WIDE_INT.  */
     static const bool host_dependent_precision = false;
     static const bool is_sign_extended = true;
+    static const bool needs_write_val_arg = false;
     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 &);
@@ -1804,8 +2367,8 @@ template <typename T1, typename T2>
 inline unsigned int
 wi::get_binary_precision (const T1 &x, const T2 &y)
 {
-  return get_precision (wi::int_traits <WI_BINARY_RESULT (T1, T2)>::
-                       get_binary_result (x, y));
+  return wi::int_traits <WI_BINARY_RESULT (T1, T2)>::get_binary_precision (x,
+                                                                          y);
 }
 
 /* Copy the contents of Y to X, but keeping X's current precision.  */
@@ -1813,9 +2376,9 @@ template <typename T1, typename T2>
 inline 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 ();
+  HOST_WIDE_INT *xval = x.write_val (len);
+  const HOST_WIDE_INT *yval = y.get_val ();
   unsigned int i = 0;
   do
     xval[i] = yval[i];
@@ -2162,6 +2725,8 @@ wi::bit_not (const T &x)
 {
   WI_UNARY_RESULT_VAR (result, val, T, x);
   WIDE_INT_REF_FOR (T) xi (x, get_precision (result));
+  if (result.needs_write_val_arg)
+    val = result.write_val (xi.len);
   for (unsigned int i = 0; i < xi.len; ++i)
     val[i] = ~xi.val[i];
   result.set_len (xi.len);
@@ -2203,6 +2768,8 @@ wi::sext (const T &x, unsigned int offse
   unsigned int precision = get_precision (result);
   WIDE_INT_REF_FOR (T) xi (x, precision);
 
+  if (result.needs_write_val_arg)
+    val = result.write_val (xi.len);
   if (offset <= HOST_BITS_PER_WIDE_INT)
     {
       val[0] = sext_hwi (xi.ulow (), offset);
@@ -2230,6 +2797,9 @@ wi::zext (const T &x, unsigned int offse
       return result;
     }
 
+  if (result.needs_write_val_arg)
+    val = result.write_val (MAX (xi.len,
+                                CEIL (offset, HOST_BITS_PER_WIDE_INT)));
   /* In these cases we know that at least the top bit will be clear,
      so no sign extension is necessary.  */
   if (offset < HOST_BITS_PER_WIDE_INT)
@@ -2259,6 +2829,9 @@ 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_FOR (T) xi (x, precision);
+  if (result.needs_write_val_arg)
+    val = result.write_val (MAX (xi.len,
+                                bit / HOST_BITS_PER_WIDE_INT + 1));
   if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       val[0] = xi.ulow () | (HOST_WIDE_INT_1U << bit);
@@ -2280,6 +2853,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.  */
   result.set_len (bswap_large (val, xi.val, xi.len, precision));
   return result;
 }
@@ -2292,6 +2867,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.  */
   result.set_len (bitreverse_large (val, xi.val, xi.len, precision));
   return result;
 }
@@ -2368,6 +2945,8 @@ wi::bit_and (const T1 &x, const T2 &y)
   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 (result.needs_write_val_arg)
+    val = result.write_val (MAX (xi.len, yi.len));
   if (LIKELY (xi.len + yi.len == 2))
     {
       val[0] = xi.ulow () & yi.ulow ();
@@ -2389,6 +2968,8 @@ wi::bit_and_not (const T1 &x, const T2 &
   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 (result.needs_write_val_arg)
+    val = result.write_val (MAX (xi.len, yi.len));
   if (LIKELY (xi.len + yi.len == 2))
     {
       val[0] = xi.ulow () & ~yi.ulow ();
@@ -2410,6 +2991,8 @@ wi::bit_or (const T1 &x, const T2 &y)
   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 (result.needs_write_val_arg)
+    val = result.write_val (MAX (xi.len, yi.len));
   if (LIKELY (xi.len + yi.len == 2))
     {
       val[0] = xi.ulow () | yi.ulow ();
@@ -2431,6 +3014,8 @@ wi::bit_or_not (const T1 &x, const T2 &y
   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 (result.needs_write_val_arg)
+    val = result.write_val (MAX (xi.len, yi.len));
   if (LIKELY (xi.len + yi.len == 2))
     {
       val[0] = xi.ulow () | ~yi.ulow ();
@@ -2452,6 +3037,8 @@ wi::bit_xor (const T1 &x, const T2 &y)
   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 (result.needs_write_val_arg)
+    val = result.write_val (MAX (xi.len, yi.len));
   if (LIKELY (xi.len + yi.len == 2))
     {
       val[0] = xi.ulow () ^ yi.ulow ();
@@ -2472,6 +3059,8 @@ wi::add (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)
+    val = result.write_val (MAX (xi.len, yi.len) + 1);
   if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       val[0] = xi.ulow () + yi.ulow ();
@@ -2515,6 +3104,8 @@ wi::add (const T1 &x, const T2 &y, signo
   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)
+    val = result.write_val (MAX (xi.len, yi.len) + 1);
   if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       unsigned HOST_WIDE_INT xl = xi.ulow ();
@@ -2558,6 +3149,8 @@ wi::sub (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)
+    val = result.write_val (MAX (xi.len, yi.len) + 1);
   if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       val[0] = xi.ulow () - yi.ulow ();
@@ -2601,6 +3194,8 @@ wi::sub (const T1 &x, const T2 &y, signo
   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)
+    val = result.write_val (MAX (xi.len, yi.len) + 1);
   if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       unsigned HOST_WIDE_INT xl = xi.ulow ();
@@ -2643,6 +3238,8 @@ wi::mul (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)
+    val = result.write_val (xi.len + yi.len + 2);
   if (precision <= HOST_BITS_PER_WIDE_INT)
     {
       val[0] = xi.ulow () * yi.ulow ();
@@ -2664,6 +3261,8 @@ wi::mul (const T1 &x, const T2 &y, signo
   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)
+    val = result.write_val (xi.len + yi.len + 2);
   result.set_len (mul_internal (val, xi.val, xi.len,
                                yi.val, yi.len, precision,
                                sgn, overflow, false));
@@ -2698,6 +3297,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.  */
   result.set_len (mul_internal (val, xi.val, xi.len,
                                yi.val, yi.len, precision,
                                sgn, 0, true));
@@ -2716,6 +3317,12 @@ wi::div_trunc (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T1) xi (x, precision);
   WIDE_INT_REF_FOR (T2) yi (y);
 
+  if (quotient.needs_write_val_arg)
+    quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                       && xi.val[xi.len - 1] < 0)
+                                      ? CEIL (precision,
+                                              HOST_BITS_PER_WIDE_INT) + 1
+                                      : xi.len + 1);
   quotient.set_len (divmod_internal (quotient_val, 0, 0, xi.val, xi.len,
                                     precision,
                                     yi.val, yi.len, yi.precision,
@@ -2753,6 +3360,15 @@ wi::div_floor (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (quotient.needs_write_val_arg)
+    {
+      quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                         && xi.val[xi.len - 1] < 0)
+                                        ? CEIL (precision,
+                                                HOST_BITS_PER_WIDE_INT) + 1
+                                        : xi.len + 1);
+      remainder_val = remainder.write_val (yi.len);
+    }
   quotient.set_len (divmod_internal (quotient_val,
                                     &remainder_len, remainder_val,
                                     xi.val, xi.len, precision,
@@ -2795,6 +3411,15 @@ wi::div_ceil (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (quotient.needs_write_val_arg)
+    {
+      quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                         && xi.val[xi.len - 1] < 0)
+                                        ? CEIL (precision,
+                                                HOST_BITS_PER_WIDE_INT) + 1
+                                        : xi.len + 1);
+      remainder_val = remainder.write_val (yi.len);
+    }
   quotient.set_len (divmod_internal (quotient_val,
                                     &remainder_len, remainder_val,
                                     xi.val, xi.len, precision,
@@ -2828,6 +3453,15 @@ wi::div_round (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (quotient.needs_write_val_arg)
+    {
+      quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                         && xi.val[xi.len - 1] < 0)
+                                        ? CEIL (precision,
+                                                HOST_BITS_PER_WIDE_INT) + 1
+                                        : xi.len + 1);
+      remainder_val = remainder.write_val (yi.len);
+    }
   quotient.set_len (divmod_internal (quotient_val,
                                     &remainder_len, remainder_val,
                                     xi.val, xi.len, precision,
@@ -2871,6 +3505,15 @@ wi::divmod_trunc (const T1 &x, const T2
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (quotient.needs_write_val_arg)
+    {
+      quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                         && xi.val[xi.len - 1] < 0)
+                                        ? CEIL (precision,
+                                                HOST_BITS_PER_WIDE_INT) + 1
+                                        : xi.len + 1);
+      remainder_val = remainder.write_val (yi.len);
+    }
   quotient.set_len (divmod_internal (quotient_val,
                                     &remainder_len, remainder_val,
                                     xi.val, xi.len, precision,
@@ -2915,6 +3558,8 @@ wi::mod_trunc (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (remainder.needs_write_val_arg)
+    remainder_val = remainder.write_val (yi.len);
   divmod_internal (0, &remainder_len, remainder_val,
                   xi.val, xi.len, precision,
                   yi.val, yi.len, yi.precision, sgn, overflow);
@@ -2955,6 +3600,15 @@ wi::mod_floor (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (quotient.needs_write_val_arg)
+    {
+      quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                         && xi.val[xi.len - 1] < 0)
+                                        ? CEIL (precision,
+                                                HOST_BITS_PER_WIDE_INT) + 1
+                                        : xi.len + 1);
+      remainder_val = remainder.write_val (yi.len);
+    }
   quotient.set_len (divmod_internal (quotient_val,
                                     &remainder_len, remainder_val,
                                     xi.val, xi.len, precision,
@@ -2991,6 +3645,15 @@ wi::mod_ceil (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (quotient.needs_write_val_arg)
+    {
+      quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                         && xi.val[xi.len - 1] < 0)
+                                        ? CEIL (precision,
+                                                HOST_BITS_PER_WIDE_INT) + 1
+                                        : xi.len + 1);
+      remainder_val = remainder.write_val (yi.len);
+    }
   quotient.set_len (divmod_internal (quotient_val,
                                     &remainder_len, remainder_val,
                                     xi.val, xi.len, precision,
@@ -3017,6 +3680,15 @@ wi::mod_round (const T1 &x, const T2 &y,
   WIDE_INT_REF_FOR (T2) yi (y);
 
   unsigned int remainder_len;
+  if (quotient.needs_write_val_arg)
+    {
+      quotient_val = quotient.write_val ((sgn == UNSIGNED
+                                         && xi.val[xi.len - 1] < 0)
+                                        ? CEIL (precision,
+                                                HOST_BITS_PER_WIDE_INT) + 1
+                                        : xi.len + 1);
+      remainder_val = remainder.write_val (yi.len);
+    }
   quotient.set_len (divmod_internal (quotient_val,
                                     &remainder_len, remainder_val,
                                     xi.val, xi.len, precision,
@@ -3086,12 +3758,16 @@ wi::lshift (const T1 &x, const T2 &y)
   /* Handle the simple cases quickly.   */
   if (geu_p (yi, precision))
     {
+      if (result.needs_write_val_arg)
+       val = result.write_val (1);
       val[0] = 0;
       result.set_len (1);
     }
   else
     {
       unsigned int shift = yi.to_uhwi ();
+      if (result.needs_write_val_arg)
+       val = result.write_val (xi.len + shift / HOST_BITS_PER_WIDE_INT + 1);
       /* For fixed-precision integers like offset_int and widest_int,
         handle the case where the shift value is constant and the
         result is a single nonnegative HWI (meaning that we don't
@@ -3130,12 +3806,23 @@ wi::lrshift (const T1 &x, const T2 &y)
   /* Handle the simple cases quickly.   */
   if (geu_p (yi, xi.precision))
     {
+      if (result.needs_write_val_arg)
+       val = result.write_val (1);
       val[0] = 0;
       result.set_len (1);
     }
   else
     {
       unsigned int shift = yi.to_uhwi ();
+      if (result.needs_write_val_arg)
+       {
+         unsigned int est_len = xi.len;
+         if (xi.val[xi.len - 1] < 0 && shift)
+           /* Logical right shift of sign-extended value might need a very
+              large precision e.g. for widest_int.  */
+           est_len = CEIL (xi.precision - shift, HOST_BITS_PER_WIDE_INT) + 1;
+         val = result.write_val (est_len);
+       }
       /* For fixed-precision integers like offset_int and widest_int,
         handle the case where the shift value is constant and the
         shifted value is a single nonnegative HWI (meaning that all
@@ -3171,6 +3858,8 @@ wi::arshift (const T1 &x, const T2 &y)
      since the result can be no larger than that.  */
   WIDE_INT_REF_FOR (T1) xi (x);
   WIDE_INT_REF_FOR (T2) yi (y);
+  if (result.needs_write_val_arg)
+    val = result.write_val (xi.len);
   /* Handle the simple cases quickly.   */
   if (geu_p (yi, xi.precision))
     {
@@ -3465,7 +4154,7 @@ inline wide_int
 wi::mask (unsigned int width, bool negate_p, unsigned int precision)
 {
   wide_int result = wide_int::create (precision);
-  result.set_len (mask (result.write_val (), width, negate_p, precision));
+  result.set_len (mask (result.write_val (0), width, negate_p, precision));
   return result;
 }
 
@@ -3477,7 +4166,7 @@ wi::shifted_mask (unsigned int start, un
                  unsigned int precision)
 {
   wide_int result = wide_int::create (precision);
-  result.set_len (shifted_mask (result.write_val (), start, width, negate_p,
+  result.set_len (shifted_mask (result.write_val (0), start, width, negate_p,
                                precision));
   return result;
 }
@@ -3498,8 +4187,8 @@ wi::mask (unsigned int width, bool negat
 {
   STATIC_ASSERT (wi::int_traits<T>::precision);
   T result;
-  result.set_len (mask (result.write_val (), width, negate_p,
-                       wi::int_traits <T>::precision));
+  result.set_len (mask (result.write_val (width / HOST_BITS_PER_WIDE_INT + 1),
+                       width, negate_p, wi::int_traits <T>::precision));
   return result;
 }
 
@@ -3512,9 +4201,13 @@ wi::shifted_mask (unsigned int start, un
 {
   STATIC_ASSERT (wi::int_traits<T>::precision);
   T result;
-  result.set_len (shifted_mask (result.write_val (), start, width,
-                               negate_p,
-                               wi::int_traits <T>::precision));
+  unsigned int prec = wi::int_traits <T>::precision;
+  unsigned int est_len
+    = result.needs_write_val_arg
+      ? ((start + (width > prec - start ? prec - start : width))
+        / HOST_BITS_PER_WIDE_INT + 1) : 0;
+  result.set_len (shifted_mask (result.write_val (est_len), start, width,
+                               negate_p, prec));
   return result;
 }
 
--- gcc/wide-int.cc.jj  2023-09-27 10:37:39.429837179 +0200
+++ gcc/wide-int.cc     2023-09-28 14:59:04.121819198 +0200
@@ -51,7 +51,7 @@ typedef unsigned int UDWtype __attribute
 #include "longlong.h"
 #endif
 
-static const HOST_WIDE_INT zeros[WIDE_INT_MAX_ELTS] = {};
+static const HOST_WIDE_INT zeros[1] = {};
 
 /*
  * Internal utilities.
@@ -62,8 +62,7 @@ static const HOST_WIDE_INT zeros[WIDE_IN
 #define HALF_INT_MASK ((HOST_WIDE_INT_1 << HOST_BITS_PER_HALF_WIDE_INT) - 1)
 
 #define BLOCK_OF(TARGET) ((TARGET) / HOST_BITS_PER_WIDE_INT)
-#define BLOCKS_NEEDED(PREC) \
-  (PREC ? (((PREC) + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT) : 1)
+#define BLOCKS_NEEDED(PREC) (PREC ? CEIL (PREC, HOST_BITS_PER_WIDE_INT) : 1)
 #define SIGN_MASK(X) ((HOST_WIDE_INT) (X) < 0 ? -1 : 0)
 
 /* Return the value a VAL[I] if I < LEN, otherwise, return 0 or -1
@@ -96,7 +95,7 @@ canonize (HOST_WIDE_INT *val, unsigned i
   top = val[len - 1];
   if (len * HOST_BITS_PER_WIDE_INT > precision)
     val[len - 1] = top = sext_hwi (top, precision % HOST_BITS_PER_WIDE_INT);
-  if (top != 0 && top != (HOST_WIDE_INT)-1)
+  if (top != 0 && top != HOST_WIDE_INT_M1)
     return len;
 
   /* At this point we know that the top is either 0 or -1.  Find the
@@ -163,7 +162,7 @@ wi::from_buffer (const unsigned char *bu
   /* We have to clear all the bits ourself, as we merely or in values
      below.  */
   unsigned int len = BLOCKS_NEEDED (precision);
-  HOST_WIDE_INT *val = result.write_val ();
+  HOST_WIDE_INT *val = result.write_val (0);
   for (unsigned int i = 0; i < len; ++i)
     val[i] = 0;
 
@@ -232,8 +231,7 @@ wi::to_mpz (const wide_int_ref &x, mpz_t
     }
   else if (excess < 0 && wi::neg_p (x))
     {
-      int extra
-       = (-excess + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
+      int extra = CEIL (-excess, HOST_BITS_PER_WIDE_INT);
       HOST_WIDE_INT *t = XALLOCAVEC (HOST_WIDE_INT, len + extra);
       for (int i = 0; i < len; i++)
        t[i] = v[i];
@@ -280,8 +278,8 @@ wi::from_mpz (const_tree type, mpz_t x,
      extracted from the GMP manual, section "Integer Import and Export":
      http://gmplib.org/manual/Integer-Import-and-Export.html  */
   numb = CHAR_BIT * sizeof (HOST_WIDE_INT);
-  count = (mpz_sizeinbase (x, 2) + numb - 1) / numb;
-  HOST_WIDE_INT *val = res.write_val ();
+  count = CEIL (mpz_sizeinbase (x, 2), numb);
+  HOST_WIDE_INT *val = res.write_val (0);
   /* Read the absolute value.
 
      Write directly to the wide_int storage if possible, otherwise leave
@@ -1334,21 +1332,6 @@ wi::mul_internal (HOST_WIDE_INT *val, co
   unsigned HOST_WIDE_INT o0, o1, k, t;
   unsigned int i;
   unsigned int j;
-  unsigned int blocks_needed = BLOCKS_NEEDED (prec);
-  unsigned int half_blocks_needed = blocks_needed * 2;
-  /* The sizes here are scaled to support a 2x largest mode by 2x
-     largest mode yielding a 4x largest mode result.  This is what is
-     needed by vpn.  */
-
-  unsigned HOST_HALF_WIDE_INT
-    u[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
-  unsigned HOST_HALF_WIDE_INT
-    v[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
-  /* The '2' in 'R' is because we are internally doing a full
-     multiply.  */
-  unsigned HOST_HALF_WIDE_INT
-    r[2 * 4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
-  HOST_WIDE_INT mask = ((HOST_WIDE_INT)1 << HOST_BITS_PER_HALF_WIDE_INT) - 1;
 
   /* If the top level routine did not really pass in an overflow, then
      just make sure that we never attempt to set it.  */
@@ -1469,6 +1452,35 @@ wi::mul_internal (HOST_WIDE_INT *val, co
       return 1;
     }
 
+  /* The sizes here are scaled to support a 2x WIDE_INT_MAX_PRECISION by 2x
+     WIDE_INT_MAX_PRECISION yielding a 4x WIDE_INT_MAX_PRECISION result.  */
+
+  unsigned HOST_HALF_WIDE_INT
+    ubuf[4 * WIDE_INT_MAX_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+  unsigned HOST_HALF_WIDE_INT
+    vbuf[4 * WIDE_INT_MAX_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+  /* The '2' in 'R' is because we are internally doing a full
+     multiply.  */
+  unsigned HOST_HALF_WIDE_INT
+    rbuf[2 * 4 * WIDE_INT_MAX_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+  const HOST_WIDE_INT mask = ((HOST_WIDE_INT)1 << HOST_BITS_PER_HALF_WIDE_INT) 
- 1;
+  unsigned HOST_HALF_WIDE_INT *u = ubuf;
+  unsigned HOST_HALF_WIDE_INT *v = vbuf;
+  unsigned HOST_HALF_WIDE_INT *r = rbuf;
+
+  if (prec > WIDE_INT_MAX_PRECISION && !high)
+    prec = (op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT;
+  unsigned int blocks_needed = BLOCKS_NEEDED (prec);
+  unsigned int half_blocks_needed = blocks_needed * 2;
+  if (UNLIKELY (prec > WIDE_INT_MAX_PRECISION))
+    {
+      unsigned HOST_HALF_WIDE_INT *buf
+       = XALLOCAVEC (unsigned HOST_HALF_WIDE_INT, 4 * 4 * blocks_needed);
+      u = buf;
+      v = u + 4 * blocks_needed;
+      r = v + 4 * blocks_needed;
+    }
+
   /* We do unsigned mul and then correct it.  */
   wi_unpack (u, op1val, op1len, half_blocks_needed, prec, SIGNED);
   wi_unpack (v, op2val, op2len, half_blocks_needed, prec, SIGNED);
@@ -1782,16 +1794,6 @@ wi::divmod_internal (HOST_WIDE_INT *quot
                     unsigned int divisor_prec, signop sgn,
                     wi::overflow_type *oflow)
 {
-  unsigned int dividend_blocks_needed = 2 * BLOCKS_NEEDED (dividend_prec);
-  unsigned int divisor_blocks_needed = 2 * BLOCKS_NEEDED (divisor_prec);
-  unsigned HOST_HALF_WIDE_INT
-    b_quotient[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
-  unsigned HOST_HALF_WIDE_INT
-    b_remainder[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
-  unsigned HOST_HALF_WIDE_INT
-    b_dividend[(4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT) + 
1];
-  unsigned HOST_HALF_WIDE_INT
-    b_divisor[4 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_HALF_WIDE_INT];
   unsigned int m, n;
   bool dividend_neg = false;
   bool divisor_neg = false;
@@ -1910,6 +1912,41 @@ wi::divmod_internal (HOST_WIDE_INT *quot
        }
     }
 
+  unsigned HOST_HALF_WIDE_INT
+    b_quotient_buf[4 * WIDE_INT_MAX_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+  unsigned HOST_HALF_WIDE_INT
+    b_remainder_buf[4 * WIDE_INT_MAX_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+  unsigned HOST_HALF_WIDE_INT
+    b_dividend_buf[(4 * WIDE_INT_MAX_PRECISION / HOST_BITS_PER_HALF_WIDE_INT)
+                  + 1];
+  unsigned HOST_HALF_WIDE_INT
+    b_divisor_buf[4 * WIDE_INT_MAX_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
+  unsigned HOST_HALF_WIDE_INT *b_quotient = b_quotient_buf;
+  unsigned HOST_HALF_WIDE_INT *b_remainder = b_remainder_buf;
+  unsigned HOST_HALF_WIDE_INT *b_dividend = b_dividend_buf;
+  unsigned HOST_HALF_WIDE_INT *b_divisor = b_divisor_buf;
+
+  if (dividend_prec > WIDE_INT_MAX_PRECISION
+      && (sgn == SIGNED || dividend_val[dividend_len - 1] >= 0))
+    dividend_prec = (dividend_len + 1) * HOST_BITS_PER_WIDE_INT;
+  if (divisor_prec > WIDE_INT_MAX_PRECISION)
+    divisor_prec = divisor_len * HOST_BITS_PER_WIDE_INT;
+  unsigned int dividend_blocks_needed = 2 * BLOCKS_NEEDED (dividend_prec);
+  unsigned int divisor_blocks_needed = 2 * BLOCKS_NEEDED (divisor_prec);
+  if (UNLIKELY (dividend_prec > WIDE_INT_MAX_PRECISION)
+      || UNLIKELY (divisor_prec > WIDE_INT_MAX_PRECISION))
+    {
+      unsigned HOST_HALF_WIDE_INT *buf
+        = XALLOCAVEC (unsigned HOST_HALF_WIDE_INT,
+                     12 * dividend_blocks_needed
+                     + 4 * divisor_blocks_needed + 1);
+      b_quotient = buf;
+      b_remainder = b_quotient + 4 * dividend_blocks_needed;
+      b_dividend = b_remainder + 4 * dividend_blocks_needed;
+      b_divisor = b_dividend + 4 * dividend_blocks_needed + 1;
+      memset (b_quotient, 0,
+             4 * dividend_blocks_needed * sizeof (HOST_HALF_WIDE_INT));
+    }
   wi_unpack (b_dividend, dividend.get_val (), dividend.get_len (),
             dividend_blocks_needed, dividend_prec, UNSIGNED);
   wi_unpack (b_divisor, divisor.get_val (), divisor.get_len (),
@@ -1924,7 +1961,8 @@ wi::divmod_internal (HOST_WIDE_INT *quot
   while (n > 1 && b_divisor[n - 1] == 0)
     n--;
 
-  memset (b_quotient, 0, sizeof (b_quotient));
+  if (b_quotient == b_quotient_buf)
+    memset (b_quotient_buf, 0, sizeof (b_quotient_buf));
 
   divmod_internal_2 (b_quotient, b_remainder, b_dividend, b_divisor, m, n);
 
@@ -1970,6 +2008,8 @@ wi::lshift_large (HOST_WIDE_INT *val, co
 
   /* The whole-block shift fills with zeros.  */
   unsigned int len = BLOCKS_NEEDED (precision);
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS))
+    len = xlen + skip + 1;
   for (unsigned int i = 0; i < skip; ++i)
     val[i] = 0;
 
@@ -1993,22 +2033,17 @@ wi::lshift_large (HOST_WIDE_INT *val, co
   return canonize (val, len, precision);
 }
 
-/* Right shift XVAL by SHIFT and store the result in VAL.  Return the
+/* Right shift XVAL by SHIFT and store the result in VAL.  LEN is the
    number of blocks in VAL.  The input has XPRECISION bits and the
    output has XPRECISION - SHIFT bits.  */
-static unsigned int
+static void
 rshift_large_common (HOST_WIDE_INT *val, const HOST_WIDE_INT *xval,
-                    unsigned int xlen, unsigned int xprecision,
-                    unsigned int shift)
+                    unsigned int xlen, unsigned int shift, unsigned int len)
 {
   /* Split the shift into a whole-block shift and a subblock shift.  */
   unsigned int skip = shift / HOST_BITS_PER_WIDE_INT;
   unsigned int small_shift = shift % HOST_BITS_PER_WIDE_INT;
 
-  /* Work out how many blocks are needed to store the significant bits
-     (excluding the upper zeros or signs).  */
-  unsigned int len = BLOCKS_NEEDED (xprecision - shift);
-
   /* It's easier to handle the simple block case specially.  */
   if (small_shift == 0)
     for (unsigned int i = 0; i < len; ++i)
@@ -2025,7 +2060,6 @@ rshift_large_common (HOST_WIDE_INT *val,
          val[i] |= curr << (-small_shift % HOST_BITS_PER_WIDE_INT);
        }
     }
-  return len;
 }
 
 /* Logically right shift XVAL by SHIFT and store the result in VAL.
@@ -2036,11 +2070,18 @@ wi::lrshift_large (HOST_WIDE_INT *val, c
                   unsigned int xlen, unsigned int xprecision,
                   unsigned int precision, unsigned int shift)
 {
-  unsigned int len = rshift_large_common (val, xval, xlen, xprecision, shift);
+  /* Work out how many blocks are needed to store the significant bits
+     (excluding the upper zeros or signs).  */
+  unsigned int blocks_needed = BLOCKS_NEEDED (xprecision - shift);
+  unsigned int len = blocks_needed;
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS) && len > xlen && xval[xlen - 1] >= 0)
+    len = xlen;
+
+  rshift_large_common (val, xval, xlen, shift, len);
 
   /* The value we just created has precision XPRECISION - SHIFT.
      Zero-extend it to wider precisions.  */
-  if (precision > xprecision - shift)
+  if (precision > xprecision - shift && len == blocks_needed)
     {
       unsigned int small_prec = (xprecision - shift) % HOST_BITS_PER_WIDE_INT;
       if (small_prec)
@@ -2063,11 +2104,18 @@ wi::arshift_large (HOST_WIDE_INT *val, c
                   unsigned int xlen, unsigned int xprecision,
                   unsigned int precision, unsigned int shift)
 {
-  unsigned int len = rshift_large_common (val, xval, xlen, xprecision, shift);
+  /* Work out how many blocks are needed to store the significant bits
+     (excluding the upper zeros or signs).  */
+  unsigned int blocks_needed = BLOCKS_NEEDED (xprecision - shift);
+  unsigned int len = blocks_needed;
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS) && len > xlen)
+    len = xlen;
+
+  rshift_large_common (val, xval, xlen, shift, len);
 
   /* The value we just created has precision XPRECISION - SHIFT.
      Sign-extend it to wider types.  */
-  if (precision > xprecision - shift)
+  if (precision > xprecision - shift && len == blocks_needed)
     {
       unsigned int small_prec = (xprecision - shift) % HOST_BITS_PER_WIDE_INT;
       if (small_prec)
@@ -2399,9 +2447,12 @@ from_int (int i)
 static void
 assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn)
 {
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
-  print_dec (wi, buf, sgn);
-  ASSERT_STREQ (expected, buf);
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+  unsigned len = wi.get_len ();
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS))
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  print_dec (wi, p, sgn);
+  ASSERT_STREQ (expected, p);
 }
 
 /* Likewise for base 16.  */
@@ -2409,9 +2460,12 @@ assert_deceq (const char *expected, cons
 static void
 assert_hexeq (const char *expected, const wide_int_ref &wi)
 {
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
-  print_hex (wi, buf);
-  ASSERT_STREQ (expected, buf);
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+  unsigned len = wi.get_len ();
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS))
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  print_hex (wi, p);
+  ASSERT_STREQ (expected, p);
 }
 
 /* Test cases.  */
--- gcc/print-tree.cc.jj        2023-07-11 13:40:39.000000000 +0200
+++ gcc/print-tree.cc   2023-09-28 14:12:40.257284557 +0200
@@ -365,13 +365,13 @@ print_node (FILE *file, const char *pref
     fputs (code == CALL_EXPR ? " must-tail-call" : " static", file);
   if (TREE_DEPRECATED (node))
     fputs (" deprecated", file);
-  if (TREE_UNAVAILABLE (node))
-    fputs (" unavailable", file);
   if (TREE_VISITED (node))
     fputs (" visited", file);
 
   if (code != TREE_VEC && code != INTEGER_CST && code != SSA_NAME)
     {
+      if (TREE_UNAVAILABLE (node))
+       fputs (" unavailable", file);
       if (TREE_LANG_FLAG_0 (node))
        fputs (" tree_0", file);
       if (TREE_LANG_FLAG_1 (node))
--- gcc/dwarf2out.cc.jj 2023-09-28 12:05:50.905151340 +0200
+++ gcc/dwarf2out.cc    2023-09-28 13:06:34.492017940 +0200
@@ -397,7 +397,7 @@ dump_struct_debug (tree type, enum debug
    of the number.  */
 
 static unsigned int
-get_full_len (const wide_int &op)
+get_full_len (const rwide_int &op)
 {
   int prec = wi::get_precision (op);
   return ((prec + HOST_BITS_PER_WIDE_INT - 1)
@@ -3900,7 +3900,7 @@ static void add_data_member_location_att
                                                struct vlr_context *);
 static bool add_const_value_attribute (dw_die_ref, machine_mode, rtx);
 static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
-static void insert_wide_int (const wide_int &, unsigned char *, int);
+static void insert_wide_int (const rwide_int &, unsigned char *, int);
 static unsigned insert_float (const_rtx, unsigned char *);
 static rtx rtl_for_decl_location (tree);
 static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool);
@@ -4598,14 +4598,14 @@ AT_unsigned (dw_attr_node *a)
 
 static inline void
 add_AT_wide (dw_die_ref die, enum dwarf_attribute attr_kind,
-            const wide_int& w)
+            const rwide_int& w)
 {
   dw_attr_node attr;
 
   attr.dw_attr = attr_kind;
   attr.dw_attr_val.val_class = dw_val_class_wide_int;
   attr.dw_attr_val.val_entry = NULL;
-  attr.dw_attr_val.v.val_wide = ggc_alloc<wide_int> ();
+  attr.dw_attr_val.v.val_wide = ggc_alloc<rwide_int> ();
   *attr.dw_attr_val.v.val_wide = w;
   add_dwarf_attr (die, &attr);
 }
@@ -16714,7 +16714,7 @@ mem_loc_descriptor (rtx rtl, machine_mod
          mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
          mem_loc_result->dw_loc_oprnd2.val_class
            = dw_val_class_wide_int;
-         mem_loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc<wide_int> ();
+         mem_loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc<rwide_int> ();
          *mem_loc_result->dw_loc_oprnd2.v.val_wide = rtx_mode_t (rtl, mode);
        }
       break;
@@ -17288,7 +17288,7 @@ loc_descriptor (rtx rtl, machine_mode mo
          loc_result = new_loc_descr (DW_OP_implicit_value,
                                      GET_MODE_SIZE (int_mode), 0);
          loc_result->dw_loc_oprnd2.val_class = dw_val_class_wide_int;
-         loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc<wide_int> ();
+         loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc<rwide_int> ();
          *loc_result->dw_loc_oprnd2.v.val_wide = rtx_mode_t (rtl, int_mode);
        }
       break;
@@ -20189,7 +20189,7 @@ extract_int (const unsigned char *src, u
 /* Writes wide_int values to dw_vec_const array.  */
 
 static void
-insert_wide_int (const wide_int &val, unsigned char *dest, int elt_size)
+insert_wide_int (const rwide_int &val, unsigned char *dest, int elt_size)
 {
   int i;
 
@@ -20274,7 +20274,7 @@ add_const_value_attribute (dw_die_ref di
          && (GET_MODE_PRECISION (int_mode)
              & (HOST_BITS_PER_WIDE_INT - 1)) == 0)
        {
-         wide_int w = rtx_mode_t (rtl, int_mode);
+         rwide_int w = rtx_mode_t (rtl, int_mode);
          add_AT_wide (die, DW_AT_const_value, w);
          return true;
        }
--- gcc/dwarf2out.h.jj  2023-09-27 10:37:38.536849616 +0200
+++ gcc/dwarf2out.h     2023-09-28 13:06:34.492017940 +0200
@@ -30,7 +30,7 @@ typedef struct dw_cfi_node *dw_cfi_ref;
 typedef struct dw_loc_descr_node *dw_loc_descr_ref;
 typedef struct dw_loc_list_struct *dw_loc_list_ref;
 typedef struct dw_discr_list_node *dw_discr_list_ref;
-typedef wide_int *wide_int_ptr;
+typedef rwide_int *rwide_int_ptr;
 
 
 /* Call frames are described using a sequence of Call Frame
@@ -252,7 +252,7 @@ struct GTY(()) dw_val_node {
       unsigned HOST_WIDE_INT
        GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
       double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
-      wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
+      rwide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
       dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
       struct dw_val_die_union
        {
--- gcc/tree.h.jj       2023-09-27 10:37:39.114841566 +0200
+++ gcc/tree.h  2023-09-28 13:06:34.506017744 +0200
@@ -6258,13 +6258,17 @@ namespace wi
   template <int N>
   struct int_traits <extended_tree <N> >
   {
-    static const enum precision_type precision_type = CONST_PRECISION;
+    static const enum precision_type precision_type
+      = N == ADDR_MAX_PRECISION ? CONST_PRECISION : WIDEST_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_PRECISION;
   };
 
-  typedef extended_tree <WIDE_INT_MAX_PRECISION> widest_extended_tree;
+  typedef extended_tree <WIDEST_INT_MAX_PRECISION> widest_extended_tree;
   typedef extended_tree <ADDR_MAX_PRECISION> offset_extended_tree;
 
   typedef const generic_wide_int <widest_extended_tree> tree_to_widest_ref;
@@ -6292,7 +6296,8 @@ namespace wi
   tree_to_poly_wide_ref to_poly_wide (const_tree);
 
   template <int N>
-  struct ints_for <generic_wide_int <extended_tree <N> >, CONST_PRECISION>
+  struct ints_for <generic_wide_int <extended_tree <N> >,
+                  int_traits <extended_tree <N> >::precision_type>
   {
     typedef generic_wide_int <extended_tree <N> > extended;
     static extended zero (const extended &);
@@ -6308,7 +6313,7 @@ namespace wi
 
 /* Used to convert a tree to a widest2_int like this:
    widest2_int foo = widest2_int_cst (some_tree).  */
-typedef generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> >
+typedef generic_wide_int <wi::extended_tree <WIDEST_INT_MAX_PRECISION * 2> >
   widest2_int_cst;
 
 /* Refer to INTEGER_CST T as though it were a widest_int.
@@ -6444,7 +6449,7 @@ wi::extended_tree <N>::get_len () const
 {
   if (N == ADDR_MAX_PRECISION)
     return TREE_INT_CST_OFFSET_NUNITS (m_t);
-  else if (N >= WIDE_INT_MAX_PRECISION)
+  else if (N >= WIDEST_INT_MAX_PRECISION)
     return TREE_INT_CST_EXT_NUNITS (m_t);
   else
     /* This class is designed to be used for specific output precisions
@@ -6530,7 +6535,8 @@ wi::to_poly_wide (const_tree t)
 template <int N>
 inline generic_wide_int <wi::extended_tree <N> >
 wi::ints_for <generic_wide_int <wi::extended_tree <N> >,
-             wi::CONST_PRECISION>::zero (const extended &x)
+             wi::int_traits <wi::extended_tree <N> >::precision_type
+            >::zero (const extended &x)
 {
   return build_zero_cst (TREE_TYPE (x.get_tree ()));
 }
--- gcc/value-range.cc.jj       2023-09-27 10:37:39.240839811 +0200
+++ gcc/value-range.cc  2023-09-28 13:06:34.512017660 +0200
@@ -245,17 +245,24 @@ vrange::dump (FILE *file) const
 void
 irange_bitmask::dump (FILE *file) const
 {
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
   pretty_printer buffer;
 
   pp_needs_newline (&buffer) = true;
   buffer.buffer->stream = file;
   pp_string (&buffer, "MASK ");
-  print_hex (m_mask, buf);
-  pp_string (&buffer, buf);
+  unsigned len_mask = m_mask.get_len ();
+  unsigned len_val = m_value.get_len ();
+  unsigned len = MAX (len_mask, len_val);
+  if (len > WIDE_INT_MAX_ELTS)
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  else
+    p = buf;
+  print_hex (m_mask, p);
+  pp_string (&buffer, p);
   pp_string (&buffer, " VALUE ");
-  print_hex (m_value, buf);
-  pp_string (&buffer, buf);
+  print_hex (m_value, p);
+  pp_string (&buffer, p);
   pp_flush (&buffer);
 }
 
--- gcc/c/c-decl.cc.jj  2023-09-27 10:37:38.428851119 +0200
+++ gcc/c/c-decl.cc     2023-09-28 13:06:34.514017632 +0200
@@ -12355,11 +12355,11 @@ declspecs_add_type (location_t loc, stru
                                spec.expr);
                      return specs;
                    }
-                 if (wi::to_widest (spec.expr) > WIDE_INT_MAX_PRECISION - 1)
+                 if (wi::to_widest (spec.expr) > WIDEST_INT_MAX_PRECISION - 1)
                    {
                      error_at (loc, "%<_BitInt%> argument %qE is larger than "
                                     "%<BITINT_MAXWIDTH%> %qd",
-                               spec.expr, (int) WIDE_INT_MAX_PRECISION - 1);
+                               spec.expr, (int) WIDEST_INT_MAX_PRECISION - 1);
                      return specs;
                    }
                  specs->u.bitint_prec = tree_to_uhwi (spec.expr);
--- gcc/gengtype.cc.jj  2023-09-27 10:37:38.751846621 +0200
+++ gcc/gengtype.cc     2023-09-28 13:06:34.515017618 +0200
@@ -5236,7 +5236,6 @@ main (int argc, char **argv)
       POS_HERE (do_scalar_typedef ("double_int", &pos));
       POS_HERE (do_scalar_typedef ("poly_int64_pod", &pos));
       POS_HERE (do_scalar_typedef ("offset_int", &pos));
-      POS_HERE (do_scalar_typedef ("widest_int", &pos));
       POS_HERE (do_scalar_typedef ("int64_t", &pos));
       POS_HERE (do_scalar_typedef ("poly_int64", &pos));
       POS_HERE (do_scalar_typedef ("poly_uint64", &pos));
--- gcc/tree-ssa-loop-niter.cc.jj       2023-09-27 10:37:39.072842151 +0200
+++ gcc/tree-ssa-loop-niter.cc  2023-09-28 13:06:34.515017618 +0200
@@ -3873,12 +3873,17 @@ do_warn_aggressive_loop_optimizations (c
     return;
 
   gimple *estmt = last_nondebug_stmt (e->src);
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
-  print_dec (i_bound, buf, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
+  unsigned len = i_bound.get_len ();
+  if (len > WIDE_INT_MAX_ELTS)
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  else
+    p = buf;
+  print_dec (i_bound, p, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
             ? UNSIGNED : SIGNED);
   auto_diagnostic_group d;
   if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
-                 "iteration %s invokes undefined behavior", buf))
+                 "iteration %s invokes undefined behavior", p))
     inform (gimple_location (estmt), "within this loop");
   loop->warned_aggressive_loop_optimizations = true;
 }
--- gcc/c-family/c-warn.cc.jj   2023-09-27 10:37:38.334852428 +0200
+++ gcc/c-family/c-warn.cc      2023-09-28 13:06:34.524017491 +0200
@@ -1517,13 +1517,15 @@ match_case_to_enum_1 (tree key, tree typ
     return;
 
   char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+  wide_int w = wi::to_wide (key);
 
+  gcc_assert (w.get_len () <= WIDE_INT_MAX_ELTS);
   if (tree_fits_uhwi_p (key))
-    print_dec (wi::to_wide (key), buf, UNSIGNED);
+    print_dec (w, buf, UNSIGNED);
   else if (tree_fits_shwi_p (key))
-    print_dec (wi::to_wide (key), buf, SIGNED);
+    print_dec (w, buf, SIGNED);
   else
-    print_hex (wi::to_wide (key), buf);
+    print_hex (w, buf);
 
   if (TYPE_NAME (type) == NULL_TREE)
     warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
--- gcc/c-family/c-cppbuiltin.cc.jj     2023-09-27 10:37:38.226853933 +0200
+++ gcc/c-family/c-cppbuiltin.cc        2023-09-28 13:06:34.541017253 +0200
@@ -1195,10 +1195,10 @@ c_cpp_builtins (cpp_reader *pfile)
       struct bitint_info info;
       /* For now, restrict __BITINT_MAXWIDTH__ to what can be represented in
         wide_int and widest_int.  */
-      if (targetm.c.bitint_type_info (WIDE_INT_MAX_PRECISION - 1, &info))
+      if (targetm.c.bitint_type_info (WIDEST_INT_MAX_PRECISION - 1, &info))
        {
          cpp_define_formatted (pfile, "__BITINT_MAXWIDTH__=%d",
-                               (int) WIDE_INT_MAX_PRECISION - 1);
+                               (int) WIDEST_INT_MAX_PRECISION - 1);
          if (flag_building_libgcc)
            {
              scalar_int_mode limb_mode
--- gcc/c-family/c-lex.cc.jj    2023-09-27 10:37:38.272853292 +0200
+++ gcc/c-family/c-lex.cc       2023-09-28 13:06:34.550017127 +0200
@@ -843,7 +843,7 @@ interpret_integer (const cpp_token *toke
       int max_bits_per_digit = 4; // ceil (log2 (10))
       unsigned int prefix_len = 0;
       bool hex = false;
-      const int bitint_maxwidth = WIDE_INT_MAX_PRECISION - 1;
+      const int bitint_maxwidth = WIDEST_INT_MAX_PRECISION - 1;
       if ((flags & CPP_N_RADIX) == CPP_N_OCTAL)
        {
          max_bits_per_digit = 3;
--- gcc/value-range-pretty-print.cc.jj  2023-09-27 10:37:39.170840787 +0200
+++ gcc/value-range-pretty-print.cc     2023-09-28 13:06:34.550017127 +0200
@@ -99,12 +99,19 @@ vrange_printer::print_irange_bitmasks (c
     return;
 
   pp_string (pp, " MASK ");
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
-  print_hex (bm.mask (), buf);
-  pp_string (pp, buf);
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p;
+  unsigned len_mask = bm.mask ().get_len ();
+  unsigned len_val = bm.value ().get_len ();
+  unsigned len = MAX (len_mask, len_val);
+  if (len > WIDE_INT_MAX_ELTS)
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  else
+    p = buf;
+  print_hex (bm.mask (), p);
+  pp_string (pp, p);
   pp_string (pp, " VALUE ");
-  print_hex (bm.value (), buf);
-  pp_string (pp, buf);
+  print_hex (bm.value (), p);
+  pp_string (pp, p);
 }
 
 void
--- gcc/poly-int.h.jj   2023-09-27 10:37:38.874844909 +0200
+++ gcc/poly-int.h      2023-09-28 13:06:34.551017113 +0200
@@ -97,6 +97,18 @@ struct poly_coeff_traits<T, wi::CONST_PR
   static const int rank = precision * 2 / CHAR_BIT;
 };
 
+template<typename T>
+struct poly_coeff_traits<T, wi::WIDEST_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;
+};
+
 /* Information about a pair of coefficient types.  */
 template<typename T1, typename T2>
 struct poly_coeff_pair_traits
--- gcc/godump.cc.jj    2023-09-27 10:37:38.805845870 +0200
+++ gcc/godump.cc       2023-09-28 13:06:34.551017113 +0200
@@ -1154,7 +1154,11 @@ go_output_typedef (class godump_containe
            snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
                      tree_to_uhwi (value));
          else
-           print_hex (wi::to_wide (element), buf);
+           {
+             wide_int w = wi::to_wide (element);
+             gcc_assert (w.get_len () <= WIDE_INT_MAX_ELTS);
+             print_hex (w, buf);
+           }
 
          mhval->value = xstrdup (buf);
          *slot = mhval;
--- gcc/value-range.h.jj        2023-09-27 10:37:39.268839422 +0200
+++ gcc/value-range.h   2023-09-28 13:06:34.555017057 +0200
@@ -626,7 +626,9 @@ irange::maybe_resize (int needed)
     {
       m_max_ranges = HARD_MAX_RANGES;
       wide_int *newmem = new wide_int[m_max_ranges * 2];
-      memcpy (newmem, m_base, sizeof (wide_int) * num_pairs () * 2);
+      unsigned n = num_pairs () * 2;
+      for (unsigned i = 0; i < n; ++i)
+       newmem[i] = m_base[i];
       m_base = newmem;
     }
 }
--- gcc/stor-layout.cc.jj       2023-09-27 10:37:38.951843836 +0200
+++ gcc/stor-layout.cc  2023-09-28 13:06:34.560016987 +0200
@@ -2946,7 +2946,7 @@ set_min_and_max_values_for_integral_type
   if (precision < 1)
     return;
 
-  gcc_assert (precision <= WIDE_INT_MAX_PRECISION);
+  gcc_assert (precision <= WIDEST_INT_MAX_PRECISION);
 
   TYPE_MIN_VALUE (type)
     = wide_int_to_tree (type, wi::min_value (precision, sgn));
--- gcc/wide-int-print.cc.jj    2023-09-27 10:37:39.379837876 +0200
+++ gcc/wide-int-print.cc       2023-09-28 14:24:04.824794192 +0200
@@ -74,9 +74,12 @@ print_decs (const wide_int_ref &wi, char
 void
 print_decs (const wide_int_ref &wi, FILE *file)
 {
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
-  print_decs (wi, buf);
-  fputs (buf, file);
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+  unsigned len = wi.get_len ();
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS))
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  print_decs (wi, p);
+  fputs (p, file);
 }
 
 /* Try to print the unsigned self in decimal to BUF if the number fits
@@ -98,9 +101,12 @@ print_decu (const wide_int_ref &wi, char
 void
 print_decu (const wide_int_ref &wi, FILE *file)
 {
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
-  print_decu (wi, buf);
-  fputs (buf, file);
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+  unsigned len = wi.get_len ();
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS))
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  print_decu (wi, p);
+  fputs (p, file);
 }
 
 void
@@ -134,9 +140,12 @@ print_hex (const wide_int_ref &val, char
 void
 print_hex (const wide_int_ref &wi, FILE *file)
 {
-  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
-  print_hex (wi, buf);
-  fputs (buf, file);
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE], *p = buf;
+  unsigned len = wi.get_len ();
+  if (UNLIKELY (len > WIDE_INT_MAX_ELTS))
+    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);
+  print_hex (wi, p);
+  fputs (p, file);
 }
 
 /* Print larger precision wide_int.  Not defined as inline in a header
--- gcc/testsuite/gcc.dg/bitint-38.c.jj 2023-09-28 15:02:23.182069788 +0200
+++ gcc/testsuite/gcc.dg/bitint-38.c    2023-09-28 15:02:39.168848976 +0200
@@ -0,0 +1,17 @@
+/* PR c/102989 */
+/* { dg-do compile { target { bitint } } } */
+
+#if __BITINT_MAXWIDTH__ >= 16319
+constexpr unsigned _BitInt(16319) a
+  = 
468098567701677261276215481936770442254383643766995378241600227179396283432916865881332215867106489159251577495372085663487092317743244770597287633199005374998455333587280357490149993101811392051483761495987108264964738337118155155862715438910721661230332533185335581757600511846854115932637261969633134365868695363914570578110064471868475841348589366933645410987699979080140212849909081188170910464967486231358935212897096260626033055536141835599284498474737858487658470115144771923114826312283863035503700600141440724426364699636330240414271275626021294939422483250619629005959992243418661230122132667769781183790338759345884903821695590991577228520523725302048215447841573113840811593638413425054938213262961448317898574140533090004992732688525115004782973893244091427000396890427152225308661078954671066069234453757593181753900865203439035402480306413572239610467142591920809187367438071170100969567440044691427487959785637338381651309916782063670286046547585240837892307170928849485877186793280707600840866783471799148179250818387716183127323346199533387463363442356218803779697005759324410376476855222420876262425985571982818180353870410149824214544313013285199544193496624223219986402944849622489422007678564946174797892795089330899535624727777525330789492703574564112252955147770942929761545604350869404246558274752353510370157229485004402131043153454290397929387276374054938578976878606467217359398684275050519104413914286024106808116340712273059427362293703151355498336213170698894448405369398757188523160460292714875857879968173578328191358215972493513271297875634400793301929250052822258636015650857683023900709845410838487936778533250407886180954576046340697908584020951295048844938047865657029072850797442976146895294184993736999505485665742811313795405530674199848055802759901786376822069529342971261963119332476504064285869362049662083405789828433132154933242817432809415810548180658750393692272729586232842065658490971201927780014258815333115459695117942273551876646844821076723664040282772834511419891351278169017103987094803829594286352340468346618726088781492626816188657331359104171819822673805856317828499039088088223137258297373929043307673570090396947789598799922928643843532617012164811074618881774622628943539037974883812689130801860915090035870244061005819418130068390986470314677853605080103313411837904358287837401546257413240466939893527508931541065241929872307203876443882106193262544652290132364691671910332006127864146991404015366683569317248057949596070354929361158326955551600236075268435044105880162798380799161607987365282458662031599096921825176202707890730023698706855762932691688259365358964076595824577775275991183149118372047206055118463112864604063853894820407249837871368934941438119680605528546887256934334246075596746410297954458632358171428714141820918183384435681332379317541048252391710712196623406338702061195213724569303285402242853671386113148211535691685461836458295037538034378318055108240082414441205300401526732399959228346926528586852743389490978734787926721999855388794711837164423007719626109179005466113706450765269687580819822772189301084503627297389675134228222337286867641110511061980231247884533492442898936743429641958314135329073406495776369208158032115883850691010569048983941126771477990976092252391972812691669847446798507244106121667885423025613769258102773855537509733295805013313937402282804897213847221072647111605172349464564089914906493508133855389627177663426057763252086286325343811254757681803068276278048757997425284334713190226818463023074461900176958010055572434983135171145365242339273326984465181064287264645470832091115100640584104375577304056951969456200138485313560009272338228103637763863289261673258726736753407044143664079479496972580560534494806170810469304773005873590626280072387999668522546747985701599613975101188543857852141559251634058676718308000324869809628199442681565615662912626022796064414496106344236431285697688357707992989966561557171729972093533007476947862215922583204811189015550505642082475400647639520782187776825395598257421714106473869797642678266380755873356747812273977691604147842741151722919464734890326772594979022403228191075586910464204870254674290437668861177639713112762996390246102030994917186957826982084194156870398312336059100521566034092740694642613192909850644003933745129291062576341213874815510099835708723355432970090139671120232910747665906191360160259512198160849784197597300106223945960886603127136037120000864968668651452411048372895607382907494278810971475663944948791458618662250238375166523484847507342040066801856222328988662049579299600545682490412754483621051190231623196265549391964259780178070495642538883789503379406531279338866955157646654913405181879254189185904298325865503395688786311067669273609670603076582607253527084977744533187145642686236350165593980428575119329911921382240780504527422630654086941060242757131313184709635181001199631726283364158943337968797uwb
+    + 
9935443518057456429927126655222257817207511311671335832560065573055276678747990652907348839741818562757939084649073348172108397183827020377941725983107513636287406530526358253508437290241937276908386282904353079102904535675608604576486162998319427702851278408213641454837223079616401615875672453250148421679223829417834227518133091055180270249266161676677176149675164257640812344297935650729629801878758059944090168862730519817203352341458310363811482318083270232434329317323822818991134500601669868922396013512969477839456472345812312321924215241849772147687455760224559240952737319009348540894966363568158349501355229264646770018071590502441702787269097973979899837683122194103110089728425676690246091146993955037918425772840022288222832932542516091501149477160856564464376910293230091963573119230648026667896399352790982611957569978972038178519570278447540707502861678502657905192743225893225663994807568918644898273702285483676385717651104042002105352993176512166420085064452431753181365805833548922676748890412420332694609096819779765600345216390394307257556778223743443958983962113723193551247897995423762348092103893683711373897139168289420267660611409947644548715007787832959251167553175096639147674776117973100447903243626902892382263767591328038235708593401563793019418124453166386471792468421003855894206584354731489363668134077946203546067237235657746480296831651791790385981397558458905904641394246279782746736009101862366868068363411976388557697921914317179371206444085390779634831369723370050764678852846779369497232374780691905280992368079762747352245519607264154197148958896955661904214909184952289996142050604821608749900417845137727596903100452350067551305840998280482775209883278873071895588751811462342517825753493814997918418437455474992422243919549967371964423457440287296270855605850954685912644303354019058716916735522533065323057755479803668782530250381988211075034655760123250249441440684338450953823290346909689822527652698723502872312570305261196768477498898020793071808758903381796873868682378850925211629392760628685222745073544116615635557910805357623590218023715832716372532519372862093828545797325567803691998051785156065861566888871461130133522039321843439017964382030080752476709398731341173062430275003111954907627837208488348686666904765710656917706470924318432160155450726007668035494571779793129212242101293274853237850848806152774463689243426683295884648680790240363097015218347966399166380090370628591288712305133171869639679922854066493076773166970190482988828017031016891561971986279675371963020932469337264061317786330566839383989384760935590299287963546863848119999451739548405124001514033096695605580766121611440638549988895970262425133218159848061727217163487131806481686766843789971465247903534853837951413845786667122427182648989156599529647439419553785158561613114023267303869927565170507781782366447011340851258178534101585950081423437703778492347448230473897643505773957385504112182446690585033823747175966929091293693201061858670141209129091452861292276276012910624071241165402089161606944423826245461608594935732481900198240862293409442308800690019550831630479883000579884614601906961723011354449804576794339826056986957680090916046848673419723529694384653809400377218545075269148766129194637039408225515678013332188074997217667835494940043014917877438354902673107453164275280010251040360040937308738925689475725131639032011979009642713542292894219059352972933151112376197383814925363288670995556269447804994925086791728136906693249507115097807060365872110998210768336078389508724184863597285987736912073071980137162590779664675033429119327855307827174673749257462983054221631797527009987595732460222197367608440973488211898471439302051388806818521659685873672383828021329848153410204926607710971678268541677584421695238011784351386047869158787156634630693872428067864980320063293435887574745859067024988485742353278548704467544298793511583587659713711677065792371199329419372392720321981862269890024832348999865449339856339220386853162641984444934998176248821703154774794026863423846665361147912580310179333239849314145158103813724371277156031826070213656189218428551171492579367736652650240510840524479280661922149370381404863668038229922105064658335083314946842545978050497021795217124947959575065471749872278802756371390871441004232633252611825748658593540667831098874027223327541523742857750954119615708541514145110863925049204517574000824797900817585376961462754521495100198829675100958066639531958106704159717265035205597161047879510849900587565746603225763129877434317949842105742386965886137117798642168190733367414126797929434627532307855448841035433795229031275545885872876848846666666475465866905332293095381494096702328649920740506658930503053162777944821433383407283155178707970906458023827141681140372968356084617001053870499079884384019820875585843129082894687740533946763756846924952825251383026364635539377880784234770789463152435704464616uwb;
+constexpr unsigned _BitInt(16319) b
+  = 
20129744567093027275741005070628998262449166046517026903695683755854448756834360166513132405078796314602781998330705368407367482030156637206994877425582250124595106718397028199112773892105727478029626122540718672466812244172521968825004812596684190534400169291245019886664334632347203172906471830047918779870667296830826108769036384267604969509336398421516482677170697323144807237345130767733861415665037591249948490085867356183319101541167176586195051721766552194667530417142250556133895688441663400613014781276825394358975458967475147806589013506569415945496841131100738180426238464950629268379774013285627049621529192047736803089092751891513992605419086502588233332057296638567290306093910878742093500873864277174719410183640765821580587831967716708363976225535905317908137780497267444416760176647705834046996010820212494244083222254037700699529789991033448979912128507710343500466786839351071045788239200231971288879352062329627654083430317549832483148696514166354870702716570783257707960927427529476249626444239951812293100465038963807939297639901456086408459677292249078230581624034160083198437374539728677906306289960873601083706201882999243554025429957091619812945018432503309674349427513057767160754691227365332241845175797106713295593063635202655344273695438810685712451003351469460085582752740414723264094665962205140763820691773090780866423727990711323748512766522537850976590598658397979845215595029782750537140603588592215363608992433922289542233458102634259275757690440754308009593855238137227351798446486981151672766513716998027602215751256719370429397129549459120277202327118788743080998483470436192625398340057850391478909668185290635380423955404607217710958636050373730838469336370845039431945543326700579270919052885975364141422331087288874462285858637176621255141698264412903522678033317989170115880081516284097559300133507799471895326457336815172421155995525168781635131143991136416642016744949082321204689839861376266795485532171923826942486502913400286963940309484507484129423576156798044985198780159055788525538310878089397895175129162099671894337526801235280427428321205321530735108239848594278720839317921782831352363541199919557577597546876704462612904924694431903072332864341465745291866718067601041404212430941956177407763481845568339170224196193106463030409080073136605433869775860974939991008596874978506245689726966715206639438259724689301019692258116991317695012205036157177039536905494005833948384397446492918129185274359806145454148241131925838562069991934872329314452016900728948186477387223161994145551216156032211038319475270853818660079065895119923373317496777184177315345923787700803986965175033224375435249224949151191006574511519055220741174631165879299688118138728380219550143006894817522270338472413899079751917314505754802052988622174392135207139715960212346858882422543222621408433817817181595201086403368301839080592455115463829425708132345811270911456928961301265223101989524481521721969838980208647528038509328501705428950749820080720418776718084142086501267418284241370398868561282277848391673847937247873117719906103441015578245152673184719538896073697272475250261227685660058944107087333786104761624391816175414338999215260190162551489343436332492645887029551964578826432156700872459216605843463884228343167159924792752429816064841479438134662749621639560203443871326810129872763539114284811330805213188716333471069710270583945841626338361700846410927750916663908367683188084193258384935122236639934335284160522042065088923421928660724095726039642836343542211473282392554371973074108770797447448654428325845253304889062021031599531436606775029315849674756213988932349651640552571880780461452187094400408403309806507698230071584809861634596000425300485805174853406774961321055086995665513868382285048348264250174388793184093524675621762558537763747237314473883173686633576273836946507237880619627632543093619281096675643877749217588495383292078713230253993525326209732859301842016440189010027733234997657748351253359664018894197346327201303258090754079801393874104215986193719394144148559622409051961205332355846077533183278890738832391535561074612724819789952480872328880408266970201766239451001690274739141595541572957753788951050043026811943691163688663710637928472363177936029259448725818579129920714382357882142208643606823754520733994646572586821541644398149238544337745998203264678454665487925173493921777764033537269522992103115842823750405588538846833724101543165897489915300004787110814394934465518176677482202804123781727309993329004830726928892557850582806559007396866888620985629055058474721708813614135721948922060211334334572381348586196886746758900465692833094336637178459072850215866106799456460266354416689624866015411034238864944123721969568161372557215009049887790769403406590484422511214573790761107726077762451440539965975955360773797196902546431341823788555069435728043202455375041817472821677779625286961992491729576392881089462100341878uwb
+    / 42uwb;
+constexpr unsigned _BitInt(16319) c
+  = 
26277232382028447345935282100364413976442241120491848683780108318345774920397366452596924421335605374686659278612312801604887370376076386444511450318895545695570784577285598906650901929444302296033412199632594998376064124714220414913923213779444306833277388995703552219430575080927111195417046911177019070713847128826447830096432003962403463656558600431115273248877177875063381111477888059798858016050213420475851620413016793445517539227019973682699447952322388748860981947593432985730684746088183583225184347825110697327973294826205227564425769950503423435597165969299975681406974619941538502827193742760455245269483134360940023933986344217577102114800134253879530890064362520368475535738854741806292542624386473461274620987891355541987873664157022522167908591164654787501854546457737341526763516705032705254046172926268968997302379261582933264475402063191548343982201230445504659038868786347667710658240088825869575188227013335559298579845948690316856611693386990691782821847535492639223427223360712994033576990398197160051785889033125034223732954451076425681456628201904077784454089380196178912326887148822779198657689238010492393879170486604804437202791286852035982584159978541711417080787022338893101116171974852272032081114570327098305927880933671644227124990161298341841320653588271798586647749346370617067175316167393884414111921877638201303618067479025167446526964230732790261566590993315887290551248612349150417516918700813876388862131622594037955509016393068514645257179527317715173019090736514553638608004576856188118523434383702648256819068546345047653068719910165573154521302405552789235554333112380164692074092017083602440917300094238211450798274305773890594242881597233221582216100516212402569681571888843321851284369613879319709906369098535804168065394213774970627125064665536078444150533436796088491087726051879648804306086489894004214709726215682689504951069889191755818331155532574370572928592103344141366890552816031266922028893616252999452323417869066941579667306347161357254079241809644500681547267163742601555111699376923690500014172294337681007418735910341792131377741308586228268385825579773985382339854821729670313925456724869607910114957040810377671394779834675225181536565444830551924417794139736686594557660483813045525089850285373756403594900392226296617656189774567019900237644329891280192776067340109751100025818473155267503490628146429306493520953677660612094758307190480072039980575323428994009982415676875786338343681850769724258724712947129844865182522700509869810541147515988955709784790248266593581532414091983670376426534289079098742549505127694160521110700035496658932724007621759500091227595477831200325335242614162624218010753586306794482732500765136299548052958345872488446969032973871418565484570096440609125401439516349061951073344772753817168731533186740449206533184858409824331269879276752302819075938894191764603880669059804914705202932220114574769307945938446355744093058483466098741029671133305308451601510124097336668044362140994842230895354232007936193610666215236351383330719496758577095102466235782700820575938453736277546445932135116947993404356975890051717304128693125699951445791328843668647245439797933691355015781238038148597339831348341049751957204680813855138272253234219030458164179195368888878989362640509486440530112337687890165646824152338885218611665567933423652236621168833497594762922586523151554244316284075364923316223457798336995440229801638249044555841786652868778333857626201712694823945146208412572567947403078655159448178467488335673853886982143607843369103504905837049147006413324087204923968347162406372146304110247436210704329838033967549296094708909042352807942165389054391217609084676765464997803900415653278041220586434133698802658726748950122980183615091029049242919298428066745937148593879994539254240070220900694662200741796632687373414952817000938093930497338259168439649970963774406833411431113922194082765390241161715106142638681072839764035976877223152727829248475639970029777900589595383604989099084081251802305001465530685587689066710306032849298712531664047230963409638484129598076118133347670029704549206295184751171783054889490211218045322681317529569999778899567668829982207035948032411418382057247326141072264502161892285323531743728756335449414720326329614400327415751813608405440522389476951223717685562226240221655814783640319063683104993438443847695342093582440489676230855515734722099028773790309518629302472390856918840009781940193713784596688294176313226823907143925396584175086934911386332502448539920116580493698106175151294846382915609543814748269873022997601962804377576934064368480060369871027634248583037300264157126892396407333810094970488786868749240778818119777818968060847669660858189435863648299750130319878885182309492320093569553086644726783916663680961005542160003603514646606310756647257217877792590840884087816175376150368236330721380807047180835128240716072193739218623529235235449408073833764uwb
+    >> 171;
+static_assert (a == 
10403542085759133691203342137159028259461894955438331210801665800234672962180907518788681055608925051917190662144445433835595489501570265148539013616306519011285861864113638610998587283343748668959870044400340187367869274012726759732348878437230149364081610941398977036594823591463255731808309715219781556045092524781748798096243155527048746090614751043610821560662864236720952557147844731917800712343725546175449104075627616077829385396994452199410766816558008090921987787438967590914249326913953731957899714113110918563882837045448642562338486517475793442626878243475178869958697311252767202125088496235928130685145568023992654921893286093433280015789621699281948053130963767216950901322064090115301029360256916486236324346980555378227825665231041206505932451054100655891377307183657244188881780309602697733965633806548575793711470844175477213922050584861112947113328821094578714380110663964395764964375008963336325761662071121014767368961020824065775639039724097407257977371623360602667242992626829630277589757195892131842788347638167481783472539736593840645020141666099662762763659119482517961624374850646183224354529879255694192077493038699570091875155722960929748259201284457182471153956119946261637096783796538046622701136421992223281799392319105563566498086105138357131671079600937329401554014025354725298453142629483842874038291307431207948198280389112036878226218928165845324560374437065373122000792930554833265840423016148390974876479752688661617125284208020330726704780298561478529279775092768807953202013307072084373090254748865483609183726295735240865516817482898554990450888147008484162850924835809973020042760450232447237837196378388135483084055028396408249214425019231777824054821326738728924661602608905318664721047678808734917923923121217803736039325080641571812479260200189082647677675380297657174607422686495562781202604884582727406463545308236800937463493199421020490845203940782000643133713413924683795888948837880891750307666957538835987772265423203470320354145742841869795472799186154631385288573730129094228733379855432514817031425884584962254283999586850250406406681047191820544352342046667950146374296364655891915135310082529994904874562441551527081311638121766367661807914647092917287784017613115795691373814041086838720316968010349263776702775009771662737124600992709418630470128579612748138807983617697487500079502839532266478317788699680283395230308668613168191852557234122469290277763000256531531071762280960597416576452124575885006363492171314551026369237325119844147154972582617127637240421323781252125819313268498872048683068789228870983086306586111793007178693570562554975762384431236664489360478109692520183356042112794589756922036102025380888246082763911915622037570736969677850621708281909652070776450422110772285659921383413532725137107621514770958361581240471968542997294446402584844918179956881219978405772785713402046471903103404871352324277109089891640558983922159359479964068994923538490500501798825116238188381267330618026093160290205596669795981834842352271011063939632623926629960113926326029952143452354640614061049438932665467928443113232214498101774523178129020155017228802221901469548072234073334681052461327832268955923701109732874360984002493130025470753861967432493102395766279717815113135763810886216491770265724160887688887515282293447287121039545323777928286876711267049135547760773655845950622676327972280622345486253084626121247885891757458308974259466441284967765824561478351421051923081842594791616249682768594796413184742007504540382141773556098929461233842797978566466734240436032269122908057438314319410489575244845739320693764798687398942275314333361838560358278583766983210126081046020231469705836544611252075187733112560778125560225565803349953151880800601890382648216375737077015744684142132303864494083237680306898134033570758401131735819237730280209424231954121970154195575070728876653187928423918894211617093567094857926079694003950142962763480728907322409338954277493711834363423032309296862081371923061150409402403668284066920335645815769603890931600189625120845560771835017710222988445713995722670892970377791415975424998772977793133120924108755323766471601770964843725827421304729349535336212587039242582503381150992918495310760366078232133800372960134691178665615437284018675587037783965019497398984583781291648236566997741116811234934754542646608973862932050896956712947890625239848619289180051302224085308716715734850608995498117691600907423641124622236235949675965926735290984369155077055324647942699875972019355174794849379024365265476001505043957802797349447782453767742359446787304217770032967959809288342189111153359045680464231699344620995535326063943372491385550455978845273436611631962336651743357242055102619760848116407351488643448217122169718350824452317641509534606434395208225350712889271762643740106849245478364448395994915755050465135468245061369394410933866013068008514339549345174558881983866497072827311379042433413uwb);
+static_assert (b == 
479279632549833982755738215967357101486884905869453021516563898948915446591294289678884104882828483681018619007873937343032559095956110409690354224418625002966550159961834004740780330764422082810229193393826635058733624861250523067262019347540099774628575459315357616349150824579695313640630281667807589996920649924543478780215152006371546893079438057655154349456445174360590648508217399231758605134881847410713059287758746575793311941456361347290358374327775052253988819455767870384140373534325319062214637649448223675213701403987503519204500321584986093940400979311922337629196153927395934961423190792514929752893552191612781025930779806940809347748073488156862698382316586632554531097474068541478416687472958980350462147229542043370966376951612302580094672036569174235908042392792082009922861348754900810642762162386011767716267196524707159512614047405558309045526869231198654773018734270263596328291409529332649735222668150705420335319769465472201979730869384913211207207537399601373999069700655463720229201053332186006978582500927709712840419997653716343058563745053549481680514857956192457105651774755444712054911665735085740088242901976172465572034046597419519355833772202459754151176845548994456208445029222984100996313709454921745133168181790539412958897510447873469344071508368320478228160779533683887240349189576312875329064089835494782533898285493126755916970631488996451823585682342809043933704643566255965170014371156957508657356962712435465291272811967482363708516439065578762133187029479457794090439202070979801732536040880905419100375029921889772128503084510931435171483979018779597166630558819909348223770001377390273307373052030729413819617985823981374070443715485088829487365151686786653141560555397632839783786973475603908129103121125925582435377586599443363217659482486021512444715078999742145616192417054383275221431750185701711793487079447980295741809417265923372265027237884200396238493927359102885825948568128006352273465051712472070059202450319054451522388321059702003081513718019001071076161432358471155369959782811652330837503075288087426055655400029411438748293362031465017502577139252244731448555188613876936961036695236179942323751116112011014592974397486473882674592008130136792663493287323834319147915022427528033518178139180198551672004671264439595962120954122300129377851806213689047404966592261393005849755403969409681891387136302126214754577574214078992738385834194218500941354892714424617818676129678402812599649389519193939384481931712519965763571236544579269391714688112594004439937791027666527275028956096005024721892268353662349049501568931426746983749923266289936079664852088114380642027976981532748458314879741695023966059798072743350980348361092364278288527112580481417860547783209941006436630295569025708378983678708447667928300527961717504931897999052674925211486251029110033534138519456704647644914365911948549537915597987234033945431722519315974082307832411934886264333083916226707665948547147824941143774031630992986403589281430493343304207573431954440506367102005746914258775268625663056944615427077330312326664431034309894720122682694874274735620802316011315482410182991906165335883031756812018133914090861319389023790839528337203606889129436487920140167370284870924438860873830296648014424844378195912932551426780779819757525353368558050825303562419989528653425507781193568399131883673447888828695552112293654073088339775808234324436627659543962164946450396759723040075906766506152022264815158093674649622869572430121164843379253826764183953324829436751005035078152203675523168431161209463034491772102996315554878311000500752369796109685119745615468446576523546008325039060775520970963367909216533343057221662059707100715990114520515109428581554773471551782223970832412406073499896797949247197263055911053575580685552002226777990994346631851517791364630330551754443656577948498726362806681419705536740324268597539896282803552799726080554573302695958428417269671660306173853381343814024048279362738039470198839365706286164147555864933364363287875097138128425573909904433183795098670203800533548856219174579901097084123411402160448390274656216062207733804522678116007830485911118338137291415500040244636646228465275546613185451215477214924093897408659253897872331630294361379429268082112519489979283826532913282908147824847781517964779380824918394924322420104717839012960422523766744397106063463998218416521947089619846125464833145312281971994057275917591591279145274837283273569411904875883590818927011083766111368623876288661469697856984023924541117354584710728162060928747544449729071086406072820826707352705098469570212430005031769870770984490147544922541878582516496026055634218534739829767044431114272772863484628968800592047985977005687260574374332608765746965647976405949709304033414442630581488362251756922883517287565772653346189666094175256518980878632057889091042584644510374477219106080358138511257658994752983022904583136418485544787844335722425uwb);
+static_assert (c == 
8779107423697189837569390605084121179785924908521985744210325591223667924519652625818373720019509245903707006132632572173386255064201355735198759440688262514780984111791042739566301784897316373994922192050963272288434060342288511971569697680026523760811225516430052699754044682818892679819131995600216280966062736732384732411361657444399695883865096103428759622813867735547259978529319436889864013687219390567604283318011100799953451520968441264866031813954488628058475114348729275414143158917874709599556247183695853838552321088973445876088042556810479910661449374661999675082811103814453353294194886612961492737263277271551889038610730760478459569256149321998350414023066363814989311109728311712989022996247280182587921449185353922885937877604500400738774240008709945289791605011177739657720181601453512259882004564462415828652714904289727235210537277721389816687643366145200001177712112197515695578887483792988755435401388456145854488880537088360397994643216014828495662460205686448548113229841097955613958440901375416256532864511852298696327611517233241324799070919491286426159788792631723833717451538043437364017185237743182402835670087683125602640318887451596650323528720128188198547270462971612157603487958526705005955580409441670771849388016438035850194585870327013409236236730914217722025655319472231141666790287955685713636274653565577454275838590350806168639165264676470440930351612992518904664647715805865941038423768376846697817543122409517591717292238745940345900530458551468519245767864531742102178628854376524513367983209186974575765707273973775386840081238803880335095740836386527208267311808973522450391189055739828936937359693167240524660624945856907042041257347192086984009640984509322622503890256046324768341632643546455779035376002061691113121234273164937984171774242327769915688742564049454163158318121818582764775268091292470889088445575108022688069271697198283151469645400870507006663799330661702702747443254220478311056407220749648103123435473381583520873055218734115120978678440455896458852497569989966723235965608706826593607128847630137618509151255834742636438796285569873869967729341871213521030011427372987388572674228441333458857512226049283243347521457804912008781036966786374760325341492033297848368160903260470019067535330611645909560888797451907088389764190403007998305168673029446934012245138838180596098559442570696150011296218144186387024615885302290744905340666905921743970013779813332493771192048043297281423248489056841417013807670308191095732464221451376997270745468459702152796818222745730565721202663103043121160101459833683249558684459108862536961994308535039970814557821268170388745941980378838969910592895670554291811739768771829941043857819603751246957962236091154755893962038363120690483862423001038948620681611253867149296463690417828034303547922792249098522404751428960713875050463906134150846089705714470303918299012691600285355859412924847760497076978432722446602521825089097454542343354847347396045079587757210635356999268706465425788833311190517623061860675230010994127196459030322166751571656642321690787471906609473496034789643710478162255664092991251446787887635351852933826820719781733754578161073401362668109819113924252291125741395271474342305574536974918273938513597418963787308994593434191890687730302495910686072338836413159162281072263542758257699588089838677469397467899348065293581751035844389848387161847435160327276066603683131703246410409122832793376751512688745195564021646069245992363396468100513536211651450610523315211697125774638845313243973083536417692075962486918844667432144353019722959653638632948294049984266861870151255315023346724671430499257993958049088066160870545025276597975154855537620265690354041028742742755074396597631965320380782500944568424053420038357524917125099241334990032189526465838192972110970861380060986802081948044345526414857158569939005895236672306344348212805851269920711043891306875873016330601673973249327072503571873518366750575070091051288590764788630190966776854031578939382690709022667421734442841784680826494146620589862829612704279521637740421694195051400095278084716974624615208392585573200182664157066813849346058321763156523965698465901396025152159642193562900743812715885811057212579017860488539960334406702752688595217360219470968738009774067915037157027492209108801337707562571266897723911401203374308490793226200974353356835311756384895692909802720948968131504604855466961987314701846460342135201914356152591684810924688350929140120187693089324255924634578576427004426339299493833434502951593902551451002292839635000904253250021884625417628756439862964325562720709528784964868687330847894476999577326582332350213148861205413652337499383416531545707272907994755638339630221576707954964236210962693804639714754668679841134928393081284209158098202683744650513918920168330598432362389777471870631039488408769354863001967531729415686631571754649uwb);
+#endif

        Jakub

Reply via email to