public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* [ranger-tech] How to use ranges within any pass with get_range_query()
@ 2021-06-10 15:20 Aldy Hernandez
  2021-06-16 12:34 ` Martin Jambor
  0 siblings, 1 reply; 2+ messages in thread
From: Aldy Hernandez @ 2021-06-10 15:20 UTC (permalink / raw)
  To: GCC Mailing List

As part of the ranger development we have found that there are various 
pieces of the infrastructure that can be used independently, and we’d 
like to document them in the hopes that they are useful to others.  We 
will be contributing short posts documenting parts of the ranger, which 
we hope can become part of a more persistent documentation (wiki? 
Internal docs?).

This first post is an introduction to accessing ranges throughout the 
compiler that will serve as a basis for the upcoming posts.

Please let us know if anything is not clear, or if you'd like us to 
expand on any particular topic...

Aldy & Andrew

The main goal of ranger is to provide a generic infrastructure for 
accessing ranges (global or on-demand) from anywhere in the compiler, 
with one common API.  This API subsumes the global ranges we accessed 
through SSA_NAME_RANGE_INFO, as well as on-demand ones with the ranger 
proper.

The base class for querying ranges in the compiler is range_query and is 
defined in value-query.h.  Instead of duplicating it here, I will list 
the more typical access points:

bool range_of_expr (irange &r, tree expr, gimple *stmt = NULL);

Returns the range of a tree expression as a range in R, with an optional 
gimple statement providing context.  The tree expression EXPR can be 
anything from an SSA, or constant, to a full complex expression such as 
a binary or unary tree.

Upon return R will contain the range of EXPR as it would appear on entry 
to STMT.  If STMT is not specified, then it will be the global range of 
EXPR.  This function always returns true unless the type of EXPR is 
unsupported (we currently support integers and pointers).

bool range_on_edge (irange &r, edge, tree expr);

Like range_of_expr, but instead of returning the range as it appears on 
entry to a statement, this function returns the range as it would appear 
on an edge.

bool range_of_stmt (irange &r, gimple *, tree name = NULL);

Returns the range of a gimple statement in R.  NAME is an optional 
SSA_NAME on the LHS of the statement.  It is only required if there is 
more than one LHS/output. This query will trigger requests for the range 
of each operand on the statement and will use those to calculate the 
resulting range. (ie, range_of_expr() will be called for each operand 
using this statement as the context)

The above is the core API for anything range related.  It can be used 
with any range_query object, which ranger is one, and which even the 
legacy vr_values is one.

Every struct function in the compiler has a range_query object 
associated with it.  By default, it is configured such that it returns 
global ranges.  That is, ranges that were globally assigned by previous 
passes, such as evrp or VRP.  These global ranges are what 
SSA_NAME_RANGE_INFO and SSA_NAME_PTR_INFO used to be, but accessible 
with one common API, and flexible in that they can return global ranges 
for SSA names, constants, and even expressions.

To get the range_query object for a given function, use the following 
with the above API:

range_query *get_range_query (struct function *);

The first step in using ranges in a pass, is to structure all queries 
with the range API, on an object returned by get_range_query().  That’s 
it.  Your pass will be able to access ranges, albeit initially with 
ranges that apply to the entire function (global ranges).

If your pass can benefit from context-aware ranges (on statements or 
edges) or on-demand ranges (more up to date than global ones), you must 
enable a ranger for your pass.  This can be done by calling the 
following on entry to the pass:

gimple_ranger *enable_ranger (struct function *fun);

And a corresponding call on exit from the pass:

void disable_ranger (struct function *fun);

No other changes are needed in your pass if you’re already using the 
range_query API.  You may continue using get_range_query(fun) since it 
will return the current active range_query object (the enabled ranger in 
this case).

You may notice that enable_ranger() returns a gimple_ranger object 
(which is a derived class of range_query).  This can be used for more 
advanced operations on ranges (see gimple-range.h), but more 
importantly, it can be used to export any ranges found throughout the 
execution of your pass to the global space.  If during range queries 
done in your pass, the ranger discovers any globally applicable ranges, 
they can be exported for use in subsequent passes by calling the 
export_global_ranges() method from a gimple_ranger object:

your_pass()
{
   gimple_ranger *ranger = enable-ranger (cfun);

   do_stuff();
   get_range_query ()->range_of_expr (.....);
   get_range_query ()->range_on_edge (....);
   do_stuff();

   // Export any known ranges to the global space.
   ranger->export_global_ranges ();

   disable_ranger (cfun);
}

This means that on exit from the pass, a get_range_query()->range* can 
be used to access globally applicable ranges that were found during 
your_pass().

Note that due to the caching mechanism in the ranger, on-demand ranges 
(available when enable_ranger() has been called in a pass) cannot 
survive changes in the IL.  Specifically if your pass changes the flow 
control of the IL, you may have to delay altering the IL until after 
disable_ranger() has been called.

Finally, you may notice that get_range_query() requires a struct 
function, which may not be available in certain passes (i.e. RTL based 
passes).  If this is the case, you may explicitly request the global 
range object, accessible with:

range_query *get_global_range_query ();

This function is only to be used when there is no struct function 
available, or when the overhead of an on-demand lookup is not desired. 
For example, when requesting the range of a tree expression in which you 
only care about global ranges when resolving any SSAs in said expression.


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [ranger-tech] How to use ranges within any pass with get_range_query()
  2021-06-10 15:20 [ranger-tech] How to use ranges within any pass with get_range_query() Aldy Hernandez
@ 2021-06-16 12:34 ` Martin Jambor
  0 siblings, 0 replies; 2+ messages in thread
From: Martin Jambor @ 2021-06-16 12:34 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: GCC Mailing List

Hi,

On Thu, Jun 10 2021, Aldy Hernandez via Gcc wrote:
> As part of the ranger development we have found that there are various 
> pieces of the infrastructure that can be used independently, and we’d 
> like to document them in the hopes that they are useful to others.  We 
> will be contributing short posts documenting parts of the ranger, which 
> we hope can become part of a more persistent documentation (wiki? 
> Internal docs?).

Thank you very much for writing this up.  And yes, please add something
like this to gcc/doc/gccint.texi - perhaps after it is converted to
Sphinx, assuming that writing in that format is easier.

Thanks again,

Martin

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-06-16 12:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-10 15:20 [ranger-tech] How to use ranges within any pass with get_range_query() Aldy Hernandez
2021-06-16 12:34 ` Martin Jambor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).