public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Xinliang David Li <davidxl@google.com>
To: Lawrence Crowl <crowl@googlers.com>
Cc: "gcc@gcc.gnu.org" <gcc@gcc.gnu.org>
Subject: Re: Simplifying Gimple Generation
Date: Thu, 15 Nov 2012 07:32:00 -0000	[thread overview]
Message-ID: <CAAkRFZLZPXo+bJ_OX3fJOe=489ru85dCETdQJ+TLEi7pHTZ2yQ@mail.gmail.com> (raw)
In-Reply-To: <CAGqM8fZbnET=4GGrBt-sXJ-jweTxYYLAGdaYuzK2HfiwCi7K=A@mail.gmail.com>

On Wed, Nov 14, 2012 at 5:13 PM, Lawrence Crowl <crowl@googlers.com> wrote:
> Diego and I seek your comments on the following (loose) proposal.
>
>
> Generating gimple and tree expressions require lots of detail,
> which is hard to remember and easy to get wrong.  There is some
> amount of boilerplate code that can, in most cases, be reduced and
> managed automatically.
>
> We will add a set of helper classes to be used as local variables
> to manage the details of handling the existing types.  That is,
> a layer over 'gimple_build_*'. We intend to provide helpers for
> those facilities that are both commonly used and have room for
> significant simplification.
>
>
> Generating an Expression
>
> Suppose one wants to generate the expression (shadow != 0) &
> (((base_addr & 7) + offset) >= shadow), where offset is a value and
> the other identifiers are variables.  The current code to generate
> this expression is as follows.
>
> /* t = shadow != 0 */
> g = gimple_build_assign_with_ops (NE_EXPR,
>             make_ssa_name (boolean_type_node, NULL),
>             shadow,
>             build_int_cst (shadow_type, 0));
> gimple_set_location (g, location);
> gsi_insert_after (&gsi, g, GSI_NEW_STMT);
> t = gimple_assign_lhs (g);
>
> /* a = base_addr & 7 */
> g = gimple_build_assign_with_ops (BIT_AND_EXPR,
>             make_ssa_name (uintptr_type, NULL),
>             base_addr,
>             build_int_cst (uintptr_type, 7));
> gimple_set_location (g, location);
> gsi_insert_after (&gsi, g, GSI_NEW_STMT);
>
> /* b = (shadow_type)a */
> g = gimple_build_assign_with_ops (NOP_EXPR,
>             make_ssa_name (shadow_type, NULL),
>             gimple_assign_lhs (g),
>             NULL_TREE);
> gimple_set_location (g, location);
> gsi_insert_after (&gsi, g, GSI_NEW_STMT);
>
> /* c = b + offset */
> g = gimple_build_assign_with_ops (PLUS_EXPR,
>             make_ssa_name (shadow_type, NULL),
>             gimple_assign_lhs (g),
>             build_int_cst (shadow_type, offset));
> gimple_set_location (g, location);
> gsi_insert_after (&gsi, g, GSI_NEW_STMT);
>
> /* d = c >= shadow */
> g = gimple_build_assign_with_ops (GE_EXPR,
>             make_ssa_name (boolean_type_node, NULL),
>             gimple_assign_lhs (g),
>             shadow);
> gimple_set_location (g, location);
> gsi_insert_after (&gsi, g, GSI_NEW_STMT);
>
> /* r = t & d */
> g = gimple_build_assign_with_ops (BIT_AND_EXPR,
>             make_ssa_name (boolean_type_node, NULL),
>             t,
>             gimple_assign_lhs (g));
> gimple_set_location (g, location);
> gsi_insert_after (&gsi, g, GSI_NEW_STMT);
> r = gimple_assign_lhs (g);
>
> We propose a simplified form using new build helper classes ssa_seq
> and ssa_stmt that would allow the above code to be written as
> follows.
>
> ssa_seq q;

Can it be more abstract, such as stmt_builder?


> ssa_stmt t = q.stmt (NE_EXPR, shadow, 0);
> ssa_stmt a = q.stmt (BIT_AND_EXPR, base_addr, 7);
> ssa_stmt b = q.stmt (shadow_type, a);
> ssa_stmt c = q.stmt (PLUS_EXPR, b, offset);
> ssa_stmt d = q.stmt (GE_EXPR, c, shadow);
> ssa_stmt e = q.stmt (BIT_AND_EXPR, t, d);


seq_seq::stmt(...) sounds like a getter interface, not a creator.

x = q.new_assignment (...);
x = q.new_call (..);
x.add_arg(..);
x = q.new_icall (..);

l1 = q.new_label ("xx");
l2 = q.new_label ("xxx");
join_l = q.new_label ("...");

x = new_if_then_else (cond, l1, l2, join_l);
q.insert_label (l1);
q.new_assignment (...);
q.insert_label(l2);
...
q.insert_label(join_l);
q.close_if_then_else(x);


