[PATCH][RFC] C++-style iterators for FOR_EACH_IMM_USE_STMT

Richard Biener rguenther@suse.de
Mon Nov 4 08:37:00 GMT 2019


On Sun, 3 Nov 2019, Oleg Endo wrote:

> On Wed, 2019-10-30 at 10:27 +0100, Richard Biener wrote:
> > 
> > Hmm, not sure - I'd like to write
> > 
> >  for (gimple *use_stmt : imm_stmt_uses (SSAVAR))
> >    for (use_operand_p use_p : <need to refer to the iterator object
> > from 
> > above>)
> >      ...
> > 
> > I don't see how that's possible.  It would need to be "awkward" like
> > 
> >  for (auto it : imm_stmt_uses (SSAVAR))
> >    {
> >      gimple *use_stmt = *it;
> >      for (use_operand_p use_p : it)
> >        ...
> >    }
> > 
> > so the first loops iteration object are the actual iterator and you'd
> > have to do extra indirection to get at the actual stmt you iterated
> > to.
> > 
> > So I'd extend C++ (hah) to allow
> > 
> >   for (gimple *use_stmt : imm_stmt_uses (SSAVAR))
> >     for (use_operand_p use_p : auto)
> >       ...
> > 
> > where 'auto' magically selects the next iterator object in scope
> > [that matches].
> > 
> > ;)
> 
> Have you applied for a patent yet? :D
> 
> How about this one?
> 
> for (gimple* use_stmt : imm_stmt_uses (SSAVAR))
>   for (use_operand_p use_p : imm_uses_on_stmt (*use_stmt))
> 
> ... where helper function "imm_uses_on_stmt" returns a range object
> that offers a begin and end function and its own iterator type.

The issue is that 'use_stmt' isn't enough to compute it.  Internally
we just use the same iterator object as for the outer loop but
with range-based for the iterator object isn't accessible.  So we'd
need to wrap 'use_stmt' and the iterator object somehow.  Closest
would then be

  for (auto use_stmt : imm_stmt_uses (SSAVAR))
    for (use_operand_p use_p : imm_uses_on_stmt (use_stmt))
      ...

where use_stmt auto-converts to gimple * and auto hides the
ugliness.

Not very satisfying.

So what we are really doing is iterate over a sorted vector
of use_operand_p sorted after USE_STMT (so uses on the same
stmt come in succession).  The inner loop iterates over all
uses on a single USE_STMT and conveniently lets us skip to
the next USE_STMT plus do some common update on a USE_STMT
once we saw all uses on it.  Thus..

  for (auto_vec<use_operand_p> uses : imm_stmt_uses (SSAVAR))
    for (use_operand_p : uses)
      ...

that is, using a special iterator type for the outer loop iteration
var might be conceptually OK (it's a sub-range of all immediate uses).

So supposedly it's OK to use 'auto' to hide that subrange 'class'

> Another concept that could be interesting are filter iterators.
> 
> We used a simplistic re-implementation (c++03) to avoid dragging in
> boost when working on AMS
> https://github.com/erikvarga/gcc/blob/master/gcc/filter_iterator.h
> 
> Example uses are
> https://github.com/erikvarga/gcc/blob/master/gcc/ams.h#L845
> https://github.com/erikvarga/gcc/blob/master/gcc/ams.cc#L3715
> 
> 
> I think there are also some places in RTL where filter iterators could
> be used, e.g. "iterate over all MEMs in an RTL" could be made to look
> something like that:
> 
>   for (auto&& i : filter_rtl (my_rtl_obj, MEM_P))
>    ...
> 
> 
> Anyway, maybe it can plant some ideas.

:)

Thanks,
Richard.



More information about the Gcc-patches mailing list