From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by sourceware.org (Postfix) with ESMTPS id CD5203858D28 for ; Tue, 10 Oct 2023 09:30:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CD5203858D28 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id A884A21854; Tue, 10 Oct 2023 09:30:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1696930231; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=50PgONvXNCbtN9DF9ftNVOUbS09v/Q25NTL65IB1Vcg=; b=hYH/gHjc08Um54isGSHSY+EJtsIMNxbe66H4ieXZcJmRH8/W7d+bZegPLCGeKXaMiP6iMb p15w5pPs/CmFZADJX53L3wCLXY3fqAq57JXSGHXMQufRyu4WACfJOOR3TLnckolfJ/nvZ+ DmFoIQwOsYDTKrXr8IQv2NfjG4allG0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1696930231; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=50PgONvXNCbtN9DF9ftNVOUbS09v/Q25NTL65IB1Vcg=; b=vL20ImZ/unF8HsvDpMNHMJAzYlIKxj+2foxRZY1pKXXk4lPFAvMaQQQ/aod/Jl8Ms7TV5+ y5njSEzJRfqqTsAA== Received: from wotan.suse.de (wotan.suse.de [10.160.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by relay2.suse.de (Postfix) with ESMTPS id 5B1E92C3DE; Tue, 10 Oct 2023 09:30:31 +0000 (UTC) Date: Tue, 10 Oct 2023 09:30:31 +0000 (UTC) From: Richard Biener To: Jakub Jelinek cc: Richard Sandiford , gcc-patches@gcc.gnu.org Subject: Re: [PATCH] wide-int: Remove rwide_int, introduce dw_wide_int In-Reply-To: Message-ID: References: User-Agent: Alpine 2.22 (LSU 394 2020-01-19) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Mon, 9 Oct 2023, Jakub Jelinek wrote: > On Mon, Oct 09, 2023 at 12:55:02PM +0200, Jakub Jelinek wrote: > > This makes wide_int unusable in GC structures, so for dwarf2out > > which was the only place which needed it there is a new rwide_int type > > (restricted wide_int) which supports only up to RWIDE_INT_MAX_ELTS limbs > > inline and is trivially copyable (dwarf2out should never deal with large > > _BitInt constants, those should have been lowered earlier). > > As discussed on IRC, the dwarf2out.{h,cc} needs are actually quite limited, > it just needs to allocate new GC structures val_wide points to (constructed > from some const wide_int_ref &) and needs to call operator==, > get_precision, elt, get_len and get_val methods on it. > Even trailing_wide_int would be overkill for that, the following just adds > a new struct with precision/len and trailing val array members and > implements the needed methods (only 2 of them using wide_int_ref constructed > from those). > > Incremental patch, so far compile time tested only: LGTM, wonder if we can push this separately as prerequesite? Thanks, Richard. > --- gcc/wide-int.h.jj 2023-10-09 14:37:45.878940132 +0200 > +++ gcc/wide-int.h 2023-10-09 16:06:39.326805176 +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 four predefined flavors: > + are three predefined flavors: > > 1) wide_int (the default). This flavor does the math in the > precision of its input arguments. It is assumed (and checked) > @@ -80,12 +80,7 @@ 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 RWIDE_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. > - > - 4) widest_int. This representation is an approximation of > + 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 WIDEST_INT_MAX_PRECISION. > @@ -257,9 +252,6 @@ along with GCC; see the file COPYING3. > #define WIDE_INT_MAX_ELTS 255 > #define WIDE_INT_MAX_PRECISION (WIDE_INT_MAX_ELTS * HOST_BITS_PER_WIDE_INT) > > -#define RWIDE_INT_MAX_ELTS WIDE_INT_MAX_INL_ELTS > -#define RWIDE_INT_MAX_PRECISION WIDE_INT_MAX_INL_PRECISION > - > /* Precision of widest_int and largest _BitInt precision + 1 we can > support. */ > #define WIDEST_INT_MAX_ELTS 510 > @@ -343,7 +335,6 @@ STATIC_ASSERT (WIDE_INT_MAX_INL_ELTS < W > template class generic_wide_int; > template class fixed_wide_int_storage; > class wide_int_storage; > -class rwide_int_storage; > template class widest_int_storage; > > /* An N-bit integer. Until we can use typedef templates, use this instead. */ > @@ -352,7 +343,6 @@ template class widest_int_storag > > typedef generic_wide_int wide_int; > typedef FIXED_WIDE_INT (ADDR_MAX_PRECISION) offset_int; > -typedef generic_wide_int rwide_int; > typedef generic_wide_int > widest_int; > typedef generic_wide_int > widest2_int; > > @@ -1371,180 +1361,6 @@ wi::int_traits ::get_b > return wi::get_precision (x); > } > > -/* The storage used by rwide_int. */ > -class GTY(()) rwide_int_storage > -{ > -private: > - HOST_WIDE_INT val[RWIDE_INT_MAX_ELTS]; > - unsigned int len; > - unsigned int precision; > - > -public: > - rwide_int_storage () = default; > - template > - 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 > - 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 > - { > - 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 > - static rwide_int get_binary_result (const T1 &, const T2 &); > - template > - 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 > -inline rwide_int_storage::rwide_int_storage (const T &x) > -{ > - STATIC_ASSERT (!wi::int_traits::host_dependent_precision); > - STATIC_ASSERT (wi::int_traits::precision_type != wi::CONST_PRECISION); > - STATIC_ASSERT (wi::int_traits::precision_type > - != wi::WIDEST_CONST_PRECISION); > - WIDE_INT_REF_FOR (T) xi (x); > - precision = xi.precision; > - gcc_assert (precision <= RWIDE_INT_MAX_PRECISION); > - wi::copy (*this, xi); > -} > - > -template > -inline rwide_int_storage& > -rwide_int_storage::operator = (const T &x) > -{ > - STATIC_ASSERT (!wi::int_traits::host_dependent_precision); > - STATIC_ASSERT (wi::int_traits::precision_type != wi::CONST_PRECISION); > - STATIC_ASSERT (wi::int_traits::precision_type > - != wi::WIDEST_CONST_PRECISION); > - WIDE_INT_REF_FOR (T) xi (x); > - precision = xi.precision; > - gcc_assert (precision <= RWIDE_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 <= RWIDE_INT_MAX_PRECISION); > - x.precision = precision; > - return x; > -} > - > -template > -inline rwide_int > -wi::int_traits ::get_binary_result (const T1 &x, > - const T2 &y) > -{ > - /* This shouldn't be used for two flexible-precision inputs. */ > - STATIC_ASSERT (wi::int_traits ::precision_type != FLEXIBLE_PRECISION > - || wi::int_traits ::precision_type != FLEXIBLE_PRECISION); > - if (wi::int_traits ::precision_type == FLEXIBLE_PRECISION) > - return rwide_int::create (wi::get_precision (y)); > - else > - return rwide_int::create (wi::get_precision (x)); > -} > - > -template > -inline unsigned int > -wi::int_traits ::get_binary_precision (const T1 &x, > - const T2 &y) > -{ > - /* This shouldn't be used for two flexible-precision inputs. */ > - STATIC_ASSERT (wi::int_traits ::precision_type != FLEXIBLE_PRECISION > - || wi::int_traits ::precision_type != FLEXIBLE_PRECISION); > - if (wi::int_traits ::precision_type == FLEXIBLE_PRECISION) > - return wi::get_precision (y); > - else > - return wi::get_precision (x); > -} > - > /* The storage used by FIXED_WIDE_INT (N). */ > template > class GTY(()) fixed_wide_int_storage > @@ -4082,21 +3898,6 @@ void gt_pch_nx (generic_wide_int void gt_pch_nx (generic_wide_int *, > gt_pointer_operator, void *) = delete; > > -inline void > -gt_ggc_mx (generic_wide_int *) > -{ > -} > - > -inline void > -gt_pch_nx (generic_wide_int *) > -{ > -} > - > -inline void > -gt_pch_nx (generic_wide_int *, gt_pointer_operator, void *) > -{ > -} > - > template > void > gt_ggc_mx (generic_wide_int > *) > --- gcc/dwarf2out.h.jj 2023-10-09 14:37:45.890939965 +0200 > +++ gcc/dwarf2out.h 2023-10-09 16:46:14.705816928 +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 rwide_int *rwide_int_ptr; > +typedef struct dw_wide_int *dw_wide_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; > - rwide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide; > + dw_wide_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 > { > @@ -313,6 +313,35 @@ struct GTY(()) dw_discr_list_node { > int dw_discr_range; > }; > > +struct GTY((variable_size)) dw_wide_int { > + unsigned int precision; > + unsigned int len; > + HOST_WIDE_INT val[1]; > + > + unsigned int get_precision () const { return precision; } > + unsigned int get_len () const { return len; } > + const HOST_WIDE_INT *get_val () const { return val; } > + inline HOST_WIDE_INT elt (unsigned int) const; > + inline bool operator == (const dw_wide_int &) const; > +}; > + > +inline HOST_WIDE_INT > +dw_wide_int::elt (unsigned int i) const > +{ > + if (i < len) > + return val[i]; > + wide_int_ref ref = wi::storage_ref (val, len, precision); > + return wi::sign_mask (ref); > +} > + > +inline bool > +dw_wide_int::operator == (const dw_wide_int &o) const > +{ > + wide_int_ref ref1 = wi::storage_ref (val, len, precision); > + wide_int_ref ref2 = wi::storage_ref (o.val, o.len, o.precision); > + return ref1 == ref2; > +} > + > /* Interface from dwarf2out.cc to dwarf2cfi.cc. */ > extern struct dw_loc_descr_node *build_cfa_loc > (dw_cfa_location *, poly_int64); > --- gcc/dwarf2out.cc.jj 2023-10-09 14:37:45.894939909 +0200 > +++ gcc/dwarf2out.cc 2023-10-09 16:48:24.565014459 +0200 > @@ -397,11 +397,9 @@ dump_struct_debug (tree type, enum debug > of the number. */ > > static unsigned int > -get_full_len (const rwide_int &op) > +get_full_len (const dw_wide_int &op) > { > - int prec = wi::get_precision (op); > - return ((prec + HOST_BITS_PER_WIDE_INT - 1) > - / HOST_BITS_PER_WIDE_INT); > + return CEIL (op.get_precision (), HOST_BITS_PER_WIDE_INT); > } > > static bool > @@ -3900,7 +3898,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 rwide_int &, unsigned char *, int); > +static void insert_wide_int (const wide_int_ref &, 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); > @@ -4594,19 +4592,31 @@ AT_unsigned (dw_attr_node *a) > return a->dw_attr_val.v.val_unsigned; > } > > +dw_wide_int * > +alloc_dw_wide_int (const wide_int_ref &w) > +{ > + dw_wide_int *p > + = (dw_wide_int *) ggc_internal_alloc (sizeof (dw_wide_int) > + + ((w.get_len () - 1) > + * sizeof (HOST_WIDE_INT))); > + p->precision = w.get_precision (); > + p->len = w.get_len (); > + memcpy (p->val, w.get_val (), p->len * sizeof (HOST_WIDE_INT)); > + return p; > +} > + > /* Add an unsigned wide integer attribute value to a DIE. */ > > static inline void > add_AT_wide (dw_die_ref die, enum dwarf_attribute attr_kind, > - const rwide_int& w) > + const wide_int_ref &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 (); > - *attr.dw_attr_val.v.val_wide = w; > + attr.dw_attr_val.v.val_wide = alloc_dw_wide_int (w); > add_dwarf_attr (die, &attr); > } > > @@ -16714,8 +16724,8 @@ 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 (); > - *mem_loc_result->dw_loc_oprnd2.v.val_wide = rtx_mode_t (rtl, mode); > + mem_loc_result->dw_loc_oprnd2.v.val_wide > + = alloc_dw_wide_int (rtx_mode_t (rtl, mode)); > } > break; > > @@ -17288,8 +17298,8 @@ 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 (); > - *loc_result->dw_loc_oprnd2.v.val_wide = rtx_mode_t (rtl, int_mode); > + loc_result->dw_loc_oprnd2.v.val_wide > + = alloc_dw_wide_int (rtx_mode_t (rtl, int_mode)); > } > break; > > @@ -20189,7 +20199,7 @@ extract_int (const unsigned char *src, u > /* Writes wide_int values to dw_vec_const array. */ > > static void > -insert_wide_int (const rwide_int &val, unsigned char *dest, int elt_size) > +insert_wide_int (const wide_int_ref &val, unsigned char *dest, int elt_size) > { > int i; > > @@ -20274,8 +20284,7 @@ add_const_value_attribute (dw_die_ref di > && (GET_MODE_PRECISION (int_mode) > & (HOST_BITS_PER_WIDE_INT - 1)) == 0) > { > - rwide_int w = rtx_mode_t (rtl, int_mode); > - add_AT_wide (die, DW_AT_const_value, w); > + add_AT_wide (die, DW_AT_const_value, rtx_mode_t (rtl, int_mode)); > return true; > } > return false; > > > Jakub > > -- Richard Biener SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)