On Wed, Aug 20, 2025 at 1:03 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > rtl-ssa already has a find_def function for finding the definition > of a particular resource (register or memory) at a particular point > in the program. This patch adds a similar function for looking > up uses. Both functions have amortised logarithmic complexity. > > Tested on aarch64-linux-gnu, powerpc64le-linux-gnu and > x86_64-linux-gnu. OK to install?
OK. > Richard > > > gcc/ > * rtl-ssa/accesses.h (use_lookup): New class. > * rtl-ssa/functions.h (function_info::find_def): Expand comment. > (function_info::find_use): Declare. > * rtl-ssa/member-fns.inl (use_lookup::prev_use, use_lookup::next_use) > (use_lookup::matching_use, use_lookup::matching_or_prev_use) > (use_lookup::matching_or_next_use): New member functions. > * rtl-ssa/functions.cc (function_info::find_use): Likewise. > --- > gcc/rtl-ssa/accesses.cc | 32 ++++++++++++++++++++++++++++++++ > gcc/rtl-ssa/accesses.h | 36 ++++++++++++++++++++++++++++++++++++ > gcc/rtl-ssa/functions.h | 15 +++++++++++++++ > gcc/rtl-ssa/member-fns.inl | 30 ++++++++++++++++++++++++++++++ > 4 files changed, 113 insertions(+) > > diff --git a/gcc/rtl-ssa/accesses.cc b/gcc/rtl-ssa/accesses.cc > index 3d929971f56..0415e976798 100644 > --- a/gcc/rtl-ssa/accesses.cc > +++ b/gcc/rtl-ssa/accesses.cc > @@ -1087,6 +1087,38 @@ rtl_ssa::lookup_use (splay_tree<use_info *> &tree, > insn_info *insn) > return tree.lookup (compare); > } > > +// See the comment above the declaration. > +use_lookup > +function_info::find_use (set_info *def, insn_info *insn) > +{ > + gcc_assert (!insn->is_debug_insn ()); > + use_info *first = def->first_nondebug_insn_use (); > + if (!first) > + // There are no uses. The comparison result is pretty meaningless > + // in this case. > + return { nullptr, -1 }; > + > + // See whether the first use matches. > + if (*insn <= *first->insn ()) > + { > + int comparison = (insn == first->insn () ? 0 : -1); > + return { first, comparison }; > + } > + > + // See whether the last use matches. > + use_info *last = def->last_nondebug_insn_use (); > + if (*insn >= *last->insn ()) > + { > + int comparison = (insn == last->insn () ? 0 : 1); > + return { last, comparison }; > + } > + > + // Resort to using a splay tree to search for the result. > + need_use_splay_tree (def); > + int comparison = lookup_use (def->m_use_tree, insn); > + return { def->m_use_tree.root ()->value (), comparison }; > +} > + > // Add USE to USE->def ()'s list of uses. inserting USE immediately before > // BEFORE. USE is not currently in the list. > // > diff --git a/gcc/rtl-ssa/accesses.h b/gcc/rtl-ssa/accesses.h > index 98403f78b37..b3a31fb78db 100644 > --- a/gcc/rtl-ssa/accesses.h > +++ b/gcc/rtl-ssa/accesses.h > @@ -1044,6 +1044,42 @@ public: > int comparison; > }; > > +// This class represents the result of looking for a use of a particular > +// definition at a particular point, here referred to as point P. > +// There are four states: > +// > +// - USE is null if the definition has no uses. > +// > +// - Otherwise, COMPARISON is 0 if we found a definition at P. USE then > +// contains this use. > +// > +// - Otherwise, COMPARISON is greater than 0 if we found a use that precedes > P. > +// USE then contains this use. > +// > +// - Otherwise, COMPARISON is less than zero and we found a use that follows > P. > +// USE then contains this use. > +class use_lookup > +{ > +public: > + // If we found a use at P, return that use, otherwise return null. > + use_info *matching_use () const; > + > + // If we found a use at P, return that use, otherwise return prev_use (). > + use_info *matching_or_prev_use () const; > + > + // If we found a use at P, return that use, otherwise return next_use (). > + use_info *matching_or_next_use () const; > + > + // Return the last use that occurs before P, or null if none. > + use_info *prev_use () const; > + > + // Return the first use that occurs after P, or null if none. > + use_info *next_use () const; > + > + use_info *use; > + int comparison; > +}; > + > void pp_resource (pretty_printer *, resource_info); > void pp_access (pretty_printer *, const access_info *, > unsigned int flags = PP_ACCESS_DEFAULT); > diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h > index 2e20f5e47d7..27cbc18178a 100644 > --- a/gcc/rtl-ssa/functions.h > +++ b/gcc/rtl-ssa/functions.h > @@ -131,8 +131,23 @@ public: > > // Look for a definition of RESOURCE at INSN. Return the result of the > // search as a def_lookup; see the comments there for more details. > + // > + // NOTE: This is not the function to use if INSN is known to be a real > + // instruction (one with an RTL pattern) and if the caller is only > + // interested in definitions within INSN itself. In those cases > + // it is better to use find_access. > def_lookup find_def (resource_info resource, insn_info *insn); > > + // Search for a use of DEF around non-debug instruction INSN and return the > + // result of the search as a use_lookup. See the comment above the class > + // for more details about the result means. > + // > + // NOTE: This is not the function to use if INSN is known to be a real > + // instruction (one with an RTL pattern) and if the caller is only > + // interested in uses within INSN itself. In those cases it is better > + // to use find_access. > + use_lookup find_use (set_info *def, insn_info *insn); > + > // Return an RAII object that owns all temporary RTL SSA memory > // allocated during a change attempt. The object should remain in > // scope until the change has been aborted or successfully completed. > diff --git a/gcc/rtl-ssa/member-fns.inl b/gcc/rtl-ssa/member-fns.inl > index 346a1208c84..1049f613776 100644 > --- a/gcc/rtl-ssa/member-fns.inl > +++ b/gcc/rtl-ssa/member-fns.inl > @@ -478,6 +478,36 @@ def_lookup::matching_set_or_first_def_of_next_group () > const > return first_def_of_next_group (); > } > > +inline use_info * > +use_lookup::prev_use () const > +{ > + return !use || comparison > 0 ? use : use->prev_use (); > +} > + > +inline use_info * > +use_lookup::next_use () const > +{ > + return !use || comparison < 0 ? use : use->next_nondebug_insn_use (); > +} > + > +inline use_info * > +use_lookup::matching_use () const > +{ > + return comparison == 0 ? use : nullptr; > +} > + > +inline use_info * > +use_lookup::matching_or_prev_use () const > +{ > + return comparison == 0 ? use : prev_use (); > +} > + > +inline use_info * > +use_lookup::matching_or_next_use () const > +{ > + return comparison == 0 ? use : next_use (); > +} > + > inline insn_note::insn_note (insn_note_kind kind) > : m_next_note (nullptr), > m_kind (kind), > -- > 2.43.0 >