From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id F24DA3858C78 for ; Mon, 9 Oct 2023 14:59:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F24DA3858C78 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1696863573; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references; bh=690p+x9Gp8htN/dDE+HFltKEQQpXbn8VTDnroaV8BRk=; b=SQFzVC09wDaXMF0YgYy+zSr8IDPU+U2J1ubuNp8zfvqjiZG+lC1ytUTnv5vvYIh0Re9SPX GV7Ye0bQuGVg64cGv7O/R/PRDHPEqdJE4SUteq5x6kF/wkXIt7YQ1DRN2KnDOZyywkk7CU XfDMQ0GlpaGLuPAILWNd04LlsDsMUjo= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-274-Y-sRORf9MeGwvoP3pWxICw-1; Mon, 09 Oct 2023 10:59:30 -0400 X-MC-Unique: Y-sRORf9MeGwvoP3pWxICw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id F25981C0BB50; Mon, 9 Oct 2023 14:59:29 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.193.202]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9297636F0; Mon, 9 Oct 2023 14:59:29 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 399ExQfZ797707 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 9 Oct 2023 16:59:27 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 399ExP9S797706; Mon, 9 Oct 2023 16:59:25 +0200 Date: Mon, 9 Oct 2023 16:59:25 +0200 From: Jakub Jelinek To: Richard Biener , Richard Sandiford , gcc-patches@gcc.gnu.org Subject: [PATCH] wide-int: Remove rwide_int, introduce dw_wide_int Message-ID: Reply-To: Jakub Jelinek References: MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,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, 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: --- 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 *, 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