> q.set_location (location);
> r = e.lhs ();
>
> There are a few important things to note about this example.
>
> .. We have a new class (ssa_seq) that knows how to sequence
> statements automatically and can build expressions out of types.
>
> .. Every statement created produces an SSA name.  Referencing an
> ssa_stmt instance in a an argument to ssa_seq::stmt retrieves the
> SSA name generated by that statement.

>
> .. The statement result type is that of the arguments.
>
> .. The type of integral constant arguments is that of the other
> argument.  (Which implies that only one argument can be constant.)
>
> .. The 'stmt' method handles linking the statement into the sequence.
>
> .. The 'set_location' method iterates over all statements.
>
> There will be another class of builders for generating GIMPLE
> in normal form (gimple_stmt).  We expect that this will mostly
> affect all transformations that need to generate new expressions
> and statements, like instrumentation passes.

What are the uses of the raw forms?

>
> We also expect to reduce calls to tree expression builders by
> allowing the use of numeric and string constants to be converted
> to the appropriate tree _CST node.  This will only work when the
> type of the constant can be deduced from the other argument in some
> expressions, of course.
>
>
> Generating a Type
>
> Consider the generation of the following type.
>
> struct __asan_global {
>   const_ptr_type_node __beg;
>   inttype __size;
>   inttype __size_with_redzone;
>   const_ptr_type_node __name;
>   inttype __has_dynamic_init;
> };
>
> The current code to generate it is as follows.
>
> tree inttype = build_nonstandard_integer_type (POINTER_SIZE, 1);
> tree ret = make_node (RECORD_TYPE);
> TYPE_NAME (ret) = get_identifier ("__asan_global");
> tree beg = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
>                        get_identifier ("__beg"), const_ptr_type_node);
> DECL_CONTEXT (beg) = ret;
> TYPE_FIELDS (ret) = beg;
> tree size = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
>                         get_identifier ("__size"), inttype);
> DECL_CONTEXT (size) = ret;
> DECL_CHAIN (beg) = size;
> tree red = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
>                        get_identifier ("__size_with_redzone"), inttype);
> DECL_CONTEXT (red) = ret;
> DECL_CHAIN (size) = red;
> tree name = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
>                         get_identifier ("__name"), const_ptr_type_node);
> DECL_CONTEXT (name) = ret;
> DECL_CHAIN (red) = name;
> tree init = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
>                         get_identifier ("__has_dynamic_init"), inttype);
> DECL_CONTEXT (init) = ret;
> DECL_CHAIN (name) = init;
> layout_type (ret);
>
> We propose a form as follows.
>
> tree inttype = build_nonstandard_integer_type (POINTER_SIZE, 1);
> record_builder rec ("__asan_global");
> rec.field ("__beg", const_ptr_type_node);
> rec.field ("__size", inttype);
> rec.field ("__size_with_redzone", inttype);
> rec.field ("__name", const_ptr_type_node);
> rec.field ("__has_dynamic_init", inttype);
> rec.finish ();
> tree ret = rec.as_tree ();

Again, something like new_field or add_field is more intuitive.

>
> There are a few important things to note about this example.
>
> .. The 'field' method will add context and chain links.
>
> .. The 'field' method is overloaded on both strings and identifiers.
>
> .. The 'finish' method lays out the struct.
>
>
> Proposal
>
> Create a set of IL builder classes that provide a simplified IL
> building interface.  Essentially, these builder classes will abstract
> most of the bookkeeping code required by the current interfaces.
>
> These classes will not replace the existing interfaces.  We do not
> expect that all the IL generation done in current transformations
> will be able to use the simplified interfaces.  The goal is to
> simplify most of them, however.


Looks like a good direction to go.

thanks,

David


>
> --
> Lawrence Crowl

  parent reply	other threads:[~2012-11-15  7:32 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-15  1:13 Lawrence Crowl
2012-11-15  6:06 ` Basile Starynkevitch
2012-11-15 19:34   ` Lawrence Crowl
2012-11-16 13:15   ` Diego Novillo
2012-11-15  7:32 ` Xinliang David Li [this message]
2012-11-16 13:13   ` Diego Novillo
2012-11-17  1:05     ` Xinliang David Li
2012-11-15 14:48 ` Michael Matz
2012-11-15 16:52   ` Gabriel Dos Reis
2012-11-15 17:01     ` Michael Matz
2012-11-15 17:07       ` Xinliang David Li
2012-11-15 19:59   ` Lawrence Crowl
2012-11-16 12:44     ` Michael Matz
2012-11-16 13:59   ` Diego Novillo
2012-11-16 14:30     ` Michael Matz
2012-11-16 17:31       ` Andrew Pinski
2012-11-20 16:49 ` Andrew MacLeod
2012-11-25  1:35 ` Diego Novillo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAAkRFZLZPXo+bJ_OX3fJOe=489ru85dCETdQJ+TLEi7pHTZ2yQ@mail.gmail.com' \
    --to=davidxl@google.com \
    --cc=crowl@googlers.com \
    --cc=gcc@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).