Jakub Jelinek <ja...@redhat.com> writes:
> On Mon, Oct 09, 2023 at 03:44:10PM +0200, Jakub Jelinek wrote:
>> Thanks, just quick answers, will work on patch adjustments after trying to
>> get rid of rwide_int (seems dwarf2out has very limited needs from it, just
>> some routine to construct it in GCed memory (and never change afterwards)
>> from const wide_int_ref & or so, and then working operator ==,
>> get_precision, elt, get_len and get_val methods, so I think we could just
>> have a struct dw_wide_int { unsigned int prec, len; HOST_WIDE_INT val[1]; };
>> and perform the methods on it after converting to a storage ref.
>
> Now in patch form (again, incremental).
>
>> > Does the variable-length memcpy pay for itself?  If so, perhaps that's a
>> > sign that we should have a smaller inline buffer for this class (say 2 
>> > HWIs).
>> 
>> Guess I'll try to see what results in smaller .text size.
>
> I've left the memcpy changes into a separate patch (incremental, attached).
> Seems that second patch results in .text growth by 16256 bytes (0.04%),
> though I'd bet it probably makes compile time tiny bit faster because it
> replaces an out of line memcpy (caused by variable length) with inlined one.
>
> With even the third one it shrinks by 84544 bytes (0.21% down), but the
> extra statistics patch then shows massive number of allocations after
> running make check-gcc check-g++ check-gfortran for just a minute or two.
> On the widest_int side, I see (first number from sort | uniq -c | sort -nr,
> second the estimated or final len)
> 7289034 4
>  173586 5
>   21819 6
> i.e. there are tons of widest_ints which need len 4 (or perhaps just
> have it as upper estimation), maybe even 5 would be nice.

Thanks for running the stats.  That's definitely a lot more than I expected.

> On the wide_int side, I see
>  155291 576
> (supposedly because of bound_wide_int, where we create wide_int_ref from
> the 576-bit precision bound_wide_int and then create 576-bit wide_int when
> using unary or binary operation on that).

576 bits seems quite a lot for a loop bound.  We're enterning near-infinite
territory with 128 bits. :)  But I don't want to rehash old discussions.
If we take this size for wide_int as given, then...

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

...I agree we might as well keep the widest_int size the same for
simplicity.  It'd only be worth distinguishing them if we have positive
proof that it's worthwhile.

So going with patches 1 + 2 sounds good to me, but I don't have a strong
preference.

On the wide-int.cc changes:

> @@ -1469,6 +1452,36 @@ wi::mul_internal (HOST_WIDE_INT *val, co
>        return 1;
>      }
> 
> +  /* The sizes here are scaled to support a 2x WIDE_INT_MAX_INL_PRECISION by 
> 2x
> +     WIDE_INT_MAX_INL_PRECISION yielding a 4x WIDE_INT_MAX_INL_PRECISION
> +     result.  */
> +
> +  unsigned HOST_HALF_WIDE_INT
> +    ubuf[4 * WIDE_INT_MAX_INL_PRECISION / HOST_BITS_PER_HALF_WIDE_INT];
> +  unsigned HOST_HALF_WIDE_INT
> +    vbuf[4 * WIDE_INT_MAX_INL_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_INL_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_INL_PRECISION && !high)
> +    prec = (op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT;

Changing the precision looked a bit dangerous at first, but I agree it
looks correct in context, in that nothing later on seems to require prec
to be the real precision of the number.  But I wonder whether we should
instead do:

  if (!high)
    prec = MIN ((op1len + op2len + 1) * HOST_BITS_PER_WIDE_INT, prec);

so that the assumption gets a bit more testing.  Same idea for the others.
I.e. in any case where we think it's safe to reduce a precision or
length for out-of-line buffers, I think we should try to do the same
for inline ones.

I'm not sure off-hand why + 1 is safe here but + 2 is needed for the
write_val estimate.  Might be worth a comment in one place or the other.

> +  unsigned int blocks_needed = BLOCKS_NEEDED (prec);
> +  unsigned int half_blocks_needed = blocks_needed * 2;
> +  if (UNLIKELY (prec > WIDE_INT_MAX_INL_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);
> [...]
> @@ -2399,9 +2453,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_INL_ELTS))
> +    p = XALLOCAVEC (char, len * HOST_BITS_PER_WIDE_INT / 4 + 4);

Is this size enough for decimal?  E.g. to go back to the 576-bit example,
2^575 is O(10^173), but 576/4+4 == 148.

> +  print_dec (wi, p, sgn);
> +  ASSERT_STREQ (expected, p);
>  }
> 
>  /* Likewise for base 16.  */

The wide-int.cc changes LGTM otherwise.  I don't think I'm the right
person to review the other changes.

Thanks,
Richard

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

Reply via email to