Hi, On Mon, May 22 2023, Aldy Hernandez via Gcc-patches wrote: > Implement hashing for ipa_vr. When all is said and done, all these > patches incurr a 7.64% slowdown for ipa-cp, with is entirely covered by > the similar 7% increase in this area last week. So we get type agnostic > ranges with "infinite" range precision close to free.
Do you know why/where this slow-down happens? Do we perhaps want to limit the "infiniteness" a little somehow? Also, jump functions live for a long time, have you looked at how memory hungry they become? I hope that the hashing would be good at preventing any issues. Generally, I think I OK with the patches if the impact on memory is not too bad, though I guess they depend on the one I looked at last week, so we may focus on that one first. Thanks, Martin > > There is no change in overall compilation. > > OK? > > gcc/ChangeLog: > > * ipa-prop.cc (struct ipa_vr_ggc_hash_traits): Adjust for use with > ipa_vr instead of value_range. > (gt_pch_nx): Same. > (gt_ggc_mx): Same. > (ipa_get_value_range): Same. > * value-range.cc (gt_pch_nx): Move to ipa-prop.cc and adjust for > ipa_vr. > (gt_ggc_mx): Same. > --- > gcc/ipa-prop.cc | 76 +++++++++++++++++++++++++++------------------- > gcc/value-range.cc | 15 --------- > 2 files changed, 45 insertions(+), 46 deletions(-) > > diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc > index c46a89f1b49..6383bc11e0a 100644 > --- a/gcc/ipa-prop.cc > +++ b/gcc/ipa-prop.cc > @@ -109,53 +109,53 @@ struct ipa_bit_ggc_hash_traits : public > ggc_cache_remove <ipa_bits *> > /* Hash table for avoid repeated allocations of equal ipa_bits. */ > static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits> > *ipa_bits_hash_table; > > -/* Traits for a hash table for reusing value_ranges used for IPA. Note that > - the equiv bitmap is not hashed and is expected to be NULL. */ > +/* Traits for a hash table for reusing ranges. */ > > -struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <value_range *> > +struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <ipa_vr *> > { > - typedef value_range *value_type; > - typedef value_range *compare_type; > + typedef ipa_vr *value_type; > + typedef const vrange *compare_type; > static hashval_t > - hash (const value_range *p) > + hash (const ipa_vr *p) > { > - tree min, max; > - value_range_kind kind = get_legacy_range (*p, min, max); > - inchash::hash hstate (kind); > - inchash::add_expr (min, hstate); > - inchash::add_expr (max, hstate); > + // This never get called, except in the verification code, as > + // ipa_get_value_range() calculates the hash itself. This > + // function is mostly here for completness' sake. > + Value_Range vr; > + p->get_vrange (vr); > + inchash::hash hstate; > + add_vrange (vr, hstate); > return hstate.end (); > } > static bool > - equal (const value_range *a, const value_range *b) > + equal (const ipa_vr *a, const vrange *b) > { > - return (types_compatible_p (a->type (), b->type ()) > - && *a == *b); > + return a->equal_p (*b); > } > static const bool empty_zero_p = true; > static void > - mark_empty (value_range *&p) > + mark_empty (ipa_vr *&p) > { > p = NULL; > } > static bool > - is_empty (const value_range *p) > + is_empty (const ipa_vr *p) > { > return p == NULL; > } > static bool > - is_deleted (const value_range *p) > + is_deleted (const ipa_vr *p) > { > - return p == reinterpret_cast<const value_range *> (1); > + return p == reinterpret_cast<const ipa_vr *> (1); > } > static void > - mark_deleted (value_range *&p) > + mark_deleted (ipa_vr *&p) > { > - p = reinterpret_cast<value_range *> (1); > + p = reinterpret_cast<ipa_vr *> (1); > } > }; > > -/* Hash table for avoid repeated allocations of equal value_ranges. */ > +/* Hash table for avoid repeated allocations of equal ranges. */ > static GTY ((cache)) hash_table<ipa_vr_ggc_hash_traits> *ipa_vr_hash_table; > > /* Holders of ipa cgraph hooks: */ > @@ -265,6 +265,22 @@ ipa_vr::dump (FILE *out) const > fprintf (out, "NO RANGE"); > } > > +// ?? These stubs are because we use an ipa_vr in a hash_traits and > +// hash-traits.h defines an extern of gt_ggc_mx (T &) instead of > +// picking up the gt_ggc_mx (T *) version. > +void > +gt_pch_nx (ipa_vr *&x) > +{ > + return gt_pch_nx ((ipa_vr *) x); > +} > + > +void > +gt_ggc_mx (ipa_vr *&x) > +{ > + return gt_ggc_mx ((ipa_vr *) x); > +} > + > + > /* Return true if DECL_FUNCTION_SPECIFIC_OPTIMIZATION of the decl associated > with NODE should prevent us from analyzing it for the purposes of IPA-CP. > */ > > @@ -2284,27 +2300,25 @@ ipa_set_jfunc_bits (ipa_jump_func *jf, const > widest_int &value, > jf->bits = ipa_get_ipa_bits_for_value (value, mask); > } > > -/* Return a pointer to a value_range just like *TMP, but either find it in > - ipa_vr_hash_table or allocate it in GC memory. TMP->equiv must be NULL. > */ > +/* Return a pointer to an ipa_vr just like TMP, but either find it in > + ipa_vr_hash_table or allocate it in GC memory. */ > > static ipa_vr * > ipa_get_value_range (const vrange &tmp) > { > - /* FIXME: Add hashing support. > - value_range **slot = ipa_vr_hash_table->find_slot (tmp, INSERT); > + inchash::hash hstate; > + inchash::add_vrange (tmp, hstate); > + hashval_t hash = hstate.end (); > + ipa_vr **slot = ipa_vr_hash_table->find_slot_with_hash (&tmp, hash, > INSERT); > if (*slot) > return *slot; > > - value_range *vr = new (ggc_alloc<value_range> ()) value_range; > - *vr = *tmp; > - *slot = vr; > - */ > ipa_vr *vr = new (ggc_alloc<ipa_vr> ()) ipa_vr (tmp); > - > + *slot = vr; > return vr; > } > > -/* Assign to JF a pointer to a value_range just like TMP but either fetch a > +/* Assign to JF a pointer to a range just like TMP but either fetch a > copy from ipa_vr_hash_table or allocate a new on in GC memory. */ > > static void > diff --git a/gcc/value-range.cc b/gcc/value-range.cc > index 45b1e655967..7b81025357b 100644 > --- a/gcc/value-range.cc > +++ b/gcc/value-range.cc > @@ -2008,21 +2008,6 @@ gt_pch_nx (vrange *x, gt_pointer_operator op, void > *cookie) > gcc_unreachable (); > } > > -// ?? These stubs are for ipa-prop.cc which use a value_range in a > -// hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &) > -// instead of picking up the gt_ggc_mx (T *) version. > -void > -gt_pch_nx (int_range<2> *&x) > -{ > - return gt_pch_nx ((irange *) x); > -} > - > -void > -gt_ggc_mx (int_range<2> *&x) > -{ > - return gt_ggc_mx ((irange *) x); > -} > - > #define DEFINE_INT_RANGE_INSTANCE(N) \ > template int_range<N>::int_range(tree_node *, > \ > const wide_int &, \ > -- > 2.40.1