Re: [PATCH] dwarf2out: Stop using wide_int in GC structures
On Tue, 10 Oct 2023, Jakub Jelinek wrote: > Hi! > > On Tue, Oct 10, 2023 at 09:30:31AM +, Richard Biener wrote: > > On Mon, 9 Oct 2023, 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? > > Here it is as a separate independent patch. Even without the > wide_int changing patch it should save some memory, by not always > allocating room for 9 limbs, but say just the 2/3 or how many we actually > need. And, another advantage is that if we really need it at some point, > it could support even more than 9 limbs if it is created from a wide_int_ref > with get_len () > 9. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? OK by me if Jason doesn't object. Thanks, Richard. > 2023-10-10 Jakub Jelinek > > * dwarf2out.h (wide_int_ptr): Remove. > (dw_wide_int_ptr): New typedef. > (struct dw_val_node): Change type of val_wide from wide_int_ptr > to dw_wide_int_ptr. > (struct dw_wide_int): New type. > (dw_wide_int::elt): New method. > (dw_wide_int::operator ==): Likewise. > * dwarf2out.cc (get_full_len): Change argument type to > const dw_wide_int & from const wide_int &. Use CEIL. Call > get_precision method instead of calling wi::get_precision. > (alloc_dw_wide_int): New function. > (add_AT_wide): Change w argument type to const wide_int_ref & > from const wide_int &. Use alloc_dw_wide_int. > (mem_loc_descriptor, loc_descriptor): Use alloc_dw_wide_int. > (insert_wide_int): Change val argument type to const wide_int_ref & > from const wide_int &. > (add_const_value_attribute): Pass rtx_mode_t temporary directly to > add_AT_wide instead of using a temporary variable. > > --- gcc/dwarf2out.h.jj2023-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 wide_int *wide_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; > - wide_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
[PATCH] dwarf2out: Stop using wide_int in GC structures
Hi! On Tue, Oct 10, 2023 at 09:30:31AM +, Richard Biener wrote: > On Mon, 9 Oct 2023, 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? Here it is as a separate independent patch. Even without the wide_int changing patch it should save some memory, by not always allocating room for 9 limbs, but say just the 2/3 or how many we actually need. And, another advantage is that if we really need it at some point, it could support even more than 9 limbs if it is created from a wide_int_ref with get_len () > 9. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2023-10-10 Jakub Jelinek * dwarf2out.h (wide_int_ptr): Remove. (dw_wide_int_ptr): New typedef. (struct dw_val_node): Change type of val_wide from wide_int_ptr to dw_wide_int_ptr. (struct dw_wide_int): New type. (dw_wide_int::elt): New method. (dw_wide_int::operator ==): Likewise. * dwarf2out.cc (get_full_len): Change argument type to const dw_wide_int & from const wide_int &. Use CEIL. Call get_precision method instead of calling wi::get_precision. (alloc_dw_wide_int): New function. (add_AT_wide): Change w argument type to const wide_int_ref & from const wide_int &. Use alloc_dw_wide_int. (mem_loc_descriptor, loc_descriptor): Use alloc_dw_wide_int. (insert_wide_int): Change val argument type to const wide_int_ref & from const wide_int &. (add_const_value_attribute): Pass rtx_mode_t temporary directly to add_AT_wide instead of using a temporary variable. --- 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 wide_int *wide_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; - wide_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.cc2023-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 wide_int &op) +get_full_len (const dw_wide_int &op) { - int prec = wi::get_precision (op); - return ((prec + HOST_BITS_PER_WIDE_INT - 1) -