diff mbox

Fix checking of gimple types

Message ID 1385393718.11568.266.camel@surprise
State New
Headers show

Commit Message

David Malcolm Nov. 25, 2013, 3:35 p.m. UTC
On Thu, 2013-11-21 at 18:03 -0500, Andrew MacLeod wrote:
> On 11/21/2013 05:42 PM, Jakub Jelinek wrote:
> > On Thu, Nov 21, 2013 at 03:24:55PM -0700, Jeff Law wrote:
> >> On 11/21/13 15:19, Jakub Jelinek wrote:
> >>> On Mon, Nov 18, 2013 at 03:25:52PM -0500, David Malcolm wrote:
> >>>>> So is there some reason the GIMPLE_CHECK was left in here rather than
> >>>>> doing the downcasting?  This happens in other places.
> >>> Note that the changes removed tons of checks that IMHO were desirable.
> >>> The as_a that replaced those checks e.g. allows 3 different gimple codes,
> >>> while previously only one was allowed, this is both more expensive for
> >>> --enable-checking=yes, and allows one to use inline wrappers e.g.
> >>> gimple_omp_parallel_something on GIMPLE_OMP_TASK etc.
> >> Can you give a couple examples, please?
> > I mean e.g.
> > gimple_omp_parallel_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > gimple_omp_taskreg_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > gimple_omp_target_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > gimple_omp_teams_{,set_}clauses{,_ptr}
> > gimple_omp_return_{,set_}lhs{,_ptr}
> > gimple_omp_atomic_store_{,set_}val{,_ptr}
> > gimple_resx_{,set_}region
> > gimple_eh_dispatch_{,set_}region
> >
> > 	Jakub
> Why does  is_a_helper <gimple_statement_omp_parallel>::test allow 
> anything other than a GIMPLE_OMP_PARALLEL..?  That seems wrong to me. 
> should just be the one check.
> 
> gimple_omp_taskreg and other routines "sharing" that helper should have 
> their own helper and only check the one code.. thats is whole point to 
> remain at least codegen neutral in these cases and provide correct 
> checking.   The fact that they may happen to share the same underlying 
> structure is irrelevant.
> 
> I also think this is wrong.

Mea culpa.  Unfortunately I made a conceptual error during the
conversion (the worst kind of error).  I misunderstood the relationships
between the various OMP statements: there (mostly) aren't any, but the
sharing of structures for layout made me think there were.

Attached is a patch, successfully bootstrapped&regtested on
x86_64-unknown-linux-gnu, which I believe reinstates the checked-build
behaviors from before r205034 (and that the unchecked-build behaviors
were not affected by that commit and likewise are not by this patch).

As I understand it, there are almost no "is-a" relationships between the
various omp statement types, some of them just happen to share layouts.
The exception is that the various gimple_omp_taskreg_* accessors accept
either codes GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK and so an
"omp_taskreg" is a concept, of which OMP_PARALLEL and OMP_TASK have an
is-a relationship.

Based on this, I've reworked the is_a_helper functions, eliminating
almost all of the ones that accepted multiple codes.  The only ones that
remain accepting multiple codes are those for:

  * gimple_statement_with_ops, which uses gimple_has_ops (gs), and for
  * gimple_statement_with_memory_ops, which uses gimple_has_mem_ops
(gs), plus
  * a new class gimple_statement_omp_taskreg, which expresses the
"either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK" condition, and becomes a
parent struct for those.

I introduced some new structs to express the pre-existing layouts for
GSS codes, and to distinguish them from structs that imply a specific
GIMPLE_ code.
For example,
  gimple_statement_omp_atomic_store
now requires that the code be GIMPLE_OMP_ATOMIC_STORE, but it was also
the name of a layout, GSS_OMP_ATOMIC_STORE.  So I renamed these purely
layout classes, so that there is now a
  gimple_statement_omp_atomic_store_layout
class for the corresponding GSS value, which I renamed to
  GSS_OMP_ATOMIC_STORE_LAYOUT
to make clear that this is just a layout: that although
GIMPLE_OMP_RETURN happens to share the data layout of
GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related - they now both
inherit from the "_layout" class.

I'm not a fan of these "_layout" names, but I'm not sure what better to
call them. Perhaps:
   GSS_OMP_PARALLEL_LAYOUT     -> GSS_OMP_WITH_CLAUSES_CHILD_FN_DATA_ARG
   GSS_OMP_SINGLE_LAYOUT       -> GSS_OMP_WITH_CLAUSES
   GSS_OMP_ATOMIC_STORE_LAYOUT -> GSS_OMP_WITHOUT_SEQ_WITH_VAL
with analogous names for the corresponding structs.

I added GTY tags for every class in the hierarchy, not just those that
introduce a new layout, since gengtype only recognizes inheritance when
supplied a "tag" option.  This leads to the GSS values appearing
multiple times within the class hierarchy, which required a patch to
gengtype, to prevent duplicate case labels in the generated switch
statement.

I believe that this structure correctly reinstates the exact behavior
from before the inheritance patch for the checked build, and that either
way, the behavior in the unchecked build is the same.

Another approach to this would be to entirely eliminate these shared
layout types, going purely with the conceptual is-a relationships
between the types, say, by replacing the gengtype switch on GSS_ value
with a switch on GIMPLE_ code.  Given that this might affect the speed
of GC (bigger switch statements), I went with the relatively more
conservative change.

Successfully bootstrapped&regtested on x86_64-unknown-linux-gnu.

OK for trunk?

Sorry again for breaking this.

Here's an ASCII art inheritance diagram, showing the relationships
between structs, GSS_ values (layouts) and GIMPLE_ values (codes) - as I
see them.  If I'm still misunderstanding something, sorry, please let me
know.  Should this diagram live in gimple.h?
+- gimple_statement_base
     |    layout: GSS_BASE.  4 codes use this layout.
     |
     + gimple_statement_with_ops_base
     |   |    (no GSS layout)
     |   |
     |   + gimple_statement_with_ops
     |   |        layout: GSS_WITH_OPS.   5 codes use this layout.
     |   |
     |   + gimple_statement_with_memory_ops_base
     |       |    layout: GSS_WITH_MEM_OPS_BASE
     |       |
     |       + gimple_statement_with_memory_ops
     |       |        layout: GSS_WITH_MEM_OPS.
     |       |        Used by codes GIMPLE_ASSIGN and GIMPLE_RETURN.
     |       |
     |       + gimple_statement_call
     |       |        layout: GSS_CALL, code: GIMPLE_CALL
     |       |
     |       + gimple_statement_asm
     |       |        layout: GSS_ASM, code: GIMPLE_ASM
     |       |
     |       + gimple_statement_transaction
     |                layout: GSS_TRANSACTION, code: GIMPLE_TRANSACTION
     |
     + gimple_statement_omp
     |   |    layout: GSS_OMP
     |   |
     |   + gimple_statement_omp_critical
     |   |        layout: GSS_OMP_CRITICAL, code: GIMPLE_OMP_CRITICAL
     |   |
     |   + gimple_statement_omp_for
     |   |        layout: GSS_OMP_FOR, code: GIMPLE_OMP_FOR
     |   |
     |   + gimple_statement_omp_parallel_layout
     |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
     |   |   |
     |   |   + gimple_statement_omp_taskreg
     |   |   |   |
     |   |   |   + gimple_statement_omp_parallel
     |   |   |   |        code: GIMPLE_OMP_PARALLEL
     |   |   |   |
     |   |   |   + gimple_statement_omp_task
     |   |   |            code: GIMPLE_OMP_TASK
     |   |   |
     |   |   + gimple_statement_omp_target
     |   |            code: GIMPLE_OMP_TARGET
     |   |
     |   + gimple_statement_omp_sections
     |   |        layout: GSS_OMP_SECTIONS, code: GIMPLE_OMP_SECTIONS
     |   |
     |   + gimple_statement_omp_single_layout
     |       |    layout: GSS_OMP_SINGLE_LAYOUT
     |       |
     |       + gimple_statement_omp_single
     |       |        code: GIMPLE_OMP_SINGLE
     |       |
     |       + gimple_statement_omp_teams
     |                code: GIMPLE_OMP_TEAMS
     |
     + gimple_statement_bind
     |        layout: GSS_BIND, code: GIMPLE_BIND
     |
     + gimple_statement_catch
     |        layout: GSS_CATCH, code: GIMPLE_CATCH
     |
     + gimple_statement_eh_filter
     |        layout: GSS_EH_FILTER, code: GIMPLE_EH_FILTER
     |
     + gimple_statement_eh_else
     |        layout: GSS_EH_ELSE, code: GIMPLE_EH_ELSE
     |
     + gimple_statement_eh_mnt
     |        layout: GSS_EH_MNT, code: GIMPLE_EH_MUST_NOT_THROW
     |
     + gimple_statement_phi
     |        layout: GSS_PHI, code: GIMPLE_PHI
     |
     + gimple_statement_eh_ctrl
     |   |    layout: GSS_EH_CTRL
     |   |
     |   + gimple_statement_resx
     |   |        code: GIMPLE_RESX
     |   |
     |   + gimple_statement_eh_dispatch
     |            code: GIMPLE_EH_DISPATCH
     |
     + gimple_statement_try
     |        layout: GSS_TRY, code: GIMPLE_TRY
     |
     + gimple_statement_wce
     |        layout: GSS_WCE, code: GIMPLE_WITH_CLEANUP_EXPR
     |
     + gimple_statement_omp_continue
     |        layout: GSS_OMP_CONTINUE, code: GIMPLE_OMP_CONTINUE
     |
     + gimple_statement_omp_atomic_load
     |        layout: GSS_OMP_ATOMIC_LOAD, code: GIMPLE_OMP_ATOMIC_LOAD
     |
     + gimple_statement_omp_atomic_store_layout
         |    layout: GSS_OMP_ATOMIC_STORE_LAYOUT,
         |    code: GIMPLE_OMP_ATOMIC_STORE
         |
         + gimple_statement_omp_atomic_store
         |        code: GIMPLE_OMP_ATOMIC_STORE
         |
         + gimple_statement_omp_return
                  code: GIMPLE_OMP_RETURN

Comments

Michael Matz Nov. 25, 2013, 5:09 p.m. UTC | #1
Hi,

On Mon, 25 Nov 2013, David Malcolm wrote:

> I'm not a fan of these "_layout" names, but I'm not sure what better to
> call them. Perhaps:
>    GSS_OMP_PARALLEL_LAYOUT     -> GSS_OMP_WITH_CLAUSES_CHILD_FN_DATA_ARG
>    GSS_OMP_SINGLE_LAYOUT       -> GSS_OMP_WITH_CLAUSES
>    GSS_OMP_ATOMIC_STORE_LAYOUT -> GSS_OMP_WITHOUT_SEQ_WITH_VAL
> with analogous names for the corresponding structs.

The preexisting name for these structs has a _base suffix 
(gimple_statement_with_ops_base and gimple_statement_with_memory_ops_base
are indeed in the same situation in that no gimple codes 
exist that directly make use of that gss, unlike e.g. GSS_BASE which 
does have some direct users).

(I do like more selfdescribing names, though, so perhaps the existing 
_base variants could also use some renaming, but it should either be no 
_base names at all, or only _base names (i.e. no additional _layout for 
some other names)).

> Another approach to this would be to entirely eliminate these shared
> layout types, going purely with the conceptual is-a relationships
> between the types, say, by replacing the gengtype switch on GSS_ value
> with a switch on GIMPLE_ code.  Given that this might affect the speed
> of GC (bigger switch statements), I went with the relatively more
> conservative change.

I think it makes sense to keep storage layout and gimple codes separate, 
but still have them both structured.  The former allows easier changes 
when looking at data layout problems (like memory optimizations, or GC), 
the latter easier transformations related to higher level logic of the 
data structures.


Ciao,
Michael.
Jeff Law Nov. 25, 2013, 7:34 p.m. UTC | #2
On 11/25/13 08:35, David Malcolm wrote:
>
> I'm not a fan of these "_layout" names, but I'm not sure what better to
> call them. Perhaps:
>     GSS_OMP_PARALLEL_LAYOUT     -> GSS_OMP_WITH_CLAUSES_CHILD_FN_DATA_ARG
>     GSS_OMP_SINGLE_LAYOUT       -> GSS_OMP_WITH_CLAUSES
>     GSS_OMP_ATOMIC_STORE_LAYOUT -> GSS_OMP_WITHOUT_SEQ_WITH_VAL
> with analogous names for the corresponding structs.
I think the _layout names are fine for now.  We might want change them 
to be more descriptive at a later date.

>
> OK for trunk?
Yes.

>
> Sorry again for breaking this.
It happens.  I suspect you'll look beyond the sharing of data structures 
to build a class hierarchy next time :-)

Thanks for quickly addressing this.

Jeff
David Malcolm Nov. 27, 2013, 2:27 a.m. UTC | #3
On Mon, 2013-11-25 at 12:34 -0700, Jeff Law wrote:
> On 11/25/13 08:35, David Malcolm wrote:
> >
> > I'm not a fan of these "_layout" names, but I'm not sure what better to
> > call them. Perhaps:
> >     GSS_OMP_PARALLEL_LAYOUT     -> GSS_OMP_WITH_CLAUSES_CHILD_FN_DATA_ARG
> >     GSS_OMP_SINGLE_LAYOUT       -> GSS_OMP_WITH_CLAUSES
> >     GSS_OMP_ATOMIC_STORE_LAYOUT -> GSS_OMP_WITHOUT_SEQ_WITH_VAL
> > with analogous names for the corresponding structs.
> I think the _layout names are fine for now.  We might want change them 
> to be more descriptive at a later date.
> 
> >
> > OK for trunk?
> Yes.

Thanks; committed to trunk as r205428.
Thomas Schwinge July 23, 2014, 1 p.m. UTC | #4
Hi!

In context of adding support for OpenACC, next to the existing
GIMPLE_OMP_TARGET (quoting from gcc/gimple.def and gcc/gimple.h):

    DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)

    /* GIMPLE_OMP_TARGET */
    struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
      gimple_statement_omp_target : public gimple_statement_omp_parallel_layout
    {
        /* No extra fields; adds invariant:
             stmt->code == GIMPLE_OMP_TARGET.  */
    };

..., we're adding additional GIMPLE codes:

    DEFGSCODE(GIMPLE_OACC_KERNELS, "gimple_oacc_kernels", GSS_OMP_PARALLEL_LAYOUT)

    /* GIMPLE_OACC_KERNELS */
    struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
      gimple_statement_oacc_kernels : public gimple_statement_omp_parallel_layout
    {
        /* No extra fields; adds invariant:
             stmt->code == GIMPLE_OACC_KERNELS.  */
    };

    DEFGSCODE(GIMPLE_OACC_PARALLEL, "gimple_oacc_parallel", GSS_OMP_PARALLEL_LAYOUT)

    /* GIMPLE_OACC_PARALLEL */
    struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
      gimple_statement_oacc_parallel : public gimple_statement_omp_parallel_layout
    {
        /* No extra fields; adds invariant:
             stmt->code == GIMPLE_OACC_PARALLEL.  */
    };

As you can see, all these codes share the same layout,
GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout.

Given this, I'd like to better understand the following:

On Mon, 25 Nov 2013 10:35:18 -0500, David Malcolm <dmalcolm@redhat.com> wrote:
> On Thu, 2013-11-21 at 18:03 -0500, Andrew MacLeod wrote:
> > On 11/21/2013 05:42 PM, Jakub Jelinek wrote:
> > > On Thu, Nov 21, 2013 at 03:24:55PM -0700, Jeff Law wrote:
> > >> On 11/21/13 15:19, Jakub Jelinek wrote:
> > >>> On Mon, Nov 18, 2013 at 03:25:52PM -0500, David Malcolm wrote:
> > >>>>> So is there some reason the GIMPLE_CHECK was left in here rather than
> > >>>>> doing the downcasting?  This happens in other places.
> > >>> Note that the changes removed tons of checks that IMHO were desirable.
> > >>> The as_a that replaced those checks e.g. allows 3 different gimple codes,
> > >>> while previously only one was allowed, this is both more expensive for
> > >>> --enable-checking=yes, and allows one to use inline wrappers e.g.
> > >>> gimple_omp_parallel_something on GIMPLE_OMP_TASK etc.
> > >> Can you give a couple examples, please?
> > > I mean e.g.
> > > gimple_omp_parallel_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > gimple_omp_taskreg_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > gimple_omp_target_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > gimple_omp_teams_{,set_}clauses{,_ptr}
> > > gimple_omp_return_{,set_}lhs{,_ptr}
> > > gimple_omp_atomic_store_{,set_}val{,_ptr}
> > > gimple_resx_{,set_}region
> > > gimple_eh_dispatch_{,set_}region

We (have to) add the whole fleet of
gimple_oacc_{kernels,parallel}_{clauses,...} accessors as well as new
is_a_helper for {,const} gimple_statement_oacc_{kernels,parallel}.

> > Why does  is_a_helper <gimple_statement_omp_parallel>::test allow 
> > anything other than a GIMPLE_OMP_PARALLEL..?  That seems wrong to me. 
> > should just be the one check.
> > 
> > gimple_omp_taskreg and other routines "sharing" that helper should have 
> > their own helper and only check the one code.. thats is whole point to 
> > remain at least codegen neutral in these cases and provide correct 
> > checking.   The fact that they may happen to share the same underlying 
> > structure is irrelevant.
> > 
> > I also think this is wrong.
> 
> Mea culpa.  Unfortunately I made a conceptual error during the
> conversion (the worst kind of error).  I misunderstood the relationships
> between the various OMP statements: there (mostly) aren't any, but the
> sharing of structures for layout made me think there were.
> 
> Attached is a patch, successfully bootstrapped&regtested on
> x86_64-unknown-linux-gnu, which I believe reinstates the checked-build
> behaviors from before r205034 (and that the unchecked-build behaviors
> were not affected by that commit and likewise are not by this patch).
> 
> As I understand it, there are almost no "is-a" relationships between the
> various omp statement types, some of them just happen to share layouts.
> The exception is that the various gimple_omp_taskreg_* accessors accept
> either codes GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK and so an
> "omp_taskreg" is a concept, of which OMP_PARALLEL and OMP_TASK have an
> is-a relationship.

Admittedly, there is no is-a relationship between these, but yet,
GIMPLE_OMP_TARGET as well as the new GIMPLE_OACC_KERNELS and
GIMPLE_OACC_PARALLEL can share a lot of code, but, for example, where
previously gimple_omp_target_set_child_fn or gimple_omp_target_clauses
have been used, I now find myself writing code such as:

      void (*gimple_omp_set_child_fn) (gimple, tree);
      tree (*gimple_omp_clauses) (const_gimple);
      switch (gimple_code (stmt))
        {
        case GIMPLE_OACC_KERNELS:
          gimple_omp_set_child_fn = gimple_oacc_kernels_set_child_fn;
          gimple_omp_clauses = gimple_oacc_kernels_clauses;
          break;
        case GIMPLE_OACC_PARALLEL:
          gimple_omp_set_child_fn = gimple_oacc_parallel_set_child_fn;
          gimple_omp_clauses = gimple_oacc_parallel_clauses;
          break;
        case GIMPLE_OMP_TARGET:
          gimple_omp_set_child_fn = gimple_omp_target_set_child_fn;
          gimple_omp_clauses = gimple_omp_target_clauses;
          break;
        default:
          gcc_unreachable ();
        }

..., only that I can then in the following use a unified interface for
setting the child function or getting access to the clauses.

What you can see here is that I first look at the GIMPLE code, and use
that to determine the appropritate accessor functions.  I have to do that
because these specific accessor functions then again would like to check
the respective GIMPLE code -- which I have just checked in the code
quoted above.  Instead, I'd rather like layout-specific accessor
functions, such as gimple_omp_parallel_layout_set_child_fn or
gimple_omp_parallel_layout_clauses.

Is this a reasonable wish, or am I misunderstanding what all this
"boilerplate" code for GIMPLE code checking is meant to achieve?  (It's
entirely possible that I'm misunderstanding something...)  ;-)

For example, might this suggest that our new GIMPLE code should in fact
be proper sub-codes of GIMPLE_OMP_TARGET?  Hmm...

And regardless of this, from someone who is still learning his share of
GCC internals, many, many thanks to you, Andrew and David (as well as
everyone else who's contributing, of course), for all the refactoring
work you're doing!  This does make the GCC code more accessible.  :-)

(Follows full quote for reference.)

> Based on this, I've reworked the is_a_helper functions, eliminating
> almost all of the ones that accepted multiple codes.  The only ones that
> remain accepting multiple codes are those for:
> 
>   * gimple_statement_with_ops, which uses gimple_has_ops (gs), and for
>   * gimple_statement_with_memory_ops, which uses gimple_has_mem_ops
> (gs), plus
>   * a new class gimple_statement_omp_taskreg, which expresses the
> "either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK" condition, and becomes a
> parent struct for those.
> 
> I introduced some new structs to express the pre-existing layouts for
> GSS codes, and to distinguish them from structs that imply a specific
> GIMPLE_ code.
> For example,
>   gimple_statement_omp_atomic_store
> now requires that the code be GIMPLE_OMP_ATOMIC_STORE, but it was also
> the name of a layout, GSS_OMP_ATOMIC_STORE.  So I renamed these purely
> layout classes, so that there is now a
>   gimple_statement_omp_atomic_store_layout
> class for the corresponding GSS value, which I renamed to
>   GSS_OMP_ATOMIC_STORE_LAYOUT
> to make clear that this is just a layout: that although
> GIMPLE_OMP_RETURN happens to share the data layout of
> GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related - they now both
> inherit from the "_layout" class.
> 
> I'm not a fan of these "_layout" names, but I'm not sure what better to
> call them. Perhaps:
>    GSS_OMP_PARALLEL_LAYOUT     -> GSS_OMP_WITH_CLAUSES_CHILD_FN_DATA_ARG
>    GSS_OMP_SINGLE_LAYOUT       -> GSS_OMP_WITH_CLAUSES
>    GSS_OMP_ATOMIC_STORE_LAYOUT -> GSS_OMP_WITHOUT_SEQ_WITH_VAL
> with analogous names for the corresponding structs.
> 
> I added GTY tags for every class in the hierarchy, not just those that
> introduce a new layout, since gengtype only recognizes inheritance when
> supplied a "tag" option.  This leads to the GSS values appearing
> multiple times within the class hierarchy, which required a patch to
> gengtype, to prevent duplicate case labels in the generated switch
> statement.
> 
> I believe that this structure correctly reinstates the exact behavior
> from before the inheritance patch for the checked build, and that either
> way, the behavior in the unchecked build is the same.
> 
> Another approach to this would be to entirely eliminate these shared
> layout types, going purely with the conceptual is-a relationships
> between the types, say, by replacing the gengtype switch on GSS_ value
> with a switch on GIMPLE_ code.  Given that this might affect the speed
> of GC (bigger switch statements), I went with the relatively more
> conservative change.
> 
> Successfully bootstrapped&regtested on x86_64-unknown-linux-gnu.
> 
> OK for trunk?
> 
> Sorry again for breaking this.
> 
> Here's an ASCII art inheritance diagram, showing the relationships
> between structs, GSS_ values (layouts) and GIMPLE_ values (codes) - as I
> see them.  If I'm still misunderstanding something, sorry, please let me
> know.  Should this diagram live in gimple.h?
> +- gimple_statement_base
>      |    layout: GSS_BASE.  4 codes use this layout.
>      |
>      + gimple_statement_with_ops_base
>      |   |    (no GSS layout)
>      |   |
>      |   + gimple_statement_with_ops
>      |   |        layout: GSS_WITH_OPS.   5 codes use this layout.
>      |   |
>      |   + gimple_statement_with_memory_ops_base
>      |       |    layout: GSS_WITH_MEM_OPS_BASE
>      |       |
>      |       + gimple_statement_with_memory_ops
>      |       |        layout: GSS_WITH_MEM_OPS.
>      |       |        Used by codes GIMPLE_ASSIGN and GIMPLE_RETURN.
>      |       |
>      |       + gimple_statement_call
>      |       |        layout: GSS_CALL, code: GIMPLE_CALL
>      |       |
>      |       + gimple_statement_asm
>      |       |        layout: GSS_ASM, code: GIMPLE_ASM
>      |       |
>      |       + gimple_statement_transaction
>      |                layout: GSS_TRANSACTION, code: GIMPLE_TRANSACTION
>      |
>      + gimple_statement_omp
>      |   |    layout: GSS_OMP
>      |   |
>      |   + gimple_statement_omp_critical
>      |   |        layout: GSS_OMP_CRITICAL, code: GIMPLE_OMP_CRITICAL
>      |   |
>      |   + gimple_statement_omp_for
>      |   |        layout: GSS_OMP_FOR, code: GIMPLE_OMP_FOR
>      |   |
>      |   + gimple_statement_omp_parallel_layout
>      |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
>      |   |   |
>      |   |   + gimple_statement_omp_taskreg
>      |   |   |   |
>      |   |   |   + gimple_statement_omp_parallel
>      |   |   |   |        code: GIMPLE_OMP_PARALLEL
>      |   |   |   |
>      |   |   |   + gimple_statement_omp_task
>      |   |   |            code: GIMPLE_OMP_TASK
>      |   |   |
>      |   |   + gimple_statement_omp_target
>      |   |            code: GIMPLE_OMP_TARGET
>      |   |
>      |   + gimple_statement_omp_sections
>      |   |        layout: GSS_OMP_SECTIONS, code: GIMPLE_OMP_SECTIONS
>      |   |
>      |   + gimple_statement_omp_single_layout
>      |       |    layout: GSS_OMP_SINGLE_LAYOUT
>      |       |
>      |       + gimple_statement_omp_single
>      |       |        code: GIMPLE_OMP_SINGLE
>      |       |
>      |       + gimple_statement_omp_teams
>      |                code: GIMPLE_OMP_TEAMS
>      |
>      + gimple_statement_bind
>      |        layout: GSS_BIND, code: GIMPLE_BIND
>      |
>      + gimple_statement_catch
>      |        layout: GSS_CATCH, code: GIMPLE_CATCH
>      |
>      + gimple_statement_eh_filter
>      |        layout: GSS_EH_FILTER, code: GIMPLE_EH_FILTER
>      |
>      + gimple_statement_eh_else
>      |        layout: GSS_EH_ELSE, code: GIMPLE_EH_ELSE
>      |
>      + gimple_statement_eh_mnt
>      |        layout: GSS_EH_MNT, code: GIMPLE_EH_MUST_NOT_THROW
>      |
>      + gimple_statement_phi
>      |        layout: GSS_PHI, code: GIMPLE_PHI
>      |
>      + gimple_statement_eh_ctrl
>      |   |    layout: GSS_EH_CTRL
>      |   |
>      |   + gimple_statement_resx
>      |   |        code: GIMPLE_RESX
>      |   |
>      |   + gimple_statement_eh_dispatch
>      |            code: GIMPLE_EH_DISPATCH
>      |
>      + gimple_statement_try
>      |        layout: GSS_TRY, code: GIMPLE_TRY
>      |
>      + gimple_statement_wce
>      |        layout: GSS_WCE, code: GIMPLE_WITH_CLEANUP_EXPR
>      |
>      + gimple_statement_omp_continue
>      |        layout: GSS_OMP_CONTINUE, code: GIMPLE_OMP_CONTINUE
>      |
>      + gimple_statement_omp_atomic_load
>      |        layout: GSS_OMP_ATOMIC_LOAD, code: GIMPLE_OMP_ATOMIC_LOAD
>      |
>      + gimple_statement_omp_atomic_store_layout
>          |    layout: GSS_OMP_ATOMIC_STORE_LAYOUT,
>          |    code: GIMPLE_OMP_ATOMIC_STORE
>          |
>          + gimple_statement_omp_atomic_store
>          |        code: GIMPLE_OMP_ATOMIC_STORE
>          |
>          + gimple_statement_omp_return
>                   code: GIMPLE_OMP_RETURN
> 
> 
> commit 9a0c36081b3baecfc16a8500464df3a94c8dd145
> Author: David Malcolm <dmalcolm@redhat.com>
> Date:   Thu Nov 21 21:46:58 2013 -0500
> 
>     Fix as_a<> helpers for gimple
>     
>     	* gengtype.c (struct seen_tag): New.
>     	(already_seen_tag): New.
>     	(mark_tag_as_seen): New.
>     	(walk_subclasses): Support having multiple subclasses using the
>     	same tag by tracking which tags have already been seen, and using
>     	this to avoid adding duplicate cases to the "switch" statement.
>     	The call to already_seen_tag introduces an O(N^2) when running
>     	gengtype on N, the number of tags, due to the repeated linear
>     	search, but currently max(N) is relatively small (the number of
>     	GSS codes, which is 26).
>     	(walk_type): Pass in a seen_tag for use by the walk_subclasses
>     	recursion.
>     
>     	* gimple.def (GIMPLE_OMP_ATOMIC_STORE, GIMPLE_OMP_RETURN): Rename
>     	underlying GSS values for these codes (from GSS_OMP_ATOMIC_STORE to
>     	GSS_OMP_ATOMIC_STORE_LAYOUT) to make clear that although
>     	GIMPLE_OMP_RETURN happens to share the data layout of
>     	GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related.
>     	(GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET): Likewise, rename
>     	underlying GSS value from GSS_OMP_PARALLEL to
>     	GSS_OMP_PARALLEL_LAYOUT to make clear that these gimple codes are
>     	not directly related; they merely share in-memory layout.
>     	(GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS): Likewise, rename GSS values
>     	for these two codes from GSS_OMP_SINGLE to GSS_OMP_SINGLE_LAYOUT.
>     
>     	* gsstruct.def (GSS_OMP_PARALLEL, gimple_statement_omp_parallel):
>     	Rename to...
>     	(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout):
>     	...these.
>     	(GSS_OMP_SINGLE, gimple_statement_omp_single): Rename to...
>     	(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout):
>     	...these.
>     	(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store): Rename
>     	to...
>     	(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store):
>     	...these.
>     
>     	* gimple.h (gimple_statement_resx): New subclass of
>     	gimple_statement_eh_ctrl, with the invariant that
>     	stmt->code == GIMPLE_RESX.
>     	(gimple_statement_eh_dispatch): New subclass of
>     	gimple_statement_eh_ctrl, with the invariant that
>     	stmt->code == GIMPLE_EH_DISPATH.
>     
>     	(gimple_statement_omp_parallel): The existing class expressed
>     	a layout (GSS_OMP_PARALLEL), but the codes with that layout
>     	are not all related, so it makes more sense for this class to
>     	express a *code* (GIMPLE_OMP_PARALLEL).  GSS_OMP_PARALLEL has
>     	been renamed to GSS_OMP_PARALLEL_LAYOUT to express this, so
>     	rename the existing gimple_statement_omp_parallel class to...
>     	(gimple_statement_omp_parallel_layout): ...this, expressing
>     	a statement of structure layout GSS_OMP_PARALLEL_LAYOUT.
>     	(gimple_statement_omp_taskreg): New subclass of
>     	gimple_statement_omp_parallel_layout, expressing the invariant
>     	that the code is one of GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
>     	as used by the various gimple_omp_taskreg_ accessors.
>     	(gimple_statement_omp_parallel): Reintroduce this class, this time
>     	as a subclass of gimple_statement_omp_taskreg to express the
>     	invariant stmt->code == GIMPLE_OMP_PARALLEL.
>     	(gimple_statement_omp_target) New class, subclassing
>     	gimple_statement_omp_parallel_layout, to express the invariant
>     	stmt->code == GIMPLE_OMP_TARGET.
>     	(gimple_statement_omp_task): Update to inherit from
>     	gimple_statement_omp_taskreg rather than
>     	gimple_statement_omp_parallel.
>     
>     	(gimple_statement_omp_single): Rename to...
>     	(gimple_statement_omp_single_layout): ...this, expressing the
>     	invariant that the layout is GSS_OMP_SINGLE_LAYOUT.
>     	(gimple_statement_omp_single): ...and reintroduce this name as
>     	a subclass of gimple_statement_omp_single_layout, expressing
>     	the invariant that code == GIMPLE_OMP_SINGLE.
>     	(gimple_statement_omp_teams): New class, subclassing
>     	gimple_statement_omp_single_layout, for the code GIMPLE_OMP_TEAMS.
>     
>     	(gimple_statement_omp_atomic_store): Rename to...
>     	(gimple_statement_omp_atomic_store_layout): ...this, expressing
>     	the invariant that the layout is GSS_OMP_ATOMIC_STORE_LAYOUT.
>     	(gimple_statement_omp_atomic_store): ...and reintroduce this
>     	name as a subclass of gimple_statement_omp_atomic_store_layout
>     	with code == GIMPLE_OMP_ATOMIC_STORE.
>     	(gimple_statement_omp_return): New class, subclassing
>     	gimple_statement_omp_atomic_store_layout for the code
>     	GIMPLE_OMP_RETURN.
>     
>     	(is_a_helper <gimple_statement_eh_ctrl>::test): Delete.
>     	(is_a_helper <gimple_statement_resx>::test): New.
>     	(is_a_helper <gimple_statement_eh_dispatch>::test): New.
>     	(is_a_helper <gimple_statement_omp_atomic_store>::test): Only
>     	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
>     	(is_a_helper <gimple_statement_omp_return>::test): New.
>     	(is_a_helper <gimple_statement_omp_taskreg>::test): New.
>     	(is_a_helper <gimple_statement_omp_parallel>::test): Only check
>     	for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
>     	GIMPLE_OMP_TARGET.
>     	(is_a_helper <gimple_statement_omp_target>::test): New.
>     	(is_a_helper <gimple_statement_omp_single>::test): Only check
>     	for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
>     	(is_a_helper <gimple_statement_omp_teams>::test): New.
>     
>     	(is_a_helper <const gimple_statement_eh_ctrl>::test): Delete.
>     	(is_a_helper <const gimple_statement_resx>::test): New.
>     	(is_a_helper <const gimple_statement_eh_dispatch>::test): New.
>     	(is_a_helper <const gimple_statement_omp_atomic_store>::test): Only
>     	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
>     	(is_a_helper <const gimple_statement_omp_return>::test): New.
>     	(is_a_helper <const gimple_statement_omp_taskreg>::test): New.
>     	(is_a_helper <const gimple_statement_omp_parallel>::test): Only
>     	check for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
>     	GIMPLE_OMP_TARGET.
>     	(is_a_helper <const gimple_statement_omp_target>::test): New.
>     	(is_a_helper <const gimple_statement_omp_single>::test): Only
>     	check for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
>     	(is_a_helper <const gimple_statement_omp_teams>::test): New.
>     
>     	(gimple_omp_return_set_lhs, gimple_omp_return_lhs,
>     	gimple_omp_return_lhs_ptr): Replace bogus downcasts to
>     	gimple_statement_omp_atomic_store with downcasts to
>     	gimple_statement_omp_return, thus requiring that the code be
>     	GIMPLE_OMP_RETURN.
>     	(gimple_resx_region, gimple_resx_set_region): Replace bogus
>     	downcasts to gimple_statement_eh_ctrl with downcasts to
>     	gimple_statement_resx, thus requiring that the code be
>     	GIMPLE_RESX.
>     	(gimple_eh_dispatch_region, gimple_eh_dispatch_set_region):
>     	Replace bogus downcasts to const gimple_statement_eh_ctrl with
>     	downcasts to gimple_statement_eh_dispatch, thus requiring that
>     	the code be GIMPLE_EH_DISPATCH.
>     	(gimple_omp_taskreg_clauses, gimple_omp_taskreg_clauses_ptr)
>     	gimple_omp_taskreg_set_clauses, gimple_omp_taskreg_child_fn,
>     	gimple_omp_taskreg_child_fn_ptr, gimple_omp_taskreg_set_child_fn,
>     	gimple_omp_taskreg_data_arg, gimple_omp_taskreg_data_arg_ptr,
>     	gimple_omp_taskreg_set_data_arg): Replace bogus downcasts to
>     	gimple_statement_omp_parallel with downcasts to
>     	gimple_statement_omp_taskreg, thus requiring that the code be
>     	either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK.
>     	(gimple_omp_target_clauses, gimple_omp_target_clauses_ptr
>     	gimple_omp_target_set_clauses, gimple_omp_target_child_fn
>     	gimple_omp_target_child_fn_ptr, gimple_omp_target_set_child_fn
>     	gimple_omp_target_data_arg, gimple_omp_target_data_arg_ptr
>     	gimple_omp_target_set_data_arg): Replace bogus downcasts to
>     	gimple_statement_omp_parallel with downcasts to
>     	gimple_statement_omp_target, thus requiring that the code be
>     	GIMPLE_OMP_TARGET.
>     	(gimple_omp_teams_clauses, gimple_omp_teams_clauses_ptr
>     	gimple_omp_teams_set_clauses): Replace bogus downcasts to
>     	gimple_statement_omp_single with downcasts to
>     	gimple_statement_omp_teams, thus requiring that the code be
>     	GIMPLE_OMP_TEAMS.
>     
>     	* gimple.c (gimple_build_resx): Fix bogus as_a<> to use
>     	gimple_statement_resx.
>     	(gimple_build_eh_dispatch): Fix bogus as_a<> to use
>     	gimple_statement_eh_dispatch.
> 
> diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> index 86e9ca2..6e675cc 100644
> --- a/gcc/gengtype.c
> +++ b/gcc/gengtype.c
> @@ -2654,15 +2654,48 @@ get_string_option (options_p opt, const char *key)
>    return NULL;
>  }
>  
> +/* Machinery for avoiding duplicate tags within switch statements.  */
> +struct seen_tag
> +{
> +  const char *tag;
> +  struct seen_tag *next;
> +};
> +
> +int
> +already_seen_tag (struct seen_tag *seen_tags, const char *tag)
> +{
> +  /* Linear search, so O(n^2), but n is currently small.  */
> +  while (seen_tags)
> +    {
> +      if (!strcmp (seen_tags->tag, tag))
> +	return 1;
> +      seen_tags = seen_tags->next;
> +    }
> +  /* Not yet seen this tag. */
> +  return 0;
> +}
> +
> +void
> +mark_tag_as_seen (struct seen_tag **seen_tags, const char *tag)
> +{
> +  /* Add to front of linked list. */
> +  struct seen_tag *new_node = XCNEW (struct seen_tag);
> +  new_node->tag = tag;
> +  new_node->next = *seen_tags;
> +  *seen_tags = new_node;
> +}
> +
>  static void
> -walk_subclasses (type_p base, struct walk_type_data *d)
> +walk_subclasses (type_p base, struct walk_type_data *d,
> +		 struct seen_tag **seen_tags)
>  {
>    for (type_p sub = base->u.s.first_subclass; sub != NULL;
>         sub = sub->u.s.next_sibling_class)
>      {
>        const char *type_tag = get_string_option (sub->u.s.opt, "tag");
> -      if (type_tag)
> +      if (type_tag && !already_seen_tag (*seen_tags, type_tag))
>  	{
> +	  mark_tag_as_seen (seen_tags, type_tag);
>  	  oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
>  	  d->indent += 2;
>  	  oprintf (d->of, "%*s{\n", d->indent, "");
> @@ -2678,7 +2711,7 @@ walk_subclasses (type_p base, struct walk_type_data *d)
>  	  oprintf (d->of, "%*sbreak;\n", d->indent, "");
>  	  d->indent -= 2;
>  	}
> -      walk_subclasses (sub, d);
> +      walk_subclasses (sub, d, seen_tags);
>      }
>  }
>  
> @@ -3225,7 +3258,8 @@ walk_type (type_p t, struct walk_type_data *d)
>  	else if (desc)
>  	  {
>  	    /* Add cases to handle subclasses.  */
> -	    walk_subclasses (t, d);
> +	    struct seen_tag *tags = NULL;
> +	    walk_subclasses (t, d, &tags);
>  
>  	    /* Ensure that if someone forgets a "tag" option that we don't
>  	       silent fail to traverse that subclass's fields.  */
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index d48ca6b..2e45f37 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -697,8 +697,8 @@ gimple_build_wce (gimple_seq cleanup)
>  gimple
>  gimple_build_resx (int region)
>  {
> -  gimple_statement_eh_ctrl *p =
> -    as_a <gimple_statement_eh_ctrl> (
> +  gimple_statement_resx *p =
> +    as_a <gimple_statement_resx> (
>        gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
>    p->region = region;
>    return p;
> @@ -747,8 +747,8 @@ gimple_build_switch (tree index, tree default_label, vec<tree> args)
>  gimple
>  gimple_build_eh_dispatch (int region)
>  {
> -  gimple_statement_eh_ctrl *p =
> -    as_a <gimple_statement_eh_ctrl> (
> +  gimple_statement_eh_dispatch *p =
> +    as_a <gimple_statement_eh_dispatch> (
>        gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
>    p->region = region;
>    return p;
> diff --git a/gcc/gimple.def b/gcc/gimple.def
> index 07370ae..ff1ef43 100644
> --- a/gcc/gimple.def
> +++ b/gcc/gimple.def
> @@ -221,7 +221,7 @@ DEFGSCODE(GIMPLE_NOP, "gimple_nop", GSS_BASE)
>  DEFGSCODE(GIMPLE_OMP_ATOMIC_LOAD, "gimple_omp_atomic_load",
>  	  GSS_OMP_ATOMIC_LOAD)
>  DEFGSCODE(GIMPLE_OMP_ATOMIC_STORE, "gimple_omp_atomic_store",
> -	  GSS_OMP_ATOMIC_STORE)
> +	  GSS_OMP_ATOMIC_STORE_LAYOUT)
>  
>  /* GIMPLE_OMP_CONTINUE marks the location of the loop or sections
>     iteration in partially lowered OpenMP code.  */
> @@ -300,7 +300,7 @@ DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered", GSS_OMP)
>     DATA_ARG is a local variable in the parent function containing data
>     to be shared with CHILD_FN.  This is used to implement all the data
>     sharing clauses.  */
> -DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
> +DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL_LAYOUT)
>  
>  /* GIMPLE_OMP_TASK <BODY, CLAUSES, CHILD_FN, DATA_ARG, COPY_FN,
>  		    ARG_SIZE, ARG_ALIGN> represents
> @@ -329,7 +329,7 @@ DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
>  DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK)
>  
>  /* OMP_RETURN marks the end of an OpenMP directive.  */
> -DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE)
> +DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
>  
>  /* OMP_SECTION <BODY> represents #pragma omp section.
>     BODY is the sequence of statements in the section body.  */
> @@ -351,7 +351,7 @@ DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch", GSS_BASE)
>  /* GIMPLE_OMP_SINGLE <BODY, CLAUSES> represents #pragma omp single
>     BODY is the sequence of statements inside the single section.
>     CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
> -DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
> +DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE_LAYOUT)
>  
>  /* GIMPLE_OMP_TARGET <BODY, CLAUSES, CHILD_FN> represents
>     #pragma omp target {,data,update}
> @@ -364,12 +364,12 @@ DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
>     DATA_ARG is a vec of 3 local variables in the parent function
>     containing data to be mapped to CHILD_FN.  This is used to
>     implement the MAP clauses.  */
> -DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL)
> +DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)
>  
>  /* GIMPLE_OMP_TEAMS <BODY, CLAUSES> represents #pragma omp teams
>     BODY is the sequence of statements inside the single section.
>     CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
> -DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE)
> +DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE_LAYOUT)
>  
>  /* GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction.
>  
> diff --git a/gcc/gimple.h b/gcc/gimple.h
> index 0eb23fc..0257576 100644
> --- a/gcc/gimple.h
> +++ b/gcc/gimple.h
> @@ -420,6 +420,20 @@ struct GTY((tag("GSS_EH_CTRL")))
>    int region;
>  };
>  
> +struct GTY((tag("GSS_EH_CTRL")))
> +  gimple_statement_resx : public gimple_statement_eh_ctrl
> +{
> +  /* No extra fields; adds invariant:
> +       stmt->code == GIMPLE_RESX.  */
> +};
> +
> +struct GTY((tag("GSS_EH_CTRL")))
> +  gimple_statement_eh_dispatch : public gimple_statement_eh_ctrl
> +{
> +  /* No extra fields; adds invariant:
> +       stmt->code == GIMPLE_EH_DISPATH.  */
> +};
> +
>  
>  /* GIMPLE_TRY */
>  
> @@ -547,10 +561,9 @@ struct GTY((tag("GSS_OMP_FOR")))
>  };
>  
>  
> -/* GIMPLE_OMP_PARALLEL */
> -
> -struct GTY((tag("GSS_OMP_PARALLEL")))
> -  gimple_statement_omp_parallel : public gimple_statement_omp
> +/* GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET */
> +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> +  gimple_statement_omp_parallel_layout : public gimple_statement_omp
>  {
>    /* [ WORD 1-7 ] : base class */
>  
> @@ -567,11 +580,35 @@ struct GTY((tag("GSS_OMP_PARALLEL")))
>    tree data_arg;
>  };
>  
> +/* GIMPLE_OMP_PARALLEL or GIMPLE_TASK */
> +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> +  gimple_statement_omp_taskreg : public gimple_statement_omp_parallel_layout
> +{
> +    /* No extra fields; adds invariant:
> +         stmt->code == GIMPLE_OMP_PARALLEL
> +	 || stmt->code == GIMPLE_OMP_TASK.  */
> +};
> +
> +
> +/* GIMPLE_OMP_PARALLEL */
> +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> +  gimple_statement_omp_parallel : public gimple_statement_omp_taskreg
> +{
> +    /* No extra fields; adds invariant:
> +         stmt->code == GIMPLE_OMP_PARALLEL.  */
> +};
> +
> +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> +  gimple_statement_omp_target : public gimple_statement_omp_parallel_layout
> +{
> +    /* No extra fields; adds invariant:
> +         stmt->code == GIMPLE_OMP_TARGET.  */
> +};
>  
>  /* GIMPLE_OMP_TASK */
>  
>  struct GTY((tag("GSS_OMP_TASK")))
> -  gimple_statement_omp_task : public gimple_statement_omp_parallel
> +  gimple_statement_omp_task : public gimple_statement_omp_taskreg
>  {
>    /* [ WORD 1-10 ] : base class */
>  
> @@ -623,10 +660,10 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
>    tree control_use;
>  };
>  
> -/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS */
> +/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS */
>  
> -struct GTY((tag("GSS_OMP_SINGLE")))
> -  gimple_statement_omp_single : public gimple_statement_omp
> +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> +  gimple_statement_omp_single_layout : public gimple_statement_omp
>  {
>    /* [ WORD 1-7 ] : base class */
>  
> @@ -634,6 +671,20 @@ struct GTY((tag("GSS_OMP_SINGLE")))
>    tree clauses;
>  };
>  
> +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> +  gimple_statement_omp_single : public gimple_statement_omp_single_layout
> +{
> +    /* No extra fields; adds invariant:
> +         stmt->code == GIMPLE_OMP_SINGLE.  */
> +};
> +
> +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> +  gimple_statement_omp_teams : public gimple_statement_omp_single_layout
> +{
> +    /* No extra fields; adds invariant:
> +         stmt->code == GIMPLE_OMP_TEAMS.  */
> +};
> +
>  
>  /* GIMPLE_OMP_ATOMIC_LOAD.
>     Note: This is based on gimple_statement_base, not g_s_omp, because g_s_omp
> @@ -651,8 +702,8 @@ struct GTY((tag("GSS_OMP_ATOMIC_LOAD")))
>  /* GIMPLE_OMP_ATOMIC_STORE.
>     See note on GIMPLE_OMP_ATOMIC_LOAD.  */
>  
> -struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
> -  gimple_statement_omp_atomic_store : public gimple_statement_base
> +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> +  gimple_statement_omp_atomic_store_layout : public gimple_statement_base
>  {
>    /* [ WORD 1-6 ] : base class */
>  
> @@ -660,6 +711,22 @@ struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
>    tree val;
>  };
>  
> +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> +  gimple_statement_omp_atomic_store :
> +    public gimple_statement_omp_atomic_store_layout
> +{
> +    /* No extra fields; adds invariant:
> +         stmt->code == GIMPLE_OMP_ATOMIC_STORE.  */
> +};
> +
> +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> +  gimple_statement_omp_return :
> +    public gimple_statement_omp_atomic_store_layout
> +{
> +    /* No extra fields; adds invariant:
> +         stmt->code == GIMPLE_OMP_RETURN.  */
> +};
> +
>  /* GIMPLE_TRANSACTION.  */
>  
>  /* Bits to be stored in the GIMPLE_TRANSACTION subcode.  */
> @@ -742,9 +809,17 @@ is_a_helper <gimple_statement_catch>::test (gimple gs)
>  template <>
>  template <>
>  inline bool
> -is_a_helper <gimple_statement_eh_ctrl>::test (gimple gs)
> +is_a_helper <gimple_statement_resx>::test (gimple gs)
> +{
> +  return gs->code == GIMPLE_RESX;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <gimple_statement_eh_dispatch>::test (gimple gs)
>  {
> -  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
> +  return gs->code == GIMPLE_EH_DISPATCH;
>  }
>  
>  template <>
> @@ -784,7 +859,15 @@ template <>
>  inline bool
>  is_a_helper <gimple_statement_omp_atomic_store>::test (gimple gs)
>  {
> -  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
> +  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <gimple_statement_omp_return>::test (gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_RETURN;
>  }
>  
>  template <>
> @@ -814,9 +897,25 @@ is_a_helper <gimple_statement_omp_for>::test (gimple gs)
>  template <>
>  template <>
>  inline bool
> +is_a_helper <gimple_statement_omp_taskreg>::test (gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
> +}
> +
> +template <>
> +template <>
> +inline bool
>  is_a_helper <gimple_statement_omp_parallel>::test (gimple gs)
>  {
> -  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
> +  return gs->code == GIMPLE_OMP_PARALLEL;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <gimple_statement_omp_target>::test (gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_TARGET;
>  }
>  
>  template <>
> @@ -832,7 +931,15 @@ template <>
>  inline bool
>  is_a_helper <gimple_statement_omp_single>::test (gimple gs)
>  {
> -  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
> +  return gs->code == GIMPLE_OMP_SINGLE;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <gimple_statement_omp_teams>::test (gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_TEAMS;
>  }
>  
>  template <>
> @@ -910,9 +1017,17 @@ is_a_helper <const gimple_statement_catch>::test (const_gimple gs)
>  template <>
>  template <>
>  inline bool
> -is_a_helper <const gimple_statement_eh_ctrl>::test (const_gimple gs)
> +is_a_helper <const gimple_statement_resx>::test (const_gimple gs)
>  {
> -  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
> +  return gs->code == GIMPLE_RESX;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <const gimple_statement_eh_dispatch>::test (const_gimple gs)
> +{
> +  return gs->code == GIMPLE_EH_DISPATCH;
>  }
>  
>  template <>
> @@ -936,7 +1051,15 @@ template <>
>  inline bool
>  is_a_helper <const gimple_statement_omp_atomic_store>::test (const_gimple gs)
>  {
> -  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
> +  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <const gimple_statement_omp_return>::test (const_gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_RETURN;
>  }
>  
>  template <>
> @@ -966,9 +1089,25 @@ is_a_helper <const gimple_statement_omp_for>::test (const_gimple gs)
>  template <>
>  template <>
>  inline bool
> +is_a_helper <const gimple_statement_omp_taskreg>::test (const_gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
> +}
> +
> +template <>
> +template <>
> +inline bool
>  is_a_helper <const gimple_statement_omp_parallel>::test (const_gimple gs)
>  {
> -  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
> +  return gs->code == GIMPLE_OMP_PARALLEL;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <const gimple_statement_omp_target>::test (const_gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_TARGET;
>  }
>  
>  template <>
> @@ -984,7 +1123,15 @@ template <>
>  inline bool
>  is_a_helper <const gimple_statement_omp_single>::test (const_gimple gs)
>  {
> -  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
> +  return gs->code == GIMPLE_OMP_SINGLE;
> +}
> +
> +template <>
> +template <>
> +inline bool
> +is_a_helper <const gimple_statement_omp_teams>::test (const_gimple gs)
> +{
> +  return gs->code == GIMPLE_OMP_TEAMS;
>  }
>  
>  template <>
> @@ -1766,9 +1913,9 @@ gimple_omp_return_nowait_p (const_gimple g)
>  static inline void
>  gimple_omp_return_set_lhs (gimple g, tree lhs)
>  {
> -  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> -    as_a <gimple_statement_omp_atomic_store> (g);
> -  omp_atomic_store_stmt->val = lhs;
> +  gimple_statement_omp_return *omp_return_stmt =
> +    as_a <gimple_statement_omp_return> (g);
> +  omp_return_stmt->val = lhs;
>  }
>  
>  
> @@ -1777,9 +1924,9 @@ gimple_omp_return_set_lhs (gimple g, tree lhs)
>  static inline tree
>  gimple_omp_return_lhs (const_gimple g)
>  {
> -  const gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> -    as_a <const gimple_statement_omp_atomic_store> (g);
> -  return omp_atomic_store_stmt->val;
> +  const gimple_statement_omp_return *omp_return_stmt =
> +    as_a <const gimple_statement_omp_return> (g);
> +  return omp_return_stmt->val;
>  }
>  
>  
> @@ -1788,9 +1935,9 @@ gimple_omp_return_lhs (const_gimple g)
>  static inline tree *
>  gimple_omp_return_lhs_ptr (gimple g)
>  {
> -  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> -    as_a <gimple_statement_omp_atomic_store> (g);
> -  return &omp_atomic_store_stmt->val;
> +  gimple_statement_omp_return *omp_return_stmt =
> +    as_a <gimple_statement_omp_return> (g);
> +  return &omp_return_stmt->val;
>  }
>  
>  
> @@ -3793,9 +3940,9 @@ gimple_phi_arg_has_location (gimple gs, size_t i)
>  static inline int
>  gimple_resx_region (const_gimple gs)
>  {
> -  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
> -    as_a <const gimple_statement_eh_ctrl> (gs);
> -  return eh_ctrl_stmt->region;
> +  const gimple_statement_resx *resx_stmt =
> +    as_a <const gimple_statement_resx> (gs);
> +  return resx_stmt->region;
>  }
>  
>  /* Set REGION to be the region number for GIMPLE_RESX GS.  */
> @@ -3803,9 +3950,8 @@ gimple_resx_region (const_gimple gs)
>  static inline void
>  gimple_resx_set_region (gimple gs, int region)
>  {
> -  gimple_statement_eh_ctrl *eh_ctrl_stmt =
> -    as_a <gimple_statement_eh_ctrl> (gs);
> -  eh_ctrl_stmt->region = region;
> +  gimple_statement_resx *resx_stmt = as_a <gimple_statement_resx> (gs);
> +  resx_stmt->region = region;
>  }
>  
>  /* Return the region number for GIMPLE_EH_DISPATCH GS.  */
> @@ -3813,9 +3959,9 @@ gimple_resx_set_region (gimple gs, int region)
>  static inline int
>  gimple_eh_dispatch_region (const_gimple gs)
>  {
> -  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
> -    as_a <const gimple_statement_eh_ctrl> (gs);
> -  return eh_ctrl_stmt->region;
> +  const gimple_statement_eh_dispatch *eh_dispatch_stmt =
> +    as_a <const gimple_statement_eh_dispatch> (gs);
> +  return eh_dispatch_stmt->region;
>  }
>  
>  /* Set REGION to be the region number for GIMPLE_EH_DISPATCH GS.  */
> @@ -3823,9 +3969,9 @@ gimple_eh_dispatch_region (const_gimple gs)
>  static inline void
>  gimple_eh_dispatch_set_region (gimple gs, int region)
>  {
> -  gimple_statement_eh_ctrl *eh_ctrl_stmt =
> -    as_a <gimple_statement_eh_ctrl> (gs);
> -  eh_ctrl_stmt->region = region;
> +  gimple_statement_eh_dispatch *eh_dispatch_stmt =
> +    as_a <gimple_statement_eh_dispatch> (gs);
> +  eh_dispatch_stmt->region = region;
>  }
>  
>  /* Return the number of labels associated with the switch statement GS.  */
> @@ -4663,9 +4809,9 @@ gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
>  static inline tree
>  gimple_omp_taskreg_clauses (const_gimple gs)
>  {
> -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <const gimple_statement_omp_parallel> (gs);
> -  return omp_parallel_stmt->clauses;
> +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <const gimple_statement_omp_taskreg> (gs);
> +  return omp_taskreg_stmt->clauses;
>  }
>  
>  
> @@ -4674,9 +4820,9 @@ gimple_omp_taskreg_clauses (const_gimple gs)
>  static inline tree *
>  gimple_omp_taskreg_clauses_ptr (gimple gs)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  return &omp_parallel_stmt->clauses;
> +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <gimple_statement_omp_taskreg> (gs);
> +  return &omp_taskreg_stmt->clauses;
>  }
>  
>  
> @@ -4686,9 +4832,9 @@ gimple_omp_taskreg_clauses_ptr (gimple gs)
>  static inline void
>  gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  omp_parallel_stmt->clauses = clauses;
> +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <gimple_statement_omp_taskreg> (gs);
> +  omp_taskreg_stmt->clauses = clauses;
>  }
>  
>  
> @@ -4697,9 +4843,9 @@ gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
>  static inline tree
>  gimple_omp_taskreg_child_fn (const_gimple gs)
>  {
> -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <const gimple_statement_omp_parallel> (gs);
> -  return omp_parallel_stmt->child_fn;
> +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <const gimple_statement_omp_taskreg> (gs);
> +  return omp_taskreg_stmt->child_fn;
>  }
>  
>  /* Return a pointer to the child function used to hold the body of
> @@ -4708,9 +4854,9 @@ gimple_omp_taskreg_child_fn (const_gimple gs)
>  static inline tree *
>  gimple_omp_taskreg_child_fn_ptr (gimple gs)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  return &omp_parallel_stmt->child_fn;
> +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <gimple_statement_omp_taskreg> (gs);
> +  return &omp_taskreg_stmt->child_fn;
>  }
>  
>  
> @@ -4719,9 +4865,9 @@ gimple_omp_taskreg_child_fn_ptr (gimple gs)
>  static inline void
>  gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  omp_parallel_stmt->child_fn = child_fn;
> +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <gimple_statement_omp_taskreg> (gs);
> +  omp_taskreg_stmt->child_fn = child_fn;
>  }
>  
>  
> @@ -4731,9 +4877,9 @@ gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
>  static inline tree
>  gimple_omp_taskreg_data_arg (const_gimple gs)
>  {
> -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <const gimple_statement_omp_parallel> (gs);
> -  return omp_parallel_stmt->data_arg;
> +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <const gimple_statement_omp_taskreg> (gs);
> +  return omp_taskreg_stmt->data_arg;
>  }
>  
>  
> @@ -4742,9 +4888,9 @@ gimple_omp_taskreg_data_arg (const_gimple gs)
>  static inline tree *
>  gimple_omp_taskreg_data_arg_ptr (gimple gs)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  return &omp_parallel_stmt->data_arg;
> +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <gimple_statement_omp_taskreg> (gs);
> +  return &omp_taskreg_stmt->data_arg;
>  }
>  
>  
> @@ -4753,9 +4899,9 @@ gimple_omp_taskreg_data_arg_ptr (gimple gs)
>  static inline void
>  gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  omp_parallel_stmt->data_arg = data_arg;
> +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> +    as_a <gimple_statement_omp_taskreg> (gs);
> +  omp_taskreg_stmt->data_arg = data_arg;
>  }
>  
>  
> @@ -4896,9 +5042,9 @@ gimple_omp_single_set_clauses (gimple gs, tree clauses)
>  static inline tree
>  gimple_omp_target_clauses (const_gimple gs)
>  {
> -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <const gimple_statement_omp_parallel> (gs);
> -  return omp_parallel_stmt->clauses;
> +  const gimple_statement_omp_target *omp_target_stmt =
> +    as_a <const gimple_statement_omp_target> (gs);
> +  return omp_target_stmt->clauses;
>  }
>  
>  
> @@ -4907,9 +5053,9 @@ gimple_omp_target_clauses (const_gimple gs)
>  static inline tree *
>  gimple_omp_target_clauses_ptr (gimple gs)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  return &omp_parallel_stmt->clauses;
> +  gimple_statement_omp_target *omp_target_stmt =
> +    as_a <gimple_statement_omp_target> (gs);
> +  return &omp_target_stmt->clauses;
>  }
>  
>  
> @@ -4918,9 +5064,9 @@ gimple_omp_target_clauses_ptr (gimple gs)
>  static inline void
>  gimple_omp_target_set_clauses (gimple gs, tree clauses)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  omp_parallel_stmt->clauses = clauses;
> +  gimple_statement_omp_target *omp_target_stmt =
> +    as_a <gimple_statement_omp_target> (gs);
> +  omp_target_stmt->clauses = clauses;
>  }
>  
>  
> @@ -4950,9 +5096,9 @@ gimple_omp_target_set_kind (gimple g, int kind)
>  static inline tree
>  gimple_omp_target_child_fn (const_gimple gs)
>  {
> -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <const gimple_statement_omp_parallel> (gs);
> -  return omp_parallel_stmt->child_fn;
> +  const gimple_statement_omp_target *omp_target_stmt =
> +    as_a <const gimple_statement_omp_target> (gs);
> +  return omp_target_stmt->child_fn;
>  }
>  
>  /* Return a pointer to the child function used to hold the body of
> @@ -4961,9 +5107,9 @@ gimple_omp_target_child_fn (const_gimple gs)
>  static inline tree *
>  gimple_omp_target_child_fn_ptr (gimple gs)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  return &omp_parallel_stmt->child_fn;
> +  gimple_statement_omp_target *omp_target_stmt =
> +    as_a <gimple_statement_omp_target> (gs);
> +  return &omp_target_stmt->child_fn;
>  }
>  
>  
> @@ -4972,9 +5118,9 @@ gimple_omp_target_child_fn_ptr (gimple gs)
>  static inline void
>  gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  omp_parallel_stmt->child_fn = child_fn;
> +  gimple_statement_omp_target *omp_target_stmt =
> +    as_a <gimple_statement_omp_target> (gs);
> +  omp_target_stmt->child_fn = child_fn;
>  }
>  
>  
> @@ -4984,9 +5130,9 @@ gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
>  static inline tree
>  gimple_omp_target_data_arg (const_gimple gs)
>  {
> -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <const gimple_statement_omp_parallel> (gs);
> -  return omp_parallel_stmt->data_arg;
> +  const gimple_statement_omp_target *omp_target_stmt =
> +    as_a <const gimple_statement_omp_target> (gs);
> +  return omp_target_stmt->data_arg;
>  }
>  
>  
> @@ -4995,9 +5141,9 @@ gimple_omp_target_data_arg (const_gimple gs)
>  static inline tree *
>  gimple_omp_target_data_arg_ptr (gimple gs)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  return &omp_parallel_stmt->data_arg;
> +  gimple_statement_omp_target *omp_target_stmt =
> +    as_a <gimple_statement_omp_target> (gs);
> +  return &omp_target_stmt->data_arg;
>  }
>  
>  
> @@ -5006,9 +5152,9 @@ gimple_omp_target_data_arg_ptr (gimple gs)
>  static inline void
>  gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
>  {
> -  gimple_statement_omp_parallel *omp_parallel_stmt =
> -    as_a <gimple_statement_omp_parallel> (gs);
> -  omp_parallel_stmt->data_arg = data_arg;
> +  gimple_statement_omp_target *omp_target_stmt =
> +    as_a <gimple_statement_omp_target> (gs);
> +  omp_target_stmt->data_arg = data_arg;
>  }
>  
>  
> @@ -5017,9 +5163,9 @@ gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
>  static inline tree
>  gimple_omp_teams_clauses (const_gimple gs)
>  {
> -  const gimple_statement_omp_single *omp_single_stmt =
> -    as_a <const gimple_statement_omp_single> (gs);
> -  return omp_single_stmt->clauses;
> +  const gimple_statement_omp_teams *omp_teams_stmt =
> +    as_a <const gimple_statement_omp_teams> (gs);
> +  return omp_teams_stmt->clauses;
>  }
>  
>  
> @@ -5028,9 +5174,9 @@ gimple_omp_teams_clauses (const_gimple gs)
>  static inline tree *
>  gimple_omp_teams_clauses_ptr (gimple gs)
>  {
> -  gimple_statement_omp_single *omp_single_stmt =
> -    as_a <gimple_statement_omp_single> (gs);
> -  return &omp_single_stmt->clauses;
> +  gimple_statement_omp_teams *omp_teams_stmt =
> +    as_a <gimple_statement_omp_teams> (gs);
> +  return &omp_teams_stmt->clauses;
>  }
>  
>  
> @@ -5039,9 +5185,9 @@ gimple_omp_teams_clauses_ptr (gimple gs)
>  static inline void
>  gimple_omp_teams_set_clauses (gimple gs, tree clauses)
>  {
> -  gimple_statement_omp_single *omp_single_stmt =
> -    as_a <gimple_statement_omp_single> (gs);
> -  omp_single_stmt->clauses = clauses;
> +  gimple_statement_omp_teams *omp_teams_stmt =
> +    as_a <gimple_statement_omp_teams> (gs);
> +  omp_teams_stmt->clauses = clauses;
>  }
>  
>  
> diff --git a/gcc/gsstruct.def b/gcc/gsstruct.def
> index 91738f4..82f1f52 100644
> --- a/gcc/gsstruct.def
> +++ b/gcc/gsstruct.def
> @@ -43,11 +43,11 @@ DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false)
>  DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
>  DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false)
>  DEFGSSTRUCT(GSS_OMP_FOR, gimple_statement_omp_for, false)
> -DEFGSSTRUCT(GSS_OMP_PARALLEL, gimple_statement_omp_parallel, false)
> +DEFGSSTRUCT(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout, false)
>  DEFGSSTRUCT(GSS_OMP_TASK, gimple_statement_omp_task, false)
>  DEFGSSTRUCT(GSS_OMP_SECTIONS, gimple_statement_omp_sections, false)
> -DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_statement_omp_single, false)
> +DEFGSSTRUCT(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout, false)
>  DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false)
>  DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false)
> -DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false)
> +DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store, false)
>  DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false)


Grüße,
 Thomas
David Malcolm July 24, 2014, 12:54 a.m. UTC | #5
On Wed, 2014-07-23 at 15:00 +0200, Thomas Schwinge wrote:
> Hi!
> 
> In context of adding support for OpenACC, next to the existing
> GIMPLE_OMP_TARGET (quoting from gcc/gimple.def and gcc/gimple.h):
> 
>     DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)
> 
>     /* GIMPLE_OMP_TARGET */
>     struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
>       gimple_statement_omp_target : public gimple_statement_omp_parallel_layout
>     {
>         /* No extra fields; adds invariant:
>              stmt->code == GIMPLE_OMP_TARGET.  */
>     };
> 
> ..., we're adding additional GIMPLE codes:
> 
>     DEFGSCODE(GIMPLE_OACC_KERNELS, "gimple_oacc_kernels", GSS_OMP_PARALLEL_LAYOUT)
> 
>     /* GIMPLE_OACC_KERNELS */
>     struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
>       gimple_statement_oacc_kernels : public gimple_statement_omp_parallel_layout
>     {
>         /* No extra fields; adds invariant:
>              stmt->code == GIMPLE_OACC_KERNELS.  */
>     };
> 
>     DEFGSCODE(GIMPLE_OACC_PARALLEL, "gimple_oacc_parallel", GSS_OMP_PARALLEL_LAYOUT)
> 
>     /* GIMPLE_OACC_PARALLEL */
>     struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
>       gimple_statement_oacc_parallel : public gimple_statement_omp_parallel_layout
>     {
>         /* No extra fields; adds invariant:
>              stmt->code == GIMPLE_OACC_PARALLEL.  */
>     };
> 
> As you can see, all these codes share the same layout,
> GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout.
> 
> Given this, I'd like to better understand the following:
> 
> On Mon, 25 Nov 2013 10:35:18 -0500, David Malcolm <dmalcolm@redhat.com> wrote:
> > On Thu, 2013-11-21 at 18:03 -0500, Andrew MacLeod wrote:
> > > On 11/21/2013 05:42 PM, Jakub Jelinek wrote:
> > > > On Thu, Nov 21, 2013 at 03:24:55PM -0700, Jeff Law wrote:
> > > >> On 11/21/13 15:19, Jakub Jelinek wrote:
> > > >>> On Mon, Nov 18, 2013 at 03:25:52PM -0500, David Malcolm wrote:
> > > >>>>> So is there some reason the GIMPLE_CHECK was left in here rather than
> > > >>>>> doing the downcasting?  This happens in other places.
> > > >>> Note that the changes removed tons of checks that IMHO were desirable.
> > > >>> The as_a that replaced those checks e.g. allows 3 different gimple codes,
> > > >>> while previously only one was allowed, this is both more expensive for
> > > >>> --enable-checking=yes, and allows one to use inline wrappers e.g.
> > > >>> gimple_omp_parallel_something on GIMPLE_OMP_TASK etc.
> > > >> Can you give a couple examples, please?
> > > > I mean e.g.
> > > > gimple_omp_parallel_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > > gimple_omp_taskreg_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > > gimple_omp_target_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > > gimple_omp_teams_{,set_}clauses{,_ptr}
> > > > gimple_omp_return_{,set_}lhs{,_ptr}
> > > > gimple_omp_atomic_store_{,set_}val{,_ptr}
> > > > gimple_resx_{,set_}region
> > > > gimple_eh_dispatch_{,set_}region
> 
> We (have to) add the whole fleet of
> gimple_oacc_{kernels,parallel}_{clauses,...} accessors as well as new
> is_a_helper for {,const} gimple_statement_oacc_{kernels,parallel}.
> 
> > > Why does  is_a_helper <gimple_statement_omp_parallel>::test allow 
> > > anything other than a GIMPLE_OMP_PARALLEL..?  That seems wrong to me. 
> > > should just be the one check.
> > > 
> > > gimple_omp_taskreg and other routines "sharing" that helper should have 
> > > their own helper and only check the one code.. thats is whole point to 
> > > remain at least codegen neutral in these cases and provide correct 
> > > checking.   The fact that they may happen to share the same underlying 
> > > structure is irrelevant.
> > > 
> > > I also think this is wrong.
> > 
> > Mea culpa.  Unfortunately I made a conceptual error during the
> > conversion (the worst kind of error).  I misunderstood the relationships
> > between the various OMP statements: there (mostly) aren't any, but the
> > sharing of structures for layout made me think there were.
> > 
> > Attached is a patch, successfully bootstrapped&regtested on
> > x86_64-unknown-linux-gnu, which I believe reinstates the checked-build
> > behaviors from before r205034 (and that the unchecked-build behaviors
> > were not affected by that commit and likewise are not by this patch).
> > 
> > As I understand it, there are almost no "is-a" relationships between the
> > various omp statement types, some of them just happen to share layouts.
> > The exception is that the various gimple_omp_taskreg_* accessors accept
> > either codes GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK and so an
> > "omp_taskreg" is a concept, of which OMP_PARALLEL and OMP_TASK have an
> > is-a relationship.
> 
> Admittedly, there is no is-a relationship between these, but yet,
> GIMPLE_OMP_TARGET as well as the new GIMPLE_OACC_KERNELS and
> GIMPLE_OACC_PARALLEL can share a lot of code, but, for example, where
> previously gimple_omp_target_set_child_fn or gimple_omp_target_clauses
> have been used, I now find myself writing code such as:
> 
>       void (*gimple_omp_set_child_fn) (gimple, tree);
>       tree (*gimple_omp_clauses) (const_gimple);
>       switch (gimple_code (stmt))
>         {
>         case GIMPLE_OACC_KERNELS:
>           gimple_omp_set_child_fn = gimple_oacc_kernels_set_child_fn;
>           gimple_omp_clauses = gimple_oacc_kernels_clauses;
>           break;
>         case GIMPLE_OACC_PARALLEL:
>           gimple_omp_set_child_fn = gimple_oacc_parallel_set_child_fn;
>           gimple_omp_clauses = gimple_oacc_parallel_clauses;
>           break;
>         case GIMPLE_OMP_TARGET:
>           gimple_omp_set_child_fn = gimple_omp_target_set_child_fn;
>           gimple_omp_clauses = gimple_omp_target_clauses;
>           break;
>         default:
>           gcc_unreachable ();
>         }
> 
> ..., only that I can then in the following use a unified interface for
> setting the child function or getting access to the clauses.

Hmmmm.   What does the above code do, and is that pattern happening
repeatedly?  Given the above it sounds like we may need these types to
inherit from a common parent class ("gimple_something"), and for the
parent to provide:
 gimple_something_set_child_fn
 gimple_something_clauses

> What you can see here is that I first look at the GIMPLE code, and use
> that to determine the appropritate accessor functions.  I have to do that
> because these specific accessor functions then again would like to check
> the respective GIMPLE code -- which I have just checked in the code
> quoted above.  Instead, I'd rather like layout-specific accessor
> functions, such as gimple_omp_parallel_layout_set_child_fn or
> gimple_omp_parallel_layout_clauses.

BTW I have an 89-patch patch kit that strengthens the params to gimple
accessors, requiring appropriate subclasses, and eliminating the code
checks; see e.g.:
https://gcc.gnu.org/ml/gcc-patches/2014-04/msg01159.html
This patch kit was approved, but I was asked to hold off committing it
to trunk until 4.9.1 was out, and also to investigate some renamings, so
it's been in a "holding pattern" for a while.

So we'll need to incorporate whatever we do for OpenACC into those
patches (or vice versa).

FWIW, I was never particularly fond of the name
"gimple_omp_parallel_layout"; IIRC it was necessary as a way of
expressing that we're using a particular data layout
(GSS_OMP_PARALLEL_LAYOUT), and to be different from the specific
concrete subclass used for code GIMPLE_OMP_PARALLEL.

> Is this a reasonable wish, or am I misunderstanding what all this
> "boilerplate" code for GIMPLE code checking is meant to achieve?  (It's
> entirely possible that I'm misunderstanding something...)  ;-)
> 
> For example, might this suggest that our new GIMPLE code should in fact
> be proper sub-codes of GIMPLE_OMP_TARGET?  Hmm...

Right now, the relevant part of the class hierarchy looks like this
(from doc/gimple.texi):
     + gimple_statement_omp
     |   |    layout: GSS_OMP.  Used for code GIMPLE_OMP_SECTION
     |   |
     |   + gimple_statement_omp_parallel_layout
     |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
     |   |   |
     |   |   + gimple_statement_omp_taskreg
     |   |   |   |
     |   |   |   + gimple_statement_omp_parallel
     |   |   |   |        code: GIMPLE_OMP_PARALLEL
     |   |   |   |
     |   |   |   + gimple_statement_omp_task
     |   |   |            code: GIMPLE_OMP_TASK
     |   |   |
     |   |   + gimple_statement_omp_target
     |   |            code: GIMPLE_OMP_TARGET


Given the code fragment you posted above, where you want to work on each
of GIMPLE_OACC_KERNELS, GIMPLE_OACC_PARALLEL, GIMPLE_OMP_TARGET to get
at "set_child_fn" and the "clauses", it seems to me that you want the
new classes to inherit from either gimple_statement_omp_parallel_layout
(and have omp_target inherit from it) or from
gimple_statement_omp_target; the accessors could then work on that
specific new class.

I suspect I don't yet have enough knowledge of OpenACC and OpenMP to
propose a good name for the class, but for the former approach, the new
class hierarchy might look like this:
     + gimple_statement_omp
     |   |    layout: GSS_OMP.  Used for code GIMPLE_OMP_SECTION
     |   |
     |   + gimple_statement_omp_parallel_layout
     |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
     |   |   |
     |   |   + gimple_statement_omp_taskreg
     |   |   |   |
     |   |   |   + gimple_statement_omp_parallel
     |   |   |   |        code: GIMPLE_OMP_PARALLEL
     |   |   |   |
     |   |   |   + gimple_statement_omp_task
     |   |   |            code: GIMPLE_OMP_TASK
     |   |   |
     |   |   + "gimple_something" <<< NEW CLASS GOES HERE?
     |   |       |   
     |   |       + gimple_statement_omp_target
     |   |       |        code: GIMPLE_OMP_TARGET
     |   |       |
     |   |       + gimple_statement_oacc_kernels
     |   |       |        code: GIMPLE_OACC_KERNELS
     |   |       |
     |   |       + gimple_statement_oacc_parallel
     |   |                code: GIMPLE_OACC_PARALLEL

again, assuming that "gimple_something" is a meaningful concept, for the
above to be sane.

> And regardless of this, from someone who is still learning his share of
> GCC internals, many, many thanks to you, Andrew and David (as well as
> everyone else who's contributing, of course), for all the refactoring
> work you're doing!  This does make the GCC code more accessible.  :-)

Thanks; hope the above was helpful
Dave

> (Follows full quote for reference.)
> 
> > Based on this, I've reworked the is_a_helper functions, eliminating
> > almost all of the ones that accepted multiple codes.  The only ones that
> > remain accepting multiple codes are those for:
> > 
> >   * gimple_statement_with_ops, which uses gimple_has_ops (gs), and for
> >   * gimple_statement_with_memory_ops, which uses gimple_has_mem_ops
> > (gs), plus
> >   * a new class gimple_statement_omp_taskreg, which expresses the
> > "either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK" condition, and becomes a
> > parent struct for those.
> > 
> > I introduced some new structs to express the pre-existing layouts for
> > GSS codes, and to distinguish them from structs that imply a specific
> > GIMPLE_ code.
> > For example,
> >   gimple_statement_omp_atomic_store
> > now requires that the code be GIMPLE_OMP_ATOMIC_STORE, but it was also
> > the name of a layout, GSS_OMP_ATOMIC_STORE.  So I renamed these purely
> > layout classes, so that there is now a
> >   gimple_statement_omp_atomic_store_layout
> > class for the corresponding GSS value, which I renamed to
> >   GSS_OMP_ATOMIC_STORE_LAYOUT
> > to make clear that this is just a layout: that although
> > GIMPLE_OMP_RETURN happens to share the data layout of
> > GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related - they now both
> > inherit from the "_layout" class.
> > 
> > I'm not a fan of these "_layout" names, but I'm not sure what better to
> > call them. Perhaps:
> >    GSS_OMP_PARALLEL_LAYOUT     -> GSS_OMP_WITH_CLAUSES_CHILD_FN_DATA_ARG
> >    GSS_OMP_SINGLE_LAYOUT       -> GSS_OMP_WITH_CLAUSES
> >    GSS_OMP_ATOMIC_STORE_LAYOUT -> GSS_OMP_WITHOUT_SEQ_WITH_VAL
> > with analogous names for the corresponding structs.
> > 
> > I added GTY tags for every class in the hierarchy, not just those that
> > introduce a new layout, since gengtype only recognizes inheritance when
> > supplied a "tag" option.  This leads to the GSS values appearing
> > multiple times within the class hierarchy, which required a patch to
> > gengtype, to prevent duplicate case labels in the generated switch
> > statement.
> > 
> > I believe that this structure correctly reinstates the exact behavior
> > from before the inheritance patch for the checked build, and that either
> > way, the behavior in the unchecked build is the same.
> > 
> > Another approach to this would be to entirely eliminate these shared
> > layout types, going purely with the conceptual is-a relationships
> > between the types, say, by replacing the gengtype switch on GSS_ value
> > with a switch on GIMPLE_ code.  Given that this might affect the speed
> > of GC (bigger switch statements), I went with the relatively more
> > conservative change.
> > 
> > Successfully bootstrapped&regtested on x86_64-unknown-linux-gnu.
> > 
> > OK for trunk?
> > 
> > Sorry again for breaking this.
> > 
> > Here's an ASCII art inheritance diagram, showing the relationships
> > between structs, GSS_ values (layouts) and GIMPLE_ values (codes) - as I
> > see them.  If I'm still misunderstanding something, sorry, please let me
> > know.  Should this diagram live in gimple.h?
> > +- gimple_statement_base
> >      |    layout: GSS_BASE.  4 codes use this layout.
> >      |
> >      + gimple_statement_with_ops_base
> >      |   |    (no GSS layout)
> >      |   |
> >      |   + gimple_statement_with_ops
> >      |   |        layout: GSS_WITH_OPS.   5 codes use this layout.
> >      |   |
> >      |   + gimple_statement_with_memory_ops_base
> >      |       |    layout: GSS_WITH_MEM_OPS_BASE
> >      |       |
> >      |       + gimple_statement_with_memory_ops
> >      |       |        layout: GSS_WITH_MEM_OPS.
> >      |       |        Used by codes GIMPLE_ASSIGN and GIMPLE_RETURN.
> >      |       |
> >      |       + gimple_statement_call
> >      |       |        layout: GSS_CALL, code: GIMPLE_CALL
> >      |       |
> >      |       + gimple_statement_asm
> >      |       |        layout: GSS_ASM, code: GIMPLE_ASM
> >      |       |
> >      |       + gimple_statement_transaction
> >      |                layout: GSS_TRANSACTION, code: GIMPLE_TRANSACTION
> >      |
> >      + gimple_statement_omp
> >      |   |    layout: GSS_OMP
> >      |   |
> >      |   + gimple_statement_omp_critical
> >      |   |        layout: GSS_OMP_CRITICAL, code: GIMPLE_OMP_CRITICAL
> >      |   |
> >      |   + gimple_statement_omp_for
> >      |   |        layout: GSS_OMP_FOR, code: GIMPLE_OMP_FOR
> >      |   |
> >      |   + gimple_statement_omp_parallel_layout
> >      |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
> >      |   |   |
> >      |   |   + gimple_statement_omp_taskreg
> >      |   |   |   |
> >      |   |   |   + gimple_statement_omp_parallel
> >      |   |   |   |        code: GIMPLE_OMP_PARALLEL
> >      |   |   |   |
> >      |   |   |   + gimple_statement_omp_task
> >      |   |   |            code: GIMPLE_OMP_TASK
> >      |   |   |
> >      |   |   + gimple_statement_omp_target
> >      |   |            code: GIMPLE_OMP_TARGET
> >      |   |
> >      |   + gimple_statement_omp_sections
> >      |   |        layout: GSS_OMP_SECTIONS, code: GIMPLE_OMP_SECTIONS
> >      |   |
> >      |   + gimple_statement_omp_single_layout
> >      |       |    layout: GSS_OMP_SINGLE_LAYOUT
> >      |       |
> >      |       + gimple_statement_omp_single
> >      |       |        code: GIMPLE_OMP_SINGLE
> >      |       |
> >      |       + gimple_statement_omp_teams
> >      |                code: GIMPLE_OMP_TEAMS
> >      |
> >      + gimple_statement_bind
> >      |        layout: GSS_BIND, code: GIMPLE_BIND
> >      |
> >      + gimple_statement_catch
> >      |        layout: GSS_CATCH, code: GIMPLE_CATCH
> >      |
> >      + gimple_statement_eh_filter
> >      |        layout: GSS_EH_FILTER, code: GIMPLE_EH_FILTER
> >      |
> >      + gimple_statement_eh_else
> >      |        layout: GSS_EH_ELSE, code: GIMPLE_EH_ELSE
> >      |
> >      + gimple_statement_eh_mnt
> >      |        layout: GSS_EH_MNT, code: GIMPLE_EH_MUST_NOT_THROW
> >      |
> >      + gimple_statement_phi
> >      |        layout: GSS_PHI, code: GIMPLE_PHI
> >      |
> >      + gimple_statement_eh_ctrl
> >      |   |    layout: GSS_EH_CTRL
> >      |   |
> >      |   + gimple_statement_resx
> >      |   |        code: GIMPLE_RESX
> >      |   |
> >      |   + gimple_statement_eh_dispatch
> >      |            code: GIMPLE_EH_DISPATCH
> >      |
> >      + gimple_statement_try
> >      |        layout: GSS_TRY, code: GIMPLE_TRY
> >      |
> >      + gimple_statement_wce
> >      |        layout: GSS_WCE, code: GIMPLE_WITH_CLEANUP_EXPR
> >      |
> >      + gimple_statement_omp_continue
> >      |        layout: GSS_OMP_CONTINUE, code: GIMPLE_OMP_CONTINUE
> >      |
> >      + gimple_statement_omp_atomic_load
> >      |        layout: GSS_OMP_ATOMIC_LOAD, code: GIMPLE_OMP_ATOMIC_LOAD
> >      |
> >      + gimple_statement_omp_atomic_store_layout
> >          |    layout: GSS_OMP_ATOMIC_STORE_LAYOUT,
> >          |    code: GIMPLE_OMP_ATOMIC_STORE
> >          |
> >          + gimple_statement_omp_atomic_store
> >          |        code: GIMPLE_OMP_ATOMIC_STORE
> >          |
> >          + gimple_statement_omp_return
> >                   code: GIMPLE_OMP_RETURN
> > 
> > 
> > commit 9a0c36081b3baecfc16a8500464df3a94c8dd145
> > Author: David Malcolm <dmalcolm@redhat.com>
> > Date:   Thu Nov 21 21:46:58 2013 -0500
> > 
> >     Fix as_a<> helpers for gimple
> >     
> >     	* gengtype.c (struct seen_tag): New.
> >     	(already_seen_tag): New.
> >     	(mark_tag_as_seen): New.
> >     	(walk_subclasses): Support having multiple subclasses using the
> >     	same tag by tracking which tags have already been seen, and using
> >     	this to avoid adding duplicate cases to the "switch" statement.
> >     	The call to already_seen_tag introduces an O(N^2) when running
> >     	gengtype on N, the number of tags, due to the repeated linear
> >     	search, but currently max(N) is relatively small (the number of
> >     	GSS codes, which is 26).
> >     	(walk_type): Pass in a seen_tag for use by the walk_subclasses
> >     	recursion.
> >     
> >     	* gimple.def (GIMPLE_OMP_ATOMIC_STORE, GIMPLE_OMP_RETURN): Rename
> >     	underlying GSS values for these codes (from GSS_OMP_ATOMIC_STORE to
> >     	GSS_OMP_ATOMIC_STORE_LAYOUT) to make clear that although
> >     	GIMPLE_OMP_RETURN happens to share the data layout of
> >     	GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related.
> >     	(GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET): Likewise, rename
> >     	underlying GSS value from GSS_OMP_PARALLEL to
> >     	GSS_OMP_PARALLEL_LAYOUT to make clear that these gimple codes are
> >     	not directly related; they merely share in-memory layout.
> >     	(GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS): Likewise, rename GSS values
> >     	for these two codes from GSS_OMP_SINGLE to GSS_OMP_SINGLE_LAYOUT.
> >     
> >     	* gsstruct.def (GSS_OMP_PARALLEL, gimple_statement_omp_parallel):
> >     	Rename to...
> >     	(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout):
> >     	...these.
> >     	(GSS_OMP_SINGLE, gimple_statement_omp_single): Rename to...
> >     	(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout):
> >     	...these.
> >     	(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store): Rename
> >     	to...
> >     	(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store):
> >     	...these.
> >     
> >     	* gimple.h (gimple_statement_resx): New subclass of
> >     	gimple_statement_eh_ctrl, with the invariant that
> >     	stmt->code == GIMPLE_RESX.
> >     	(gimple_statement_eh_dispatch): New subclass of
> >     	gimple_statement_eh_ctrl, with the invariant that
> >     	stmt->code == GIMPLE_EH_DISPATH.
> >     
> >     	(gimple_statement_omp_parallel): The existing class expressed
> >     	a layout (GSS_OMP_PARALLEL), but the codes with that layout
> >     	are not all related, so it makes more sense for this class to
> >     	express a *code* (GIMPLE_OMP_PARALLEL).  GSS_OMP_PARALLEL has
> >     	been renamed to GSS_OMP_PARALLEL_LAYOUT to express this, so
> >     	rename the existing gimple_statement_omp_parallel class to...
> >     	(gimple_statement_omp_parallel_layout): ...this, expressing
> >     	a statement of structure layout GSS_OMP_PARALLEL_LAYOUT.
> >     	(gimple_statement_omp_taskreg): New subclass of
> >     	gimple_statement_omp_parallel_layout, expressing the invariant
> >     	that the code is one of GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
> >     	as used by the various gimple_omp_taskreg_ accessors.
> >     	(gimple_statement_omp_parallel): Reintroduce this class, this time
> >     	as a subclass of gimple_statement_omp_taskreg to express the
> >     	invariant stmt->code == GIMPLE_OMP_PARALLEL.
> >     	(gimple_statement_omp_target) New class, subclassing
> >     	gimple_statement_omp_parallel_layout, to express the invariant
> >     	stmt->code == GIMPLE_OMP_TARGET.
> >     	(gimple_statement_omp_task): Update to inherit from
> >     	gimple_statement_omp_taskreg rather than
> >     	gimple_statement_omp_parallel.
> >     
> >     	(gimple_statement_omp_single): Rename to...
> >     	(gimple_statement_omp_single_layout): ...this, expressing the
> >     	invariant that the layout is GSS_OMP_SINGLE_LAYOUT.
> >     	(gimple_statement_omp_single): ...and reintroduce this name as
> >     	a subclass of gimple_statement_omp_single_layout, expressing
> >     	the invariant that code == GIMPLE_OMP_SINGLE.
> >     	(gimple_statement_omp_teams): New class, subclassing
> >     	gimple_statement_omp_single_layout, for the code GIMPLE_OMP_TEAMS.
> >     
> >     	(gimple_statement_omp_atomic_store): Rename to...
> >     	(gimple_statement_omp_atomic_store_layout): ...this, expressing
> >     	the invariant that the layout is GSS_OMP_ATOMIC_STORE_LAYOUT.
> >     	(gimple_statement_omp_atomic_store): ...and reintroduce this
> >     	name as a subclass of gimple_statement_omp_atomic_store_layout
> >     	with code == GIMPLE_OMP_ATOMIC_STORE.
> >     	(gimple_statement_omp_return): New class, subclassing
> >     	gimple_statement_omp_atomic_store_layout for the code
> >     	GIMPLE_OMP_RETURN.
> >     
> >     	(is_a_helper <gimple_statement_eh_ctrl>::test): Delete.
> >     	(is_a_helper <gimple_statement_resx>::test): New.
> >     	(is_a_helper <gimple_statement_eh_dispatch>::test): New.
> >     	(is_a_helper <gimple_statement_omp_atomic_store>::test): Only
> >     	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
> >     	(is_a_helper <gimple_statement_omp_return>::test): New.
> >     	(is_a_helper <gimple_statement_omp_taskreg>::test): New.
> >     	(is_a_helper <gimple_statement_omp_parallel>::test): Only check
> >     	for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
> >     	GIMPLE_OMP_TARGET.
> >     	(is_a_helper <gimple_statement_omp_target>::test): New.
> >     	(is_a_helper <gimple_statement_omp_single>::test): Only check
> >     	for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
> >     	(is_a_helper <gimple_statement_omp_teams>::test): New.
> >     
> >     	(is_a_helper <const gimple_statement_eh_ctrl>::test): Delete.
> >     	(is_a_helper <const gimple_statement_resx>::test): New.
> >     	(is_a_helper <const gimple_statement_eh_dispatch>::test): New.
> >     	(is_a_helper <const gimple_statement_omp_atomic_store>::test): Only
> >     	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
> >     	(is_a_helper <const gimple_statement_omp_return>::test): New.
> >     	(is_a_helper <const gimple_statement_omp_taskreg>::test): New.
> >     	(is_a_helper <const gimple_statement_omp_parallel>::test): Only
> >     	check for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
> >     	GIMPLE_OMP_TARGET.
> >     	(is_a_helper <const gimple_statement_omp_target>::test): New.
> >     	(is_a_helper <const gimple_statement_omp_single>::test): Only
> >     	check for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
> >     	(is_a_helper <const gimple_statement_omp_teams>::test): New.
> >     
> >     	(gimple_omp_return_set_lhs, gimple_omp_return_lhs,
> >     	gimple_omp_return_lhs_ptr): Replace bogus downcasts to
> >     	gimple_statement_omp_atomic_store with downcasts to
> >     	gimple_statement_omp_return, thus requiring that the code be
> >     	GIMPLE_OMP_RETURN.
> >     	(gimple_resx_region, gimple_resx_set_region): Replace bogus
> >     	downcasts to gimple_statement_eh_ctrl with downcasts to
> >     	gimple_statement_resx, thus requiring that the code be
> >     	GIMPLE_RESX.
> >     	(gimple_eh_dispatch_region, gimple_eh_dispatch_set_region):
> >     	Replace bogus downcasts to const gimple_statement_eh_ctrl with
> >     	downcasts to gimple_statement_eh_dispatch, thus requiring that
> >     	the code be GIMPLE_EH_DISPATCH.
> >     	(gimple_omp_taskreg_clauses, gimple_omp_taskreg_clauses_ptr)
> >     	gimple_omp_taskreg_set_clauses, gimple_omp_taskreg_child_fn,
> >     	gimple_omp_taskreg_child_fn_ptr, gimple_omp_taskreg_set_child_fn,
> >     	gimple_omp_taskreg_data_arg, gimple_omp_taskreg_data_arg_ptr,
> >     	gimple_omp_taskreg_set_data_arg): Replace bogus downcasts to
> >     	gimple_statement_omp_parallel with downcasts to
> >     	gimple_statement_omp_taskreg, thus requiring that the code be
> >     	either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK.
> >     	(gimple_omp_target_clauses, gimple_omp_target_clauses_ptr
> >     	gimple_omp_target_set_clauses, gimple_omp_target_child_fn
> >     	gimple_omp_target_child_fn_ptr, gimple_omp_target_set_child_fn
> >     	gimple_omp_target_data_arg, gimple_omp_target_data_arg_ptr
> >     	gimple_omp_target_set_data_arg): Replace bogus downcasts to
> >     	gimple_statement_omp_parallel with downcasts to
> >     	gimple_statement_omp_target, thus requiring that the code be
> >     	GIMPLE_OMP_TARGET.
> >     	(gimple_omp_teams_clauses, gimple_omp_teams_clauses_ptr
> >     	gimple_omp_teams_set_clauses): Replace bogus downcasts to
> >     	gimple_statement_omp_single with downcasts to
> >     	gimple_statement_omp_teams, thus requiring that the code be
> >     	GIMPLE_OMP_TEAMS.
> >     
> >     	* gimple.c (gimple_build_resx): Fix bogus as_a<> to use
> >     	gimple_statement_resx.
> >     	(gimple_build_eh_dispatch): Fix bogus as_a<> to use
> >     	gimple_statement_eh_dispatch.
> > 
> > diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> > index 86e9ca2..6e675cc 100644
> > --- a/gcc/gengtype.c
> > +++ b/gcc/gengtype.c
> > @@ -2654,15 +2654,48 @@ get_string_option (options_p opt, const char *key)
> >    return NULL;
> >  }
> >  
> > +/* Machinery for avoiding duplicate tags within switch statements.  */
> > +struct seen_tag
> > +{
> > +  const char *tag;
> > +  struct seen_tag *next;
> > +};
> > +
> > +int
> > +already_seen_tag (struct seen_tag *seen_tags, const char *tag)
> > +{
> > +  /* Linear search, so O(n^2), but n is currently small.  */
> > +  while (seen_tags)
> > +    {
> > +      if (!strcmp (seen_tags->tag, tag))
> > +	return 1;
> > +      seen_tags = seen_tags->next;
> > +    }
> > +  /* Not yet seen this tag. */
> > +  return 0;
> > +}
> > +
> > +void
> > +mark_tag_as_seen (struct seen_tag **seen_tags, const char *tag)
> > +{
> > +  /* Add to front of linked list. */
> > +  struct seen_tag *new_node = XCNEW (struct seen_tag);
> > +  new_node->tag = tag;
> > +  new_node->next = *seen_tags;
> > +  *seen_tags = new_node;
> > +}
> > +
> >  static void
> > -walk_subclasses (type_p base, struct walk_type_data *d)
> > +walk_subclasses (type_p base, struct walk_type_data *d,
> > +		 struct seen_tag **seen_tags)
> >  {
> >    for (type_p sub = base->u.s.first_subclass; sub != NULL;
> >         sub = sub->u.s.next_sibling_class)
> >      {
> >        const char *type_tag = get_string_option (sub->u.s.opt, "tag");
> > -      if (type_tag)
> > +      if (type_tag && !already_seen_tag (*seen_tags, type_tag))
> >  	{
> > +	  mark_tag_as_seen (seen_tags, type_tag);
> >  	  oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
> >  	  d->indent += 2;
> >  	  oprintf (d->of, "%*s{\n", d->indent, "");
> > @@ -2678,7 +2711,7 @@ walk_subclasses (type_p base, struct walk_type_data *d)
> >  	  oprintf (d->of, "%*sbreak;\n", d->indent, "");
> >  	  d->indent -= 2;
> >  	}
> > -      walk_subclasses (sub, d);
> > +      walk_subclasses (sub, d, seen_tags);
> >      }
> >  }
> >  
> > @@ -3225,7 +3258,8 @@ walk_type (type_p t, struct walk_type_data *d)
> >  	else if (desc)
> >  	  {
> >  	    /* Add cases to handle subclasses.  */
> > -	    walk_subclasses (t, d);
> > +	    struct seen_tag *tags = NULL;
> > +	    walk_subclasses (t, d, &tags);
> >  
> >  	    /* Ensure that if someone forgets a "tag" option that we don't
> >  	       silent fail to traverse that subclass's fields.  */
> > diff --git a/gcc/gimple.c b/gcc/gimple.c
> > index d48ca6b..2e45f37 100644
> > --- a/gcc/gimple.c
> > +++ b/gcc/gimple.c
> > @@ -697,8 +697,8 @@ gimple_build_wce (gimple_seq cleanup)
> >  gimple
> >  gimple_build_resx (int region)
> >  {
> > -  gimple_statement_eh_ctrl *p =
> > -    as_a <gimple_statement_eh_ctrl> (
> > +  gimple_statement_resx *p =
> > +    as_a <gimple_statement_resx> (
> >        gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
> >    p->region = region;
> >    return p;
> > @@ -747,8 +747,8 @@ gimple_build_switch (tree index, tree default_label, vec<tree> args)
> >  gimple
> >  gimple_build_eh_dispatch (int region)
> >  {
> > -  gimple_statement_eh_ctrl *p =
> > -    as_a <gimple_statement_eh_ctrl> (
> > +  gimple_statement_eh_dispatch *p =
> > +    as_a <gimple_statement_eh_dispatch> (
> >        gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
> >    p->region = region;
> >    return p;
> > diff --git a/gcc/gimple.def b/gcc/gimple.def
> > index 07370ae..ff1ef43 100644
> > --- a/gcc/gimple.def
> > +++ b/gcc/gimple.def
> > @@ -221,7 +221,7 @@ DEFGSCODE(GIMPLE_NOP, "gimple_nop", GSS_BASE)
> >  DEFGSCODE(GIMPLE_OMP_ATOMIC_LOAD, "gimple_omp_atomic_load",
> >  	  GSS_OMP_ATOMIC_LOAD)
> >  DEFGSCODE(GIMPLE_OMP_ATOMIC_STORE, "gimple_omp_atomic_store",
> > -	  GSS_OMP_ATOMIC_STORE)
> > +	  GSS_OMP_ATOMIC_STORE_LAYOUT)
> >  
> >  /* GIMPLE_OMP_CONTINUE marks the location of the loop or sections
> >     iteration in partially lowered OpenMP code.  */
> > @@ -300,7 +300,7 @@ DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered", GSS_OMP)
> >     DATA_ARG is a local variable in the parent function containing data
> >     to be shared with CHILD_FN.  This is used to implement all the data
> >     sharing clauses.  */
> > -DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
> > +DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL_LAYOUT)
> >  
> >  /* GIMPLE_OMP_TASK <BODY, CLAUSES, CHILD_FN, DATA_ARG, COPY_FN,
> >  		    ARG_SIZE, ARG_ALIGN> represents
> > @@ -329,7 +329,7 @@ DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
> >  DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK)
> >  
> >  /* OMP_RETURN marks the end of an OpenMP directive.  */
> > -DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE)
> > +DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
> >  
> >  /* OMP_SECTION <BODY> represents #pragma omp section.
> >     BODY is the sequence of statements in the section body.  */
> > @@ -351,7 +351,7 @@ DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch", GSS_BASE)
> >  /* GIMPLE_OMP_SINGLE <BODY, CLAUSES> represents #pragma omp single
> >     BODY is the sequence of statements inside the single section.
> >     CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
> > -DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
> > +DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE_LAYOUT)
> >  
> >  /* GIMPLE_OMP_TARGET <BODY, CLAUSES, CHILD_FN> represents
> >     #pragma omp target {,data,update}
> > @@ -364,12 +364,12 @@ DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
> >     DATA_ARG is a vec of 3 local variables in the parent function
> >     containing data to be mapped to CHILD_FN.  This is used to
> >     implement the MAP clauses.  */
> > -DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL)
> > +DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)
> >  
> >  /* GIMPLE_OMP_TEAMS <BODY, CLAUSES> represents #pragma omp teams
> >     BODY is the sequence of statements inside the single section.
> >     CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
> > -DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE)
> > +DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE_LAYOUT)
> >  
> >  /* GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction.
> >  
> > diff --git a/gcc/gimple.h b/gcc/gimple.h
> > index 0eb23fc..0257576 100644
> > --- a/gcc/gimple.h
> > +++ b/gcc/gimple.h
> > @@ -420,6 +420,20 @@ struct GTY((tag("GSS_EH_CTRL")))
> >    int region;
> >  };
> >  
> > +struct GTY((tag("GSS_EH_CTRL")))
> > +  gimple_statement_resx : public gimple_statement_eh_ctrl
> > +{
> > +  /* No extra fields; adds invariant:
> > +       stmt->code == GIMPLE_RESX.  */
> > +};
> > +
> > +struct GTY((tag("GSS_EH_CTRL")))
> > +  gimple_statement_eh_dispatch : public gimple_statement_eh_ctrl
> > +{
> > +  /* No extra fields; adds invariant:
> > +       stmt->code == GIMPLE_EH_DISPATH.  */
> > +};
> > +
> >  
> >  /* GIMPLE_TRY */
> >  
> > @@ -547,10 +561,9 @@ struct GTY((tag("GSS_OMP_FOR")))
> >  };
> >  
> >  
> > -/* GIMPLE_OMP_PARALLEL */
> > -
> > -struct GTY((tag("GSS_OMP_PARALLEL")))
> > -  gimple_statement_omp_parallel : public gimple_statement_omp
> > +/* GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET */
> > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > +  gimple_statement_omp_parallel_layout : public gimple_statement_omp
> >  {
> >    /* [ WORD 1-7 ] : base class */
> >  
> > @@ -567,11 +580,35 @@ struct GTY((tag("GSS_OMP_PARALLEL")))
> >    tree data_arg;
> >  };
> >  
> > +/* GIMPLE_OMP_PARALLEL or GIMPLE_TASK */
> > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > +  gimple_statement_omp_taskreg : public gimple_statement_omp_parallel_layout
> > +{
> > +    /* No extra fields; adds invariant:
> > +         stmt->code == GIMPLE_OMP_PARALLEL
> > +	 || stmt->code == GIMPLE_OMP_TASK.  */
> > +};
> > +
> > +
> > +/* GIMPLE_OMP_PARALLEL */
> > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > +  gimple_statement_omp_parallel : public gimple_statement_omp_taskreg
> > +{
> > +    /* No extra fields; adds invariant:
> > +         stmt->code == GIMPLE_OMP_PARALLEL.  */
> > +};
> > +
> > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > +  gimple_statement_omp_target : public gimple_statement_omp_parallel_layout
> > +{
> > +    /* No extra fields; adds invariant:
> > +         stmt->code == GIMPLE_OMP_TARGET.  */
> > +};
> >  
> >  /* GIMPLE_OMP_TASK */
> >  
> >  struct GTY((tag("GSS_OMP_TASK")))
> > -  gimple_statement_omp_task : public gimple_statement_omp_parallel
> > +  gimple_statement_omp_task : public gimple_statement_omp_taskreg
> >  {
> >    /* [ WORD 1-10 ] : base class */
> >  
> > @@ -623,10 +660,10 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
> >    tree control_use;
> >  };
> >  
> > -/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS */
> > +/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS */
> >  
> > -struct GTY((tag("GSS_OMP_SINGLE")))
> > -  gimple_statement_omp_single : public gimple_statement_omp
> > +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> > +  gimple_statement_omp_single_layout : public gimple_statement_omp
> >  {
> >    /* [ WORD 1-7 ] : base class */
> >  
> > @@ -634,6 +671,20 @@ struct GTY((tag("GSS_OMP_SINGLE")))
> >    tree clauses;
> >  };
> >  
> > +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> > +  gimple_statement_omp_single : public gimple_statement_omp_single_layout
> > +{
> > +    /* No extra fields; adds invariant:
> > +         stmt->code == GIMPLE_OMP_SINGLE.  */
> > +};
> > +
> > +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> > +  gimple_statement_omp_teams : public gimple_statement_omp_single_layout
> > +{
> > +    /* No extra fields; adds invariant:
> > +         stmt->code == GIMPLE_OMP_TEAMS.  */
> > +};
> > +
> >  
> >  /* GIMPLE_OMP_ATOMIC_LOAD.
> >     Note: This is based on gimple_statement_base, not g_s_omp, because g_s_omp
> > @@ -651,8 +702,8 @@ struct GTY((tag("GSS_OMP_ATOMIC_LOAD")))
> >  /* GIMPLE_OMP_ATOMIC_STORE.
> >     See note on GIMPLE_OMP_ATOMIC_LOAD.  */
> >  
> > -struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
> > -  gimple_statement_omp_atomic_store : public gimple_statement_base
> > +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> > +  gimple_statement_omp_atomic_store_layout : public gimple_statement_base
> >  {
> >    /* [ WORD 1-6 ] : base class */
> >  
> > @@ -660,6 +711,22 @@ struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
> >    tree val;
> >  };
> >  
> > +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> > +  gimple_statement_omp_atomic_store :
> > +    public gimple_statement_omp_atomic_store_layout
> > +{
> > +    /* No extra fields; adds invariant:
> > +         stmt->code == GIMPLE_OMP_ATOMIC_STORE.  */
> > +};
> > +
> > +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> > +  gimple_statement_omp_return :
> > +    public gimple_statement_omp_atomic_store_layout
> > +{
> > +    /* No extra fields; adds invariant:
> > +         stmt->code == GIMPLE_OMP_RETURN.  */
> > +};
> > +
> >  /* GIMPLE_TRANSACTION.  */
> >  
> >  /* Bits to be stored in the GIMPLE_TRANSACTION subcode.  */
> > @@ -742,9 +809,17 @@ is_a_helper <gimple_statement_catch>::test (gimple gs)
> >  template <>
> >  template <>
> >  inline bool
> > -is_a_helper <gimple_statement_eh_ctrl>::test (gimple gs)
> > +is_a_helper <gimple_statement_resx>::test (gimple gs)
> > +{
> > +  return gs->code == GIMPLE_RESX;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <gimple_statement_eh_dispatch>::test (gimple gs)
> >  {
> > -  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
> > +  return gs->code == GIMPLE_EH_DISPATCH;
> >  }
> >  
> >  template <>
> > @@ -784,7 +859,15 @@ template <>
> >  inline bool
> >  is_a_helper <gimple_statement_omp_atomic_store>::test (gimple gs)
> >  {
> > -  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
> > +  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <gimple_statement_omp_return>::test (gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_RETURN;
> >  }
> >  
> >  template <>
> > @@ -814,9 +897,25 @@ is_a_helper <gimple_statement_omp_for>::test (gimple gs)
> >  template <>
> >  template <>
> >  inline bool
> > +is_a_helper <gimple_statement_omp_taskreg>::test (gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> >  is_a_helper <gimple_statement_omp_parallel>::test (gimple gs)
> >  {
> > -  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
> > +  return gs->code == GIMPLE_OMP_PARALLEL;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <gimple_statement_omp_target>::test (gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_TARGET;
> >  }
> >  
> >  template <>
> > @@ -832,7 +931,15 @@ template <>
> >  inline bool
> >  is_a_helper <gimple_statement_omp_single>::test (gimple gs)
> >  {
> > -  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
> > +  return gs->code == GIMPLE_OMP_SINGLE;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <gimple_statement_omp_teams>::test (gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_TEAMS;
> >  }
> >  
> >  template <>
> > @@ -910,9 +1017,17 @@ is_a_helper <const gimple_statement_catch>::test (const_gimple gs)
> >  template <>
> >  template <>
> >  inline bool
> > -is_a_helper <const gimple_statement_eh_ctrl>::test (const_gimple gs)
> > +is_a_helper <const gimple_statement_resx>::test (const_gimple gs)
> >  {
> > -  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
> > +  return gs->code == GIMPLE_RESX;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <const gimple_statement_eh_dispatch>::test (const_gimple gs)
> > +{
> > +  return gs->code == GIMPLE_EH_DISPATCH;
> >  }
> >  
> >  template <>
> > @@ -936,7 +1051,15 @@ template <>
> >  inline bool
> >  is_a_helper <const gimple_statement_omp_atomic_store>::test (const_gimple gs)
> >  {
> > -  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
> > +  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <const gimple_statement_omp_return>::test (const_gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_RETURN;
> >  }
> >  
> >  template <>
> > @@ -966,9 +1089,25 @@ is_a_helper <const gimple_statement_omp_for>::test (const_gimple gs)
> >  template <>
> >  template <>
> >  inline bool
> > +is_a_helper <const gimple_statement_omp_taskreg>::test (const_gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> >  is_a_helper <const gimple_statement_omp_parallel>::test (const_gimple gs)
> >  {
> > -  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
> > +  return gs->code == GIMPLE_OMP_PARALLEL;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <const gimple_statement_omp_target>::test (const_gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_TARGET;
> >  }
> >  
> >  template <>
> > @@ -984,7 +1123,15 @@ template <>
> >  inline bool
> >  is_a_helper <const gimple_statement_omp_single>::test (const_gimple gs)
> >  {
> > -  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
> > +  return gs->code == GIMPLE_OMP_SINGLE;
> > +}
> > +
> > +template <>
> > +template <>
> > +inline bool
> > +is_a_helper <const gimple_statement_omp_teams>::test (const_gimple gs)
> > +{
> > +  return gs->code == GIMPLE_OMP_TEAMS;
> >  }
> >  
> >  template <>
> > @@ -1766,9 +1913,9 @@ gimple_omp_return_nowait_p (const_gimple g)
> >  static inline void
> >  gimple_omp_return_set_lhs (gimple g, tree lhs)
> >  {
> > -  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> > -    as_a <gimple_statement_omp_atomic_store> (g);
> > -  omp_atomic_store_stmt->val = lhs;
> > +  gimple_statement_omp_return *omp_return_stmt =
> > +    as_a <gimple_statement_omp_return> (g);
> > +  omp_return_stmt->val = lhs;
> >  }
> >  
> >  
> > @@ -1777,9 +1924,9 @@ gimple_omp_return_set_lhs (gimple g, tree lhs)
> >  static inline tree
> >  gimple_omp_return_lhs (const_gimple g)
> >  {
> > -  const gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> > -    as_a <const gimple_statement_omp_atomic_store> (g);
> > -  return omp_atomic_store_stmt->val;
> > +  const gimple_statement_omp_return *omp_return_stmt =
> > +    as_a <const gimple_statement_omp_return> (g);
> > +  return omp_return_stmt->val;
> >  }
> >  
> >  
> > @@ -1788,9 +1935,9 @@ gimple_omp_return_lhs (const_gimple g)
> >  static inline tree *
> >  gimple_omp_return_lhs_ptr (gimple g)
> >  {
> > -  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> > -    as_a <gimple_statement_omp_atomic_store> (g);
> > -  return &omp_atomic_store_stmt->val;
> > +  gimple_statement_omp_return *omp_return_stmt =
> > +    as_a <gimple_statement_omp_return> (g);
> > +  return &omp_return_stmt->val;
> >  }
> >  
> >  
> > @@ -3793,9 +3940,9 @@ gimple_phi_arg_has_location (gimple gs, size_t i)
> >  static inline int
> >  gimple_resx_region (const_gimple gs)
> >  {
> > -  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > -    as_a <const gimple_statement_eh_ctrl> (gs);
> > -  return eh_ctrl_stmt->region;
> > +  const gimple_statement_resx *resx_stmt =
> > +    as_a <const gimple_statement_resx> (gs);
> > +  return resx_stmt->region;
> >  }
> >  
> >  /* Set REGION to be the region number for GIMPLE_RESX GS.  */
> > @@ -3803,9 +3950,8 @@ gimple_resx_region (const_gimple gs)
> >  static inline void
> >  gimple_resx_set_region (gimple gs, int region)
> >  {
> > -  gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > -    as_a <gimple_statement_eh_ctrl> (gs);
> > -  eh_ctrl_stmt->region = region;
> > +  gimple_statement_resx *resx_stmt = as_a <gimple_statement_resx> (gs);
> > +  resx_stmt->region = region;
> >  }
> >  
> >  /* Return the region number for GIMPLE_EH_DISPATCH GS.  */
> > @@ -3813,9 +3959,9 @@ gimple_resx_set_region (gimple gs, int region)
> >  static inline int
> >  gimple_eh_dispatch_region (const_gimple gs)
> >  {
> > -  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > -    as_a <const gimple_statement_eh_ctrl> (gs);
> > -  return eh_ctrl_stmt->region;
> > +  const gimple_statement_eh_dispatch *eh_dispatch_stmt =
> > +    as_a <const gimple_statement_eh_dispatch> (gs);
> > +  return eh_dispatch_stmt->region;
> >  }
> >  
> >  /* Set REGION to be the region number for GIMPLE_EH_DISPATCH GS.  */
> > @@ -3823,9 +3969,9 @@ gimple_eh_dispatch_region (const_gimple gs)
> >  static inline void
> >  gimple_eh_dispatch_set_region (gimple gs, int region)
> >  {
> > -  gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > -    as_a <gimple_statement_eh_ctrl> (gs);
> > -  eh_ctrl_stmt->region = region;
> > +  gimple_statement_eh_dispatch *eh_dispatch_stmt =
> > +    as_a <gimple_statement_eh_dispatch> (gs);
> > +  eh_dispatch_stmt->region = region;
> >  }
> >  
> >  /* Return the number of labels associated with the switch statement GS.  */
> > @@ -4663,9 +4809,9 @@ gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
> >  static inline tree
> >  gimple_omp_taskreg_clauses (const_gimple gs)
> >  {
> > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <const gimple_statement_omp_parallel> (gs);
> > -  return omp_parallel_stmt->clauses;
> > +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <const gimple_statement_omp_taskreg> (gs);
> > +  return omp_taskreg_stmt->clauses;
> >  }
> >  
> >  
> > @@ -4674,9 +4820,9 @@ gimple_omp_taskreg_clauses (const_gimple gs)
> >  static inline tree *
> >  gimple_omp_taskreg_clauses_ptr (gimple gs)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  return &omp_parallel_stmt->clauses;
> > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <gimple_statement_omp_taskreg> (gs);
> > +  return &omp_taskreg_stmt->clauses;
> >  }
> >  
> >  
> > @@ -4686,9 +4832,9 @@ gimple_omp_taskreg_clauses_ptr (gimple gs)
> >  static inline void
> >  gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  omp_parallel_stmt->clauses = clauses;
> > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <gimple_statement_omp_taskreg> (gs);
> > +  omp_taskreg_stmt->clauses = clauses;
> >  }
> >  
> >  
> > @@ -4697,9 +4843,9 @@ gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
> >  static inline tree
> >  gimple_omp_taskreg_child_fn (const_gimple gs)
> >  {
> > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <const gimple_statement_omp_parallel> (gs);
> > -  return omp_parallel_stmt->child_fn;
> > +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <const gimple_statement_omp_taskreg> (gs);
> > +  return omp_taskreg_stmt->child_fn;
> >  }
> >  
> >  /* Return a pointer to the child function used to hold the body of
> > @@ -4708,9 +4854,9 @@ gimple_omp_taskreg_child_fn (const_gimple gs)
> >  static inline tree *
> >  gimple_omp_taskreg_child_fn_ptr (gimple gs)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  return &omp_parallel_stmt->child_fn;
> > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <gimple_statement_omp_taskreg> (gs);
> > +  return &omp_taskreg_stmt->child_fn;
> >  }
> >  
> >  
> > @@ -4719,9 +4865,9 @@ gimple_omp_taskreg_child_fn_ptr (gimple gs)
> >  static inline void
> >  gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  omp_parallel_stmt->child_fn = child_fn;
> > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <gimple_statement_omp_taskreg> (gs);
> > +  omp_taskreg_stmt->child_fn = child_fn;
> >  }
> >  
> >  
> > @@ -4731,9 +4877,9 @@ gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
> >  static inline tree
> >  gimple_omp_taskreg_data_arg (const_gimple gs)
> >  {
> > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <const gimple_statement_omp_parallel> (gs);
> > -  return omp_parallel_stmt->data_arg;
> > +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <const gimple_statement_omp_taskreg> (gs);
> > +  return omp_taskreg_stmt->data_arg;
> >  }
> >  
> >  
> > @@ -4742,9 +4888,9 @@ gimple_omp_taskreg_data_arg (const_gimple gs)
> >  static inline tree *
> >  gimple_omp_taskreg_data_arg_ptr (gimple gs)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  return &omp_parallel_stmt->data_arg;
> > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <gimple_statement_omp_taskreg> (gs);
> > +  return &omp_taskreg_stmt->data_arg;
> >  }
> >  
> >  
> > @@ -4753,9 +4899,9 @@ gimple_omp_taskreg_data_arg_ptr (gimple gs)
> >  static inline void
> >  gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  omp_parallel_stmt->data_arg = data_arg;
> > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > +    as_a <gimple_statement_omp_taskreg> (gs);
> > +  omp_taskreg_stmt->data_arg = data_arg;
> >  }
> >  
> >  
> > @@ -4896,9 +5042,9 @@ gimple_omp_single_set_clauses (gimple gs, tree clauses)
> >  static inline tree
> >  gimple_omp_target_clauses (const_gimple gs)
> >  {
> > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <const gimple_statement_omp_parallel> (gs);
> > -  return omp_parallel_stmt->clauses;
> > +  const gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <const gimple_statement_omp_target> (gs);
> > +  return omp_target_stmt->clauses;
> >  }
> >  
> >  
> > @@ -4907,9 +5053,9 @@ gimple_omp_target_clauses (const_gimple gs)
> >  static inline tree *
> >  gimple_omp_target_clauses_ptr (gimple gs)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  return &omp_parallel_stmt->clauses;
> > +  gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <gimple_statement_omp_target> (gs);
> > +  return &omp_target_stmt->clauses;
> >  }
> >  
> >  
> > @@ -4918,9 +5064,9 @@ gimple_omp_target_clauses_ptr (gimple gs)
> >  static inline void
> >  gimple_omp_target_set_clauses (gimple gs, tree clauses)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  omp_parallel_stmt->clauses = clauses;
> > +  gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <gimple_statement_omp_target> (gs);
> > +  omp_target_stmt->clauses = clauses;
> >  }
> >  
> >  
> > @@ -4950,9 +5096,9 @@ gimple_omp_target_set_kind (gimple g, int kind)
> >  static inline tree
> >  gimple_omp_target_child_fn (const_gimple gs)
> >  {
> > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <const gimple_statement_omp_parallel> (gs);
> > -  return omp_parallel_stmt->child_fn;
> > +  const gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <const gimple_statement_omp_target> (gs);
> > +  return omp_target_stmt->child_fn;
> >  }
> >  
> >  /* Return a pointer to the child function used to hold the body of
> > @@ -4961,9 +5107,9 @@ gimple_omp_target_child_fn (const_gimple gs)
> >  static inline tree *
> >  gimple_omp_target_child_fn_ptr (gimple gs)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  return &omp_parallel_stmt->child_fn;
> > +  gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <gimple_statement_omp_target> (gs);
> > +  return &omp_target_stmt->child_fn;
> >  }
> >  
> >  
> > @@ -4972,9 +5118,9 @@ gimple_omp_target_child_fn_ptr (gimple gs)
> >  static inline void
> >  gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  omp_parallel_stmt->child_fn = child_fn;
> > +  gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <gimple_statement_omp_target> (gs);
> > +  omp_target_stmt->child_fn = child_fn;
> >  }
> >  
> >  
> > @@ -4984,9 +5130,9 @@ gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
> >  static inline tree
> >  gimple_omp_target_data_arg (const_gimple gs)
> >  {
> > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <const gimple_statement_omp_parallel> (gs);
> > -  return omp_parallel_stmt->data_arg;
> > +  const gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <const gimple_statement_omp_target> (gs);
> > +  return omp_target_stmt->data_arg;
> >  }
> >  
> >  
> > @@ -4995,9 +5141,9 @@ gimple_omp_target_data_arg (const_gimple gs)
> >  static inline tree *
> >  gimple_omp_target_data_arg_ptr (gimple gs)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  return &omp_parallel_stmt->data_arg;
> > +  gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <gimple_statement_omp_target> (gs);
> > +  return &omp_target_stmt->data_arg;
> >  }
> >  
> >  
> > @@ -5006,9 +5152,9 @@ gimple_omp_target_data_arg_ptr (gimple gs)
> >  static inline void
> >  gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
> >  {
> > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > -    as_a <gimple_statement_omp_parallel> (gs);
> > -  omp_parallel_stmt->data_arg = data_arg;
> > +  gimple_statement_omp_target *omp_target_stmt =
> > +    as_a <gimple_statement_omp_target> (gs);
> > +  omp_target_stmt->data_arg = data_arg;
> >  }
> >  
> >  
> > @@ -5017,9 +5163,9 @@ gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
> >  static inline tree
> >  gimple_omp_teams_clauses (const_gimple gs)
> >  {
> > -  const gimple_statement_omp_single *omp_single_stmt =
> > -    as_a <const gimple_statement_omp_single> (gs);
> > -  return omp_single_stmt->clauses;
> > +  const gimple_statement_omp_teams *omp_teams_stmt =
> > +    as_a <const gimple_statement_omp_teams> (gs);
> > +  return omp_teams_stmt->clauses;
> >  }
> >  
> >  
> > @@ -5028,9 +5174,9 @@ gimple_omp_teams_clauses (const_gimple gs)
> >  static inline tree *
> >  gimple_omp_teams_clauses_ptr (gimple gs)
> >  {
> > -  gimple_statement_omp_single *omp_single_stmt =
> > -    as_a <gimple_statement_omp_single> (gs);
> > -  return &omp_single_stmt->clauses;
> > +  gimple_statement_omp_teams *omp_teams_stmt =
> > +    as_a <gimple_statement_omp_teams> (gs);
> > +  return &omp_teams_stmt->clauses;
> >  }
> >  
> >  
> > @@ -5039,9 +5185,9 @@ gimple_omp_teams_clauses_ptr (gimple gs)
> >  static inline void
> >  gimple_omp_teams_set_clauses (gimple gs, tree clauses)
> >  {
> > -  gimple_statement_omp_single *omp_single_stmt =
> > -    as_a <gimple_statement_omp_single> (gs);
> > -  omp_single_stmt->clauses = clauses;
> > +  gimple_statement_omp_teams *omp_teams_stmt =
> > +    as_a <gimple_statement_omp_teams> (gs);
> > +  omp_teams_stmt->clauses = clauses;
> >  }
> >  
> >  
> > diff --git a/gcc/gsstruct.def b/gcc/gsstruct.def
> > index 91738f4..82f1f52 100644
> > --- a/gcc/gsstruct.def
> > +++ b/gcc/gsstruct.def
> > @@ -43,11 +43,11 @@ DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false)
> >  DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
> >  DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false)
> >  DEFGSSTRUCT(GSS_OMP_FOR, gimple_statement_omp_for, false)
> > -DEFGSSTRUCT(GSS_OMP_PARALLEL, gimple_statement_omp_parallel, false)
> > +DEFGSSTRUCT(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout, false)
> >  DEFGSSTRUCT(GSS_OMP_TASK, gimple_statement_omp_task, false)
> >  DEFGSSTRUCT(GSS_OMP_SECTIONS, gimple_statement_omp_sections, false)
> > -DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_statement_omp_single, false)
> > +DEFGSSTRUCT(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout, false)
> >  DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false)
> >  DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false)
> > -DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false)
> > +DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store, false)
> >  DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false)
> 
> 
> Grüße,
>  Thomas
Thomas Schwinge July 29, 2014, 8:07 a.m. UTC | #6
Hi!

On Wed, 23 Jul 2014 20:54:24 -0400, David Malcolm <dmalcolm@redhat.com> wrote:
> On Wed, 2014-07-23 at 15:00 +0200, Thomas Schwinge wrote:
> > In context of adding support for OpenACC, next to the existing
> > GIMPLE_OMP_TARGET (quoting from gcc/gimple.def and gcc/gimple.h):
> > 
> >     DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)
> > 
> >     /* GIMPLE_OMP_TARGET */
> >     struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> >       gimple_statement_omp_target : public gimple_statement_omp_parallel_layout
> >     {
> >         /* No extra fields; adds invariant:
> >              stmt->code == GIMPLE_OMP_TARGET.  */
> >     };
> > 
> > ..., we're adding additional GIMPLE codes:
> > 
> >     DEFGSCODE(GIMPLE_OACC_KERNELS, "gimple_oacc_kernels", GSS_OMP_PARALLEL_LAYOUT)
> > 
> >     /* GIMPLE_OACC_KERNELS */
> >     struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> >       gimple_statement_oacc_kernels : public gimple_statement_omp_parallel_layout
> >     {
> >         /* No extra fields; adds invariant:
> >              stmt->code == GIMPLE_OACC_KERNELS.  */
> >     };
> > 
> >     DEFGSCODE(GIMPLE_OACC_PARALLEL, "gimple_oacc_parallel", GSS_OMP_PARALLEL_LAYOUT)
> > 
> >     /* GIMPLE_OACC_PARALLEL */
> >     struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> >       gimple_statement_oacc_parallel : public gimple_statement_omp_parallel_layout
> >     {
> >         /* No extra fields; adds invariant:
> >              stmt->code == GIMPLE_OACC_PARALLEL.  */
> >     };
> > 
> > As you can see, all these codes share the same layout,
> > GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout.
> > 
> > Given this, I'd like to better understand the following:
> > 
> > On Mon, 25 Nov 2013 10:35:18 -0500, David Malcolm <dmalcolm@redhat.com> wrote:
> > > On Thu, 2013-11-21 at 18:03 -0500, Andrew MacLeod wrote:
> > > > On 11/21/2013 05:42 PM, Jakub Jelinek wrote:
> > > > > On Thu, Nov 21, 2013 at 03:24:55PM -0700, Jeff Law wrote:
> > > > >> On 11/21/13 15:19, Jakub Jelinek wrote:
> > > > >>> On Mon, Nov 18, 2013 at 03:25:52PM -0500, David Malcolm wrote:
> > > > >>>>> So is there some reason the GIMPLE_CHECK was left in here rather than
> > > > >>>>> doing the downcasting?  This happens in other places.
> > > > >>> Note that the changes removed tons of checks that IMHO were desirable.
> > > > >>> The as_a that replaced those checks e.g. allows 3 different gimple codes,
> > > > >>> while previously only one was allowed, this is both more expensive for
> > > > >>> --enable-checking=yes, and allows one to use inline wrappers e.g.
> > > > >>> gimple_omp_parallel_something on GIMPLE_OMP_TASK etc.
> > > > >> Can you give a couple examples, please?
> > > > > I mean e.g.
> > > > > gimple_omp_parallel_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > > > gimple_omp_taskreg_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > > > gimple_omp_target_{,set_}{clauses,child_fn,data_arg}{,_ptr}
> > > > > gimple_omp_teams_{,set_}clauses{,_ptr}
> > > > > gimple_omp_return_{,set_}lhs{,_ptr}
> > > > > gimple_omp_atomic_store_{,set_}val{,_ptr}
> > > > > gimple_resx_{,set_}region
> > > > > gimple_eh_dispatch_{,set_}region
> > 
> > We (have to) add the whole fleet of
> > gimple_oacc_{kernels,parallel}_{clauses,...} accessors as well as new
> > is_a_helper for {,const} gimple_statement_oacc_{kernels,parallel}.
> > 
> > > > Why does  is_a_helper <gimple_statement_omp_parallel>::test allow 
> > > > anything other than a GIMPLE_OMP_PARALLEL..?  That seems wrong to me. 
> > > > should just be the one check.
> > > > 
> > > > gimple_omp_taskreg and other routines "sharing" that helper should have 
> > > > their own helper and only check the one code.. thats is whole point to 
> > > > remain at least codegen neutral in these cases and provide correct 
> > > > checking.   The fact that they may happen to share the same underlying 
> > > > structure is irrelevant.
> > > > 
> > > > I also think this is wrong.
> > > 
> > > Mea culpa.  Unfortunately I made a conceptual error during the
> > > conversion (the worst kind of error).  I misunderstood the relationships
> > > between the various OMP statements: there (mostly) aren't any, but the
> > > sharing of structures for layout made me think there were.
> > > 
> > > Attached is a patch, successfully bootstrapped&regtested on
> > > x86_64-unknown-linux-gnu, which I believe reinstates the checked-build
> > > behaviors from before r205034 (and that the unchecked-build behaviors
> > > were not affected by that commit and likewise are not by this patch).
> > > 
> > > As I understand it, there are almost no "is-a" relationships between the
> > > various omp statement types, some of them just happen to share layouts.
> > > The exception is that the various gimple_omp_taskreg_* accessors accept
> > > either codes GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK and so an
> > > "omp_taskreg" is a concept, of which OMP_PARALLEL and OMP_TASK have an
> > > is-a relationship.
> > 
> > Admittedly, there is no is-a relationship between these, but yet,
> > GIMPLE_OMP_TARGET as well as the new GIMPLE_OACC_KERNELS and
> > GIMPLE_OACC_PARALLEL can share a lot of code, but, for example, where
> > previously gimple_omp_target_set_child_fn or gimple_omp_target_clauses
> > have been used, I now find myself writing code such as:
> > 
> >       void (*gimple_omp_set_child_fn) (gimple, tree);
> >       tree (*gimple_omp_clauses) (const_gimple);
> >       switch (gimple_code (stmt))
> >         {
> >         case GIMPLE_OACC_KERNELS:
> >           gimple_omp_set_child_fn = gimple_oacc_kernels_set_child_fn;
> >           gimple_omp_clauses = gimple_oacc_kernels_clauses;
> >           break;
> >         case GIMPLE_OACC_PARALLEL:
> >           gimple_omp_set_child_fn = gimple_oacc_parallel_set_child_fn;
> >           gimple_omp_clauses = gimple_oacc_parallel_clauses;
> >           break;
> >         case GIMPLE_OMP_TARGET:
> >           gimple_omp_set_child_fn = gimple_omp_target_set_child_fn;
> >           gimple_omp_clauses = gimple_omp_target_clauses;
> >           break;
> >         default:
> >           gcc_unreachable ();
> >         }
> > 
> > ..., only that I can then in the following use a unified interface for
> > setting the child function or getting access to the clauses.
> 
> Hmmmm.   What does the above code do, and is that pattern happening
> repeatedly?  Given the above it sounds like we may need these types to
> inherit from a common parent class ("gimple_something"), and for the
> parent to provide:
>  gimple_something_set_child_fn
>  gimple_something_clauses

Yes, that seems reasonable to me.  And, isn't that base class basically
the ...

> > What you can see here is that I first look at the GIMPLE code, and use
> > that to determine the appropritate accessor functions.  I have to do that
> > because these specific accessor functions then again would like to check
> > the respective GIMPLE code -- which I have just checked in the code
> > quoted above.  Instead, I'd rather like layout-specific accessor
> > functions, such as gimple_omp_parallel_layout_set_child_fn or
> > gimple_omp_parallel_layout_clauses.

... gimple_omp_parallel_layout class that I (sort of) proposed here?
(And no doubt it could do with a more descriptive name, which is, hmm...)

> BTW I have an 89-patch patch kit that strengthens the params to gimple
> accessors, requiring appropriate subclasses, and eliminating the code
> checks; see e.g.:
> https://gcc.gnu.org/ml/gcc-patches/2014-04/msg01159.html
> This patch kit was approved, but I was asked to hold off committing it
> to trunk until 4.9.1 was out, and also to investigate some renamings, so
> it's been in a "holding pattern" for a while.
> 
> So we'll need to incorporate whatever we do for OpenACC into those
> patches (or vice versa).

Every few weeks I merge from trunk into gomp-4_0-branch, so I can then
take care of this; I understand the changes will be rather "mechanic".

> FWIW, I was never particularly fond of the name
> "gimple_omp_parallel_layout"; IIRC it was necessary as a way of
> expressing that we're using a particular data layout
> (GSS_OMP_PARALLEL_LAYOUT), and to be different from the specific
> concrete subclass used for code GIMPLE_OMP_PARALLEL.

Right.  I however also have difficulties coming up with a better name.

> > Is this a reasonable wish, or am I misunderstanding what all this
> > "boilerplate" code for GIMPLE code checking is meant to achieve?  (It's
> > entirely possible that I'm misunderstanding something...)  ;-)
> > 
> > For example, might this suggest that our new GIMPLE code should in fact
> > be proper sub-codes of GIMPLE_OMP_TARGET?  Hmm...
> 
> Right now, the relevant part of the class hierarchy looks like this
> (from doc/gimple.texi):
>      + gimple_statement_omp
>      |   |    layout: GSS_OMP.  Used for code GIMPLE_OMP_SECTION
>      |   |
>      |   + gimple_statement_omp_parallel_layout
>      |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
>      |   |   |
>      |   |   + gimple_statement_omp_taskreg
>      |   |   |   |
>      |   |   |   + gimple_statement_omp_parallel
>      |   |   |   |        code: GIMPLE_OMP_PARALLEL
>      |   |   |   |
>      |   |   |   + gimple_statement_omp_task
>      |   |   |            code: GIMPLE_OMP_TASK
>      |   |   |
>      |   |   + gimple_statement_omp_target
>      |   |            code: GIMPLE_OMP_TARGET
> 
> 
> Given the code fragment you posted above, where you want to work on each
> of GIMPLE_OACC_KERNELS, GIMPLE_OACC_PARALLEL, GIMPLE_OMP_TARGET to get
> at "set_child_fn" and the "clauses", it seems to me that you want the
> new classes to inherit from either gimple_statement_omp_parallel_layout
> (and have omp_target inherit from it) or from
> gimple_statement_omp_target; the accessors could then work on that
> specific new class.

I think conceptually,
gimple_statement_omp_parallel_layout/GSS_OMP_PARALLEL_LAYOUT would be the
base class.

> I suspect I don't yet have enough knowledge of OpenACC and OpenMP to
> propose a good name for the class, but for the former approach, the new
> class hierarchy might look like this:
>      + gimple_statement_omp
>      |   |    layout: GSS_OMP.  Used for code GIMPLE_OMP_SECTION
>      |   |
>      |   + gimple_statement_omp_parallel_layout
>      |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
>      |   |   |
>      |   |   + gimple_statement_omp_taskreg
>      |   |   |   |
>      |   |   |   + gimple_statement_omp_parallel
>      |   |   |   |        code: GIMPLE_OMP_PARALLEL
>      |   |   |   |
>      |   |   |   + gimple_statement_omp_task
>      |   |   |            code: GIMPLE_OMP_TASK
>      |   |   |
>      |   |   + "gimple_something" <<< NEW CLASS GOES HERE?
>      |   |       |   
>      |   |       + gimple_statement_omp_target
>      |   |       |        code: GIMPLE_OMP_TARGET
>      |   |       |
>      |   |       + gimple_statement_oacc_kernels
>      |   |       |        code: GIMPLE_OACC_KERNELS
>      |   |       |
>      |   |       + gimple_statement_oacc_parallel
>      |   |                code: GIMPLE_OACC_PARALLEL
> 
> again, assuming that "gimple_something" is a meaningful concept, for the
> above to be sane.

Given that all of GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TASK,
GIMPLE_OMP_TARGET, GIMPLE_OACC_KERNELS, GIMPLE_OACC_PARALLEL have a (the
same) concept of clauses and a child_fn (see gcc/gimple.def), I assume
gimple_statement_omp_parallel_layout/GSS_OMP_PARALLEL_LAYOUT is where the
base class should be located.  And, the accessors for the clauses could
be moved up in the class hierarchy, as that is a concept that universally
applies to all GIMPLE_OMP_* (as well as GIMPLE_OACC_*).

> > And regardless of this, from someone who is still learning his share of
> > GCC internals, many, many thanks to you, Andrew and David (as well as
> > everyone else who's contributing, of course), for all the refactoring
> > work you're doing!  This does make the GCC code more accessible.  :-)
> 
> Thanks; hope the above was helpful

Yes, thanks!

> > (Follows full quote for reference.)
> > 
> > > Based on this, I've reworked the is_a_helper functions, eliminating
> > > almost all of the ones that accepted multiple codes.  The only ones that
> > > remain accepting multiple codes are those for:
> > > 
> > >   * gimple_statement_with_ops, which uses gimple_has_ops (gs), and for
> > >   * gimple_statement_with_memory_ops, which uses gimple_has_mem_ops
> > > (gs), plus
> > >   * a new class gimple_statement_omp_taskreg, which expresses the
> > > "either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK" condition, and becomes a
> > > parent struct for those.
> > > 
> > > I introduced some new structs to express the pre-existing layouts for
> > > GSS codes, and to distinguish them from structs that imply a specific
> > > GIMPLE_ code.
> > > For example,
> > >   gimple_statement_omp_atomic_store
> > > now requires that the code be GIMPLE_OMP_ATOMIC_STORE, but it was also
> > > the name of a layout, GSS_OMP_ATOMIC_STORE.  So I renamed these purely
> > > layout classes, so that there is now a
> > >   gimple_statement_omp_atomic_store_layout
> > > class for the corresponding GSS value, which I renamed to
> > >   GSS_OMP_ATOMIC_STORE_LAYOUT
> > > to make clear that this is just a layout: that although
> > > GIMPLE_OMP_RETURN happens to share the data layout of
> > > GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related - they now both
> > > inherit from the "_layout" class.
> > > 
> > > I'm not a fan of these "_layout" names, but I'm not sure what better to
> > > call them. Perhaps:
> > >    GSS_OMP_PARALLEL_LAYOUT     -> GSS_OMP_WITH_CLAUSES_CHILD_FN_DATA_ARG
> > >    GSS_OMP_SINGLE_LAYOUT       -> GSS_OMP_WITH_CLAUSES
> > >    GSS_OMP_ATOMIC_STORE_LAYOUT -> GSS_OMP_WITHOUT_SEQ_WITH_VAL
> > > with analogous names for the corresponding structs.
> > > 
> > > I added GTY tags for every class in the hierarchy, not just those that
> > > introduce a new layout, since gengtype only recognizes inheritance when
> > > supplied a "tag" option.  This leads to the GSS values appearing
> > > multiple times within the class hierarchy, which required a patch to
> > > gengtype, to prevent duplicate case labels in the generated switch
> > > statement.
> > > 
> > > I believe that this structure correctly reinstates the exact behavior
> > > from before the inheritance patch for the checked build, and that either
> > > way, the behavior in the unchecked build is the same.
> > > 
> > > Another approach to this would be to entirely eliminate these shared
> > > layout types, going purely with the conceptual is-a relationships
> > > between the types, say, by replacing the gengtype switch on GSS_ value
> > > with a switch on GIMPLE_ code.  Given that this might affect the speed
> > > of GC (bigger switch statements), I went with the relatively more
> > > conservative change.
> > > 
> > > Successfully bootstrapped&regtested on x86_64-unknown-linux-gnu.
> > > 
> > > OK for trunk?
> > > 
> > > Sorry again for breaking this.
> > > 
> > > Here's an ASCII art inheritance diagram, showing the relationships
> > > between structs, GSS_ values (layouts) and GIMPLE_ values (codes) - as I
> > > see them.  If I'm still misunderstanding something, sorry, please let me
> > > know.  Should this diagram live in gimple.h?
> > > +- gimple_statement_base
> > >      |    layout: GSS_BASE.  4 codes use this layout.
> > >      |
> > >      + gimple_statement_with_ops_base
> > >      |   |    (no GSS layout)
> > >      |   |
> > >      |   + gimple_statement_with_ops
> > >      |   |        layout: GSS_WITH_OPS.   5 codes use this layout.
> > >      |   |
> > >      |   + gimple_statement_with_memory_ops_base
> > >      |       |    layout: GSS_WITH_MEM_OPS_BASE
> > >      |       |
> > >      |       + gimple_statement_with_memory_ops
> > >      |       |        layout: GSS_WITH_MEM_OPS.
> > >      |       |        Used by codes GIMPLE_ASSIGN and GIMPLE_RETURN.
> > >      |       |
> > >      |       + gimple_statement_call
> > >      |       |        layout: GSS_CALL, code: GIMPLE_CALL
> > >      |       |
> > >      |       + gimple_statement_asm
> > >      |       |        layout: GSS_ASM, code: GIMPLE_ASM
> > >      |       |
> > >      |       + gimple_statement_transaction
> > >      |                layout: GSS_TRANSACTION, code: GIMPLE_TRANSACTION
> > >      |
> > >      + gimple_statement_omp
> > >      |   |    layout: GSS_OMP
> > >      |   |
> > >      |   + gimple_statement_omp_critical
> > >      |   |        layout: GSS_OMP_CRITICAL, code: GIMPLE_OMP_CRITICAL
> > >      |   |
> > >      |   + gimple_statement_omp_for
> > >      |   |        layout: GSS_OMP_FOR, code: GIMPLE_OMP_FOR
> > >      |   |
> > >      |   + gimple_statement_omp_parallel_layout
> > >      |   |   |    layout: GSS_OMP_PARALLEL_LAYOUT
> > >      |   |   |
> > >      |   |   + gimple_statement_omp_taskreg
> > >      |   |   |   |
> > >      |   |   |   + gimple_statement_omp_parallel
> > >      |   |   |   |        code: GIMPLE_OMP_PARALLEL
> > >      |   |   |   |
> > >      |   |   |   + gimple_statement_omp_task
> > >      |   |   |            code: GIMPLE_OMP_TASK
> > >      |   |   |
> > >      |   |   + gimple_statement_omp_target
> > >      |   |            code: GIMPLE_OMP_TARGET
> > >      |   |
> > >      |   + gimple_statement_omp_sections
> > >      |   |        layout: GSS_OMP_SECTIONS, code: GIMPLE_OMP_SECTIONS
> > >      |   |
> > >      |   + gimple_statement_omp_single_layout
> > >      |       |    layout: GSS_OMP_SINGLE_LAYOUT
> > >      |       |
> > >      |       + gimple_statement_omp_single
> > >      |       |        code: GIMPLE_OMP_SINGLE
> > >      |       |
> > >      |       + gimple_statement_omp_teams
> > >      |                code: GIMPLE_OMP_TEAMS
> > >      |
> > >      + gimple_statement_bind
> > >      |        layout: GSS_BIND, code: GIMPLE_BIND
> > >      |
> > >      + gimple_statement_catch
> > >      |        layout: GSS_CATCH, code: GIMPLE_CATCH
> > >      |
> > >      + gimple_statement_eh_filter
> > >      |        layout: GSS_EH_FILTER, code: GIMPLE_EH_FILTER
> > >      |
> > >      + gimple_statement_eh_else
> > >      |        layout: GSS_EH_ELSE, code: GIMPLE_EH_ELSE
> > >      |
> > >      + gimple_statement_eh_mnt
> > >      |        layout: GSS_EH_MNT, code: GIMPLE_EH_MUST_NOT_THROW
> > >      |
> > >      + gimple_statement_phi
> > >      |        layout: GSS_PHI, code: GIMPLE_PHI
> > >      |
> > >      + gimple_statement_eh_ctrl
> > >      |   |    layout: GSS_EH_CTRL
> > >      |   |
> > >      |   + gimple_statement_resx
> > >      |   |        code: GIMPLE_RESX
> > >      |   |
> > >      |   + gimple_statement_eh_dispatch
> > >      |            code: GIMPLE_EH_DISPATCH
> > >      |
> > >      + gimple_statement_try
> > >      |        layout: GSS_TRY, code: GIMPLE_TRY
> > >      |
> > >      + gimple_statement_wce
> > >      |        layout: GSS_WCE, code: GIMPLE_WITH_CLEANUP_EXPR
> > >      |
> > >      + gimple_statement_omp_continue
> > >      |        layout: GSS_OMP_CONTINUE, code: GIMPLE_OMP_CONTINUE
> > >      |
> > >      + gimple_statement_omp_atomic_load
> > >      |        layout: GSS_OMP_ATOMIC_LOAD, code: GIMPLE_OMP_ATOMIC_LOAD
> > >      |
> > >      + gimple_statement_omp_atomic_store_layout
> > >          |    layout: GSS_OMP_ATOMIC_STORE_LAYOUT,
> > >          |    code: GIMPLE_OMP_ATOMIC_STORE
> > >          |
> > >          + gimple_statement_omp_atomic_store
> > >          |        code: GIMPLE_OMP_ATOMIC_STORE
> > >          |
> > >          + gimple_statement_omp_return
> > >                   code: GIMPLE_OMP_RETURN
> > > 
> > > 
> > > commit 9a0c36081b3baecfc16a8500464df3a94c8dd145
> > > Author: David Malcolm <dmalcolm@redhat.com>
> > > Date:   Thu Nov 21 21:46:58 2013 -0500
> > > 
> > >     Fix as_a<> helpers for gimple
> > >     
> > >     	* gengtype.c (struct seen_tag): New.
> > >     	(already_seen_tag): New.
> > >     	(mark_tag_as_seen): New.
> > >     	(walk_subclasses): Support having multiple subclasses using the
> > >     	same tag by tracking which tags have already been seen, and using
> > >     	this to avoid adding duplicate cases to the "switch" statement.
> > >     	The call to already_seen_tag introduces an O(N^2) when running
> > >     	gengtype on N, the number of tags, due to the repeated linear
> > >     	search, but currently max(N) is relatively small (the number of
> > >     	GSS codes, which is 26).
> > >     	(walk_type): Pass in a seen_tag for use by the walk_subclasses
> > >     	recursion.
> > >     
> > >     	* gimple.def (GIMPLE_OMP_ATOMIC_STORE, GIMPLE_OMP_RETURN): Rename
> > >     	underlying GSS values for these codes (from GSS_OMP_ATOMIC_STORE to
> > >     	GSS_OMP_ATOMIC_STORE_LAYOUT) to make clear that although
> > >     	GIMPLE_OMP_RETURN happens to share the data layout of
> > >     	GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related.
> > >     	(GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET): Likewise, rename
> > >     	underlying GSS value from GSS_OMP_PARALLEL to
> > >     	GSS_OMP_PARALLEL_LAYOUT to make clear that these gimple codes are
> > >     	not directly related; they merely share in-memory layout.
> > >     	(GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS): Likewise, rename GSS values
> > >     	for these two codes from GSS_OMP_SINGLE to GSS_OMP_SINGLE_LAYOUT.
> > >     
> > >     	* gsstruct.def (GSS_OMP_PARALLEL, gimple_statement_omp_parallel):
> > >     	Rename to...
> > >     	(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout):
> > >     	...these.
> > >     	(GSS_OMP_SINGLE, gimple_statement_omp_single): Rename to...
> > >     	(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout):
> > >     	...these.
> > >     	(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store): Rename
> > >     	to...
> > >     	(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store):
> > >     	...these.
> > >     
> > >     	* gimple.h (gimple_statement_resx): New subclass of
> > >     	gimple_statement_eh_ctrl, with the invariant that
> > >     	stmt->code == GIMPLE_RESX.
> > >     	(gimple_statement_eh_dispatch): New subclass of
> > >     	gimple_statement_eh_ctrl, with the invariant that
> > >     	stmt->code == GIMPLE_EH_DISPATH.
> > >     
> > >     	(gimple_statement_omp_parallel): The existing class expressed
> > >     	a layout (GSS_OMP_PARALLEL), but the codes with that layout
> > >     	are not all related, so it makes more sense for this class to
> > >     	express a *code* (GIMPLE_OMP_PARALLEL).  GSS_OMP_PARALLEL has
> > >     	been renamed to GSS_OMP_PARALLEL_LAYOUT to express this, so
> > >     	rename the existing gimple_statement_omp_parallel class to...
> > >     	(gimple_statement_omp_parallel_layout): ...this, expressing
> > >     	a statement of structure layout GSS_OMP_PARALLEL_LAYOUT.
> > >     	(gimple_statement_omp_taskreg): New subclass of
> > >     	gimple_statement_omp_parallel_layout, expressing the invariant
> > >     	that the code is one of GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
> > >     	as used by the various gimple_omp_taskreg_ accessors.
> > >     	(gimple_statement_omp_parallel): Reintroduce this class, this time
> > >     	as a subclass of gimple_statement_omp_taskreg to express the
> > >     	invariant stmt->code == GIMPLE_OMP_PARALLEL.
> > >     	(gimple_statement_omp_target) New class, subclassing
> > >     	gimple_statement_omp_parallel_layout, to express the invariant
> > >     	stmt->code == GIMPLE_OMP_TARGET.
> > >     	(gimple_statement_omp_task): Update to inherit from
> > >     	gimple_statement_omp_taskreg rather than
> > >     	gimple_statement_omp_parallel.
> > >     
> > >     	(gimple_statement_omp_single): Rename to...
> > >     	(gimple_statement_omp_single_layout): ...this, expressing the
> > >     	invariant that the layout is GSS_OMP_SINGLE_LAYOUT.
> > >     	(gimple_statement_omp_single): ...and reintroduce this name as
> > >     	a subclass of gimple_statement_omp_single_layout, expressing
> > >     	the invariant that code == GIMPLE_OMP_SINGLE.
> > >     	(gimple_statement_omp_teams): New class, subclassing
> > >     	gimple_statement_omp_single_layout, for the code GIMPLE_OMP_TEAMS.
> > >     
> > >     	(gimple_statement_omp_atomic_store): Rename to...
> > >     	(gimple_statement_omp_atomic_store_layout): ...this, expressing
> > >     	the invariant that the layout is GSS_OMP_ATOMIC_STORE_LAYOUT.
> > >     	(gimple_statement_omp_atomic_store): ...and reintroduce this
> > >     	name as a subclass of gimple_statement_omp_atomic_store_layout
> > >     	with code == GIMPLE_OMP_ATOMIC_STORE.
> > >     	(gimple_statement_omp_return): New class, subclassing
> > >     	gimple_statement_omp_atomic_store_layout for the code
> > >     	GIMPLE_OMP_RETURN.
> > >     
> > >     	(is_a_helper <gimple_statement_eh_ctrl>::test): Delete.
> > >     	(is_a_helper <gimple_statement_resx>::test): New.
> > >     	(is_a_helper <gimple_statement_eh_dispatch>::test): New.
> > >     	(is_a_helper <gimple_statement_omp_atomic_store>::test): Only
> > >     	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
> > >     	(is_a_helper <gimple_statement_omp_return>::test): New.
> > >     	(is_a_helper <gimple_statement_omp_taskreg>::test): New.
> > >     	(is_a_helper <gimple_statement_omp_parallel>::test): Only check
> > >     	for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
> > >     	GIMPLE_OMP_TARGET.
> > >     	(is_a_helper <gimple_statement_omp_target>::test): New.
> > >     	(is_a_helper <gimple_statement_omp_single>::test): Only check
> > >     	for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
> > >     	(is_a_helper <gimple_statement_omp_teams>::test): New.
> > >     
> > >     	(is_a_helper <const gimple_statement_eh_ctrl>::test): Delete.
> > >     	(is_a_helper <const gimple_statement_resx>::test): New.
> > >     	(is_a_helper <const gimple_statement_eh_dispatch>::test): New.
> > >     	(is_a_helper <const gimple_statement_omp_atomic_store>::test): Only
> > >     	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
> > >     	(is_a_helper <const gimple_statement_omp_return>::test): New.
> > >     	(is_a_helper <const gimple_statement_omp_taskreg>::test): New.
> > >     	(is_a_helper <const gimple_statement_omp_parallel>::test): Only
> > >     	check for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
> > >     	GIMPLE_OMP_TARGET.
> > >     	(is_a_helper <const gimple_statement_omp_target>::test): New.
> > >     	(is_a_helper <const gimple_statement_omp_single>::test): Only
> > >     	check for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
> > >     	(is_a_helper <const gimple_statement_omp_teams>::test): New.
> > >     
> > >     	(gimple_omp_return_set_lhs, gimple_omp_return_lhs,
> > >     	gimple_omp_return_lhs_ptr): Replace bogus downcasts to
> > >     	gimple_statement_omp_atomic_store with downcasts to
> > >     	gimple_statement_omp_return, thus requiring that the code be
> > >     	GIMPLE_OMP_RETURN.
> > >     	(gimple_resx_region, gimple_resx_set_region): Replace bogus
> > >     	downcasts to gimple_statement_eh_ctrl with downcasts to
> > >     	gimple_statement_resx, thus requiring that the code be
> > >     	GIMPLE_RESX.
> > >     	(gimple_eh_dispatch_region, gimple_eh_dispatch_set_region):
> > >     	Replace bogus downcasts to const gimple_statement_eh_ctrl with
> > >     	downcasts to gimple_statement_eh_dispatch, thus requiring that
> > >     	the code be GIMPLE_EH_DISPATCH.
> > >     	(gimple_omp_taskreg_clauses, gimple_omp_taskreg_clauses_ptr)
> > >     	gimple_omp_taskreg_set_clauses, gimple_omp_taskreg_child_fn,
> > >     	gimple_omp_taskreg_child_fn_ptr, gimple_omp_taskreg_set_child_fn,
> > >     	gimple_omp_taskreg_data_arg, gimple_omp_taskreg_data_arg_ptr,
> > >     	gimple_omp_taskreg_set_data_arg): Replace bogus downcasts to
> > >     	gimple_statement_omp_parallel with downcasts to
> > >     	gimple_statement_omp_taskreg, thus requiring that the code be
> > >     	either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK.
> > >     	(gimple_omp_target_clauses, gimple_omp_target_clauses_ptr
> > >     	gimple_omp_target_set_clauses, gimple_omp_target_child_fn
> > >     	gimple_omp_target_child_fn_ptr, gimple_omp_target_set_child_fn
> > >     	gimple_omp_target_data_arg, gimple_omp_target_data_arg_ptr
> > >     	gimple_omp_target_set_data_arg): Replace bogus downcasts to
> > >     	gimple_statement_omp_parallel with downcasts to
> > >     	gimple_statement_omp_target, thus requiring that the code be
> > >     	GIMPLE_OMP_TARGET.
> > >     	(gimple_omp_teams_clauses, gimple_omp_teams_clauses_ptr
> > >     	gimple_omp_teams_set_clauses): Replace bogus downcasts to
> > >     	gimple_statement_omp_single with downcasts to
> > >     	gimple_statement_omp_teams, thus requiring that the code be
> > >     	GIMPLE_OMP_TEAMS.
> > >     
> > >     	* gimple.c (gimple_build_resx): Fix bogus as_a<> to use
> > >     	gimple_statement_resx.
> > >     	(gimple_build_eh_dispatch): Fix bogus as_a<> to use
> > >     	gimple_statement_eh_dispatch.
> > > 
> > > diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> > > index 86e9ca2..6e675cc 100644
> > > --- a/gcc/gengtype.c
> > > +++ b/gcc/gengtype.c
> > > @@ -2654,15 +2654,48 @@ get_string_option (options_p opt, const char *key)
> > >    return NULL;
> > >  }
> > >  
> > > +/* Machinery for avoiding duplicate tags within switch statements.  */
> > > +struct seen_tag
> > > +{
> > > +  const char *tag;
> > > +  struct seen_tag *next;
> > > +};
> > > +
> > > +int
> > > +already_seen_tag (struct seen_tag *seen_tags, const char *tag)
> > > +{
> > > +  /* Linear search, so O(n^2), but n is currently small.  */
> > > +  while (seen_tags)
> > > +    {
> > > +      if (!strcmp (seen_tags->tag, tag))
> > > +	return 1;
> > > +      seen_tags = seen_tags->next;
> > > +    }
> > > +  /* Not yet seen this tag. */
> > > +  return 0;
> > > +}
> > > +
> > > +void
> > > +mark_tag_as_seen (struct seen_tag **seen_tags, const char *tag)
> > > +{
> > > +  /* Add to front of linked list. */
> > > +  struct seen_tag *new_node = XCNEW (struct seen_tag);
> > > +  new_node->tag = tag;
> > > +  new_node->next = *seen_tags;
> > > +  *seen_tags = new_node;
> > > +}
> > > +
> > >  static void
> > > -walk_subclasses (type_p base, struct walk_type_data *d)
> > > +walk_subclasses (type_p base, struct walk_type_data *d,
> > > +		 struct seen_tag **seen_tags)
> > >  {
> > >    for (type_p sub = base->u.s.first_subclass; sub != NULL;
> > >         sub = sub->u.s.next_sibling_class)
> > >      {
> > >        const char *type_tag = get_string_option (sub->u.s.opt, "tag");
> > > -      if (type_tag)
> > > +      if (type_tag && !already_seen_tag (*seen_tags, type_tag))
> > >  	{
> > > +	  mark_tag_as_seen (seen_tags, type_tag);
> > >  	  oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
> > >  	  d->indent += 2;
> > >  	  oprintf (d->of, "%*s{\n", d->indent, "");
> > > @@ -2678,7 +2711,7 @@ walk_subclasses (type_p base, struct walk_type_data *d)
> > >  	  oprintf (d->of, "%*sbreak;\n", d->indent, "");
> > >  	  d->indent -= 2;
> > >  	}
> > > -      walk_subclasses (sub, d);
> > > +      walk_subclasses (sub, d, seen_tags);
> > >      }
> > >  }
> > >  
> > > @@ -3225,7 +3258,8 @@ walk_type (type_p t, struct walk_type_data *d)
> > >  	else if (desc)
> > >  	  {
> > >  	    /* Add cases to handle subclasses.  */
> > > -	    walk_subclasses (t, d);
> > > +	    struct seen_tag *tags = NULL;
> > > +	    walk_subclasses (t, d, &tags);
> > >  
> > >  	    /* Ensure that if someone forgets a "tag" option that we don't
> > >  	       silent fail to traverse that subclass's fields.  */
> > > diff --git a/gcc/gimple.c b/gcc/gimple.c
> > > index d48ca6b..2e45f37 100644
> > > --- a/gcc/gimple.c
> > > +++ b/gcc/gimple.c
> > > @@ -697,8 +697,8 @@ gimple_build_wce (gimple_seq cleanup)
> > >  gimple
> > >  gimple_build_resx (int region)
> > >  {
> > > -  gimple_statement_eh_ctrl *p =
> > > -    as_a <gimple_statement_eh_ctrl> (
> > > +  gimple_statement_resx *p =
> > > +    as_a <gimple_statement_resx> (
> > >        gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
> > >    p->region = region;
> > >    return p;
> > > @@ -747,8 +747,8 @@ gimple_build_switch (tree index, tree default_label, vec<tree> args)
> > >  gimple
> > >  gimple_build_eh_dispatch (int region)
> > >  {
> > > -  gimple_statement_eh_ctrl *p =
> > > -    as_a <gimple_statement_eh_ctrl> (
> > > +  gimple_statement_eh_dispatch *p =
> > > +    as_a <gimple_statement_eh_dispatch> (
> > >        gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
> > >    p->region = region;
> > >    return p;
> > > diff --git a/gcc/gimple.def b/gcc/gimple.def
> > > index 07370ae..ff1ef43 100644
> > > --- a/gcc/gimple.def
> > > +++ b/gcc/gimple.def
> > > @@ -221,7 +221,7 @@ DEFGSCODE(GIMPLE_NOP, "gimple_nop", GSS_BASE)
> > >  DEFGSCODE(GIMPLE_OMP_ATOMIC_LOAD, "gimple_omp_atomic_load",
> > >  	  GSS_OMP_ATOMIC_LOAD)
> > >  DEFGSCODE(GIMPLE_OMP_ATOMIC_STORE, "gimple_omp_atomic_store",
> > > -	  GSS_OMP_ATOMIC_STORE)
> > > +	  GSS_OMP_ATOMIC_STORE_LAYOUT)
> > >  
> > >  /* GIMPLE_OMP_CONTINUE marks the location of the loop or sections
> > >     iteration in partially lowered OpenMP code.  */
> > > @@ -300,7 +300,7 @@ DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered", GSS_OMP)
> > >     DATA_ARG is a local variable in the parent function containing data
> > >     to be shared with CHILD_FN.  This is used to implement all the data
> > >     sharing clauses.  */
> > > -DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
> > > +DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL_LAYOUT)
> > >  
> > >  /* GIMPLE_OMP_TASK <BODY, CLAUSES, CHILD_FN, DATA_ARG, COPY_FN,
> > >  		    ARG_SIZE, ARG_ALIGN> represents
> > > @@ -329,7 +329,7 @@ DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
> > >  DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK)
> > >  
> > >  /* OMP_RETURN marks the end of an OpenMP directive.  */
> > > -DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE)
> > > +DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
> > >  
> > >  /* OMP_SECTION <BODY> represents #pragma omp section.
> > >     BODY is the sequence of statements in the section body.  */
> > > @@ -351,7 +351,7 @@ DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch", GSS_BASE)
> > >  /* GIMPLE_OMP_SINGLE <BODY, CLAUSES> represents #pragma omp single
> > >     BODY is the sequence of statements inside the single section.
> > >     CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
> > > -DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
> > > +DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE_LAYOUT)
> > >  
> > >  /* GIMPLE_OMP_TARGET <BODY, CLAUSES, CHILD_FN> represents
> > >     #pragma omp target {,data,update}
> > > @@ -364,12 +364,12 @@ DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
> > >     DATA_ARG is a vec of 3 local variables in the parent function
> > >     containing data to be mapped to CHILD_FN.  This is used to
> > >     implement the MAP clauses.  */
> > > -DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL)
> > > +DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)
> > >  
> > >  /* GIMPLE_OMP_TEAMS <BODY, CLAUSES> represents #pragma omp teams
> > >     BODY is the sequence of statements inside the single section.
> > >     CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
> > > -DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE)
> > > +DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE_LAYOUT)
> > >  
> > >  /* GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction.
> > >  
> > > diff --git a/gcc/gimple.h b/gcc/gimple.h
> > > index 0eb23fc..0257576 100644
> > > --- a/gcc/gimple.h
> > > +++ b/gcc/gimple.h
> > > @@ -420,6 +420,20 @@ struct GTY((tag("GSS_EH_CTRL")))
> > >    int region;
> > >  };
> > >  
> > > +struct GTY((tag("GSS_EH_CTRL")))
> > > +  gimple_statement_resx : public gimple_statement_eh_ctrl
> > > +{
> > > +  /* No extra fields; adds invariant:
> > > +       stmt->code == GIMPLE_RESX.  */
> > > +};
> > > +
> > > +struct GTY((tag("GSS_EH_CTRL")))
> > > +  gimple_statement_eh_dispatch : public gimple_statement_eh_ctrl
> > > +{
> > > +  /* No extra fields; adds invariant:
> > > +       stmt->code == GIMPLE_EH_DISPATH.  */
> > > +};
> > > +
> > >  
> > >  /* GIMPLE_TRY */
> > >  
> > > @@ -547,10 +561,9 @@ struct GTY((tag("GSS_OMP_FOR")))
> > >  };
> > >  
> > >  
> > > -/* GIMPLE_OMP_PARALLEL */
> > > -
> > > -struct GTY((tag("GSS_OMP_PARALLEL")))
> > > -  gimple_statement_omp_parallel : public gimple_statement_omp
> > > +/* GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET */
> > > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > > +  gimple_statement_omp_parallel_layout : public gimple_statement_omp
> > >  {
> > >    /* [ WORD 1-7 ] : base class */
> > >  
> > > @@ -567,11 +580,35 @@ struct GTY((tag("GSS_OMP_PARALLEL")))
> > >    tree data_arg;
> > >  };
> > >  
> > > +/* GIMPLE_OMP_PARALLEL or GIMPLE_TASK */
> > > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > > +  gimple_statement_omp_taskreg : public gimple_statement_omp_parallel_layout
> > > +{
> > > +    /* No extra fields; adds invariant:
> > > +         stmt->code == GIMPLE_OMP_PARALLEL
> > > +	 || stmt->code == GIMPLE_OMP_TASK.  */
> > > +};
> > > +
> > > +
> > > +/* GIMPLE_OMP_PARALLEL */
> > > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > > +  gimple_statement_omp_parallel : public gimple_statement_omp_taskreg
> > > +{
> > > +    /* No extra fields; adds invariant:
> > > +         stmt->code == GIMPLE_OMP_PARALLEL.  */
> > > +};
> > > +
> > > +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
> > > +  gimple_statement_omp_target : public gimple_statement_omp_parallel_layout
> > > +{
> > > +    /* No extra fields; adds invariant:
> > > +         stmt->code == GIMPLE_OMP_TARGET.  */
> > > +};
> > >  
> > >  /* GIMPLE_OMP_TASK */
> > >  
> > >  struct GTY((tag("GSS_OMP_TASK")))
> > > -  gimple_statement_omp_task : public gimple_statement_omp_parallel
> > > +  gimple_statement_omp_task : public gimple_statement_omp_taskreg
> > >  {
> > >    /* [ WORD 1-10 ] : base class */
> > >  
> > > @@ -623,10 +660,10 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
> > >    tree control_use;
> > >  };
> > >  
> > > -/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS */
> > > +/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS */
> > >  
> > > -struct GTY((tag("GSS_OMP_SINGLE")))
> > > -  gimple_statement_omp_single : public gimple_statement_omp
> > > +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> > > +  gimple_statement_omp_single_layout : public gimple_statement_omp
> > >  {
> > >    /* [ WORD 1-7 ] : base class */
> > >  
> > > @@ -634,6 +671,20 @@ struct GTY((tag("GSS_OMP_SINGLE")))
> > >    tree clauses;
> > >  };
> > >  
> > > +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> > > +  gimple_statement_omp_single : public gimple_statement_omp_single_layout
> > > +{
> > > +    /* No extra fields; adds invariant:
> > > +         stmt->code == GIMPLE_OMP_SINGLE.  */
> > > +};
> > > +
> > > +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
> > > +  gimple_statement_omp_teams : public gimple_statement_omp_single_layout
> > > +{
> > > +    /* No extra fields; adds invariant:
> > > +         stmt->code == GIMPLE_OMP_TEAMS.  */
> > > +};
> > > +
> > >  
> > >  /* GIMPLE_OMP_ATOMIC_LOAD.
> > >     Note: This is based on gimple_statement_base, not g_s_omp, because g_s_omp
> > > @@ -651,8 +702,8 @@ struct GTY((tag("GSS_OMP_ATOMIC_LOAD")))
> > >  /* GIMPLE_OMP_ATOMIC_STORE.
> > >     See note on GIMPLE_OMP_ATOMIC_LOAD.  */
> > >  
> > > -struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
> > > -  gimple_statement_omp_atomic_store : public gimple_statement_base
> > > +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> > > +  gimple_statement_omp_atomic_store_layout : public gimple_statement_base
> > >  {
> > >    /* [ WORD 1-6 ] : base class */
> > >  
> > > @@ -660,6 +711,22 @@ struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
> > >    tree val;
> > >  };
> > >  
> > > +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> > > +  gimple_statement_omp_atomic_store :
> > > +    public gimple_statement_omp_atomic_store_layout
> > > +{
> > > +    /* No extra fields; adds invariant:
> > > +         stmt->code == GIMPLE_OMP_ATOMIC_STORE.  */
> > > +};
> > > +
> > > +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
> > > +  gimple_statement_omp_return :
> > > +    public gimple_statement_omp_atomic_store_layout
> > > +{
> > > +    /* No extra fields; adds invariant:
> > > +         stmt->code == GIMPLE_OMP_RETURN.  */
> > > +};
> > > +
> > >  /* GIMPLE_TRANSACTION.  */
> > >  
> > >  /* Bits to be stored in the GIMPLE_TRANSACTION subcode.  */
> > > @@ -742,9 +809,17 @@ is_a_helper <gimple_statement_catch>::test (gimple gs)
> > >  template <>
> > >  template <>
> > >  inline bool
> > > -is_a_helper <gimple_statement_eh_ctrl>::test (gimple gs)
> > > +is_a_helper <gimple_statement_resx>::test (gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_RESX;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <gimple_statement_eh_dispatch>::test (gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
> > > +  return gs->code == GIMPLE_EH_DISPATCH;
> > >  }
> > >  
> > >  template <>
> > > @@ -784,7 +859,15 @@ template <>
> > >  inline bool
> > >  is_a_helper <gimple_statement_omp_atomic_store>::test (gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
> > > +  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <gimple_statement_omp_return>::test (gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_RETURN;
> > >  }
> > >  
> > >  template <>
> > > @@ -814,9 +897,25 @@ is_a_helper <gimple_statement_omp_for>::test (gimple gs)
> > >  template <>
> > >  template <>
> > >  inline bool
> > > +is_a_helper <gimple_statement_omp_taskreg>::test (gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > >  is_a_helper <gimple_statement_omp_parallel>::test (gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
> > > +  return gs->code == GIMPLE_OMP_PARALLEL;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <gimple_statement_omp_target>::test (gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_TARGET;
> > >  }
> > >  
> > >  template <>
> > > @@ -832,7 +931,15 @@ template <>
> > >  inline bool
> > >  is_a_helper <gimple_statement_omp_single>::test (gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
> > > +  return gs->code == GIMPLE_OMP_SINGLE;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <gimple_statement_omp_teams>::test (gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_TEAMS;
> > >  }
> > >  
> > >  template <>
> > > @@ -910,9 +1017,17 @@ is_a_helper <const gimple_statement_catch>::test (const_gimple gs)
> > >  template <>
> > >  template <>
> > >  inline bool
> > > -is_a_helper <const gimple_statement_eh_ctrl>::test (const_gimple gs)
> > > +is_a_helper <const gimple_statement_resx>::test (const_gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
> > > +  return gs->code == GIMPLE_RESX;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <const gimple_statement_eh_dispatch>::test (const_gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_EH_DISPATCH;
> > >  }
> > >  
> > >  template <>
> > > @@ -936,7 +1051,15 @@ template <>
> > >  inline bool
> > >  is_a_helper <const gimple_statement_omp_atomic_store>::test (const_gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
> > > +  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <const gimple_statement_omp_return>::test (const_gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_RETURN;
> > >  }
> > >  
> > >  template <>
> > > @@ -966,9 +1089,25 @@ is_a_helper <const gimple_statement_omp_for>::test (const_gimple gs)
> > >  template <>
> > >  template <>
> > >  inline bool
> > > +is_a_helper <const gimple_statement_omp_taskreg>::test (const_gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > >  is_a_helper <const gimple_statement_omp_parallel>::test (const_gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
> > > +  return gs->code == GIMPLE_OMP_PARALLEL;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <const gimple_statement_omp_target>::test (const_gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_TARGET;
> > >  }
> > >  
> > >  template <>
> > > @@ -984,7 +1123,15 @@ template <>
> > >  inline bool
> > >  is_a_helper <const gimple_statement_omp_single>::test (const_gimple gs)
> > >  {
> > > -  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
> > > +  return gs->code == GIMPLE_OMP_SINGLE;
> > > +}
> > > +
> > > +template <>
> > > +template <>
> > > +inline bool
> > > +is_a_helper <const gimple_statement_omp_teams>::test (const_gimple gs)
> > > +{
> > > +  return gs->code == GIMPLE_OMP_TEAMS;
> > >  }
> > >  
> > >  template <>
> > > @@ -1766,9 +1913,9 @@ gimple_omp_return_nowait_p (const_gimple g)
> > >  static inline void
> > >  gimple_omp_return_set_lhs (gimple g, tree lhs)
> > >  {
> > > -  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> > > -    as_a <gimple_statement_omp_atomic_store> (g);
> > > -  omp_atomic_store_stmt->val = lhs;
> > > +  gimple_statement_omp_return *omp_return_stmt =
> > > +    as_a <gimple_statement_omp_return> (g);
> > > +  omp_return_stmt->val = lhs;
> > >  }
> > >  
> > >  
> > > @@ -1777,9 +1924,9 @@ gimple_omp_return_set_lhs (gimple g, tree lhs)
> > >  static inline tree
> > >  gimple_omp_return_lhs (const_gimple g)
> > >  {
> > > -  const gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> > > -    as_a <const gimple_statement_omp_atomic_store> (g);
> > > -  return omp_atomic_store_stmt->val;
> > > +  const gimple_statement_omp_return *omp_return_stmt =
> > > +    as_a <const gimple_statement_omp_return> (g);
> > > +  return omp_return_stmt->val;
> > >  }
> > >  
> > >  
> > > @@ -1788,9 +1935,9 @@ gimple_omp_return_lhs (const_gimple g)
> > >  static inline tree *
> > >  gimple_omp_return_lhs_ptr (gimple g)
> > >  {
> > > -  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> > > -    as_a <gimple_statement_omp_atomic_store> (g);
> > > -  return &omp_atomic_store_stmt->val;
> > > +  gimple_statement_omp_return *omp_return_stmt =
> > > +    as_a <gimple_statement_omp_return> (g);
> > > +  return &omp_return_stmt->val;
> > >  }
> > >  
> > >  
> > > @@ -3793,9 +3940,9 @@ gimple_phi_arg_has_location (gimple gs, size_t i)
> > >  static inline int
> > >  gimple_resx_region (const_gimple gs)
> > >  {
> > > -  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > > -    as_a <const gimple_statement_eh_ctrl> (gs);
> > > -  return eh_ctrl_stmt->region;
> > > +  const gimple_statement_resx *resx_stmt =
> > > +    as_a <const gimple_statement_resx> (gs);
> > > +  return resx_stmt->region;
> > >  }
> > >  
> > >  /* Set REGION to be the region number for GIMPLE_RESX GS.  */
> > > @@ -3803,9 +3950,8 @@ gimple_resx_region (const_gimple gs)
> > >  static inline void
> > >  gimple_resx_set_region (gimple gs, int region)
> > >  {
> > > -  gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > > -    as_a <gimple_statement_eh_ctrl> (gs);
> > > -  eh_ctrl_stmt->region = region;
> > > +  gimple_statement_resx *resx_stmt = as_a <gimple_statement_resx> (gs);
> > > +  resx_stmt->region = region;
> > >  }
> > >  
> > >  /* Return the region number for GIMPLE_EH_DISPATCH GS.  */
> > > @@ -3813,9 +3959,9 @@ gimple_resx_set_region (gimple gs, int region)
> > >  static inline int
> > >  gimple_eh_dispatch_region (const_gimple gs)
> > >  {
> > > -  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > > -    as_a <const gimple_statement_eh_ctrl> (gs);
> > > -  return eh_ctrl_stmt->region;
> > > +  const gimple_statement_eh_dispatch *eh_dispatch_stmt =
> > > +    as_a <const gimple_statement_eh_dispatch> (gs);
> > > +  return eh_dispatch_stmt->region;
> > >  }
> > >  
> > >  /* Set REGION to be the region number for GIMPLE_EH_DISPATCH GS.  */
> > > @@ -3823,9 +3969,9 @@ gimple_eh_dispatch_region (const_gimple gs)
> > >  static inline void
> > >  gimple_eh_dispatch_set_region (gimple gs, int region)
> > >  {
> > > -  gimple_statement_eh_ctrl *eh_ctrl_stmt =
> > > -    as_a <gimple_statement_eh_ctrl> (gs);
> > > -  eh_ctrl_stmt->region = region;
> > > +  gimple_statement_eh_dispatch *eh_dispatch_stmt =
> > > +    as_a <gimple_statement_eh_dispatch> (gs);
> > > +  eh_dispatch_stmt->region = region;
> > >  }
> > >  
> > >  /* Return the number of labels associated with the switch statement GS.  */
> > > @@ -4663,9 +4809,9 @@ gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
> > >  static inline tree
> > >  gimple_omp_taskreg_clauses (const_gimple gs)
> > >  {
> > > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <const gimple_statement_omp_parallel> (gs);
> > > -  return omp_parallel_stmt->clauses;
> > > +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <const gimple_statement_omp_taskreg> (gs);
> > > +  return omp_taskreg_stmt->clauses;
> > >  }
> > >  
> > >  
> > > @@ -4674,9 +4820,9 @@ gimple_omp_taskreg_clauses (const_gimple gs)
> > >  static inline tree *
> > >  gimple_omp_taskreg_clauses_ptr (gimple gs)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  return &omp_parallel_stmt->clauses;
> > > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <gimple_statement_omp_taskreg> (gs);
> > > +  return &omp_taskreg_stmt->clauses;
> > >  }
> > >  
> > >  
> > > @@ -4686,9 +4832,9 @@ gimple_omp_taskreg_clauses_ptr (gimple gs)
> > >  static inline void
> > >  gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  omp_parallel_stmt->clauses = clauses;
> > > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <gimple_statement_omp_taskreg> (gs);
> > > +  omp_taskreg_stmt->clauses = clauses;
> > >  }
> > >  
> > >  
> > > @@ -4697,9 +4843,9 @@ gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
> > >  static inline tree
> > >  gimple_omp_taskreg_child_fn (const_gimple gs)
> > >  {
> > > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <const gimple_statement_omp_parallel> (gs);
> > > -  return omp_parallel_stmt->child_fn;
> > > +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <const gimple_statement_omp_taskreg> (gs);
> > > +  return omp_taskreg_stmt->child_fn;
> > >  }
> > >  
> > >  /* Return a pointer to the child function used to hold the body of
> > > @@ -4708,9 +4854,9 @@ gimple_omp_taskreg_child_fn (const_gimple gs)
> > >  static inline tree *
> > >  gimple_omp_taskreg_child_fn_ptr (gimple gs)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  return &omp_parallel_stmt->child_fn;
> > > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <gimple_statement_omp_taskreg> (gs);
> > > +  return &omp_taskreg_stmt->child_fn;
> > >  }
> > >  
> > >  
> > > @@ -4719,9 +4865,9 @@ gimple_omp_taskreg_child_fn_ptr (gimple gs)
> > >  static inline void
> > >  gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  omp_parallel_stmt->child_fn = child_fn;
> > > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <gimple_statement_omp_taskreg> (gs);
> > > +  omp_taskreg_stmt->child_fn = child_fn;
> > >  }
> > >  
> > >  
> > > @@ -4731,9 +4877,9 @@ gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
> > >  static inline tree
> > >  gimple_omp_taskreg_data_arg (const_gimple gs)
> > >  {
> > > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <const gimple_statement_omp_parallel> (gs);
> > > -  return omp_parallel_stmt->data_arg;
> > > +  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <const gimple_statement_omp_taskreg> (gs);
> > > +  return omp_taskreg_stmt->data_arg;
> > >  }
> > >  
> > >  
> > > @@ -4742,9 +4888,9 @@ gimple_omp_taskreg_data_arg (const_gimple gs)
> > >  static inline tree *
> > >  gimple_omp_taskreg_data_arg_ptr (gimple gs)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  return &omp_parallel_stmt->data_arg;
> > > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <gimple_statement_omp_taskreg> (gs);
> > > +  return &omp_taskreg_stmt->data_arg;
> > >  }
> > >  
> > >  
> > > @@ -4753,9 +4899,9 @@ gimple_omp_taskreg_data_arg_ptr (gimple gs)
> > >  static inline void
> > >  gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  omp_parallel_stmt->data_arg = data_arg;
> > > +  gimple_statement_omp_taskreg *omp_taskreg_stmt =
> > > +    as_a <gimple_statement_omp_taskreg> (gs);
> > > +  omp_taskreg_stmt->data_arg = data_arg;
> > >  }
> > >  
> > >  
> > > @@ -4896,9 +5042,9 @@ gimple_omp_single_set_clauses (gimple gs, tree clauses)
> > >  static inline tree
> > >  gimple_omp_target_clauses (const_gimple gs)
> > >  {
> > > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <const gimple_statement_omp_parallel> (gs);
> > > -  return omp_parallel_stmt->clauses;
> > > +  const gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <const gimple_statement_omp_target> (gs);
> > > +  return omp_target_stmt->clauses;
> > >  }
> > >  
> > >  
> > > @@ -4907,9 +5053,9 @@ gimple_omp_target_clauses (const_gimple gs)
> > >  static inline tree *
> > >  gimple_omp_target_clauses_ptr (gimple gs)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  return &omp_parallel_stmt->clauses;
> > > +  gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <gimple_statement_omp_target> (gs);
> > > +  return &omp_target_stmt->clauses;
> > >  }
> > >  
> > >  
> > > @@ -4918,9 +5064,9 @@ gimple_omp_target_clauses_ptr (gimple gs)
> > >  static inline void
> > >  gimple_omp_target_set_clauses (gimple gs, tree clauses)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  omp_parallel_stmt->clauses = clauses;
> > > +  gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <gimple_statement_omp_target> (gs);
> > > +  omp_target_stmt->clauses = clauses;
> > >  }
> > >  
> > >  
> > > @@ -4950,9 +5096,9 @@ gimple_omp_target_set_kind (gimple g, int kind)
> > >  static inline tree
> > >  gimple_omp_target_child_fn (const_gimple gs)
> > >  {
> > > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <const gimple_statement_omp_parallel> (gs);
> > > -  return omp_parallel_stmt->child_fn;
> > > +  const gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <const gimple_statement_omp_target> (gs);
> > > +  return omp_target_stmt->child_fn;
> > >  }
> > >  
> > >  /* Return a pointer to the child function used to hold the body of
> > > @@ -4961,9 +5107,9 @@ gimple_omp_target_child_fn (const_gimple gs)
> > >  static inline tree *
> > >  gimple_omp_target_child_fn_ptr (gimple gs)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  return &omp_parallel_stmt->child_fn;
> > > +  gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <gimple_statement_omp_target> (gs);
> > > +  return &omp_target_stmt->child_fn;
> > >  }
> > >  
> > >  
> > > @@ -4972,9 +5118,9 @@ gimple_omp_target_child_fn_ptr (gimple gs)
> > >  static inline void
> > >  gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  omp_parallel_stmt->child_fn = child_fn;
> > > +  gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <gimple_statement_omp_target> (gs);
> > > +  omp_target_stmt->child_fn = child_fn;
> > >  }
> > >  
> > >  
> > > @@ -4984,9 +5130,9 @@ gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
> > >  static inline tree
> > >  gimple_omp_target_data_arg (const_gimple gs)
> > >  {
> > > -  const gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <const gimple_statement_omp_parallel> (gs);
> > > -  return omp_parallel_stmt->data_arg;
> > > +  const gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <const gimple_statement_omp_target> (gs);
> > > +  return omp_target_stmt->data_arg;
> > >  }
> > >  
> > >  
> > > @@ -4995,9 +5141,9 @@ gimple_omp_target_data_arg (const_gimple gs)
> > >  static inline tree *
> > >  gimple_omp_target_data_arg_ptr (gimple gs)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  return &omp_parallel_stmt->data_arg;
> > > +  gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <gimple_statement_omp_target> (gs);
> > > +  return &omp_target_stmt->data_arg;
> > >  }
> > >  
> > >  
> > > @@ -5006,9 +5152,9 @@ gimple_omp_target_data_arg_ptr (gimple gs)
> > >  static inline void
> > >  gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
> > >  {
> > > -  gimple_statement_omp_parallel *omp_parallel_stmt =
> > > -    as_a <gimple_statement_omp_parallel> (gs);
> > > -  omp_parallel_stmt->data_arg = data_arg;
> > > +  gimple_statement_omp_target *omp_target_stmt =
> > > +    as_a <gimple_statement_omp_target> (gs);
> > > +  omp_target_stmt->data_arg = data_arg;
> > >  }
> > >  
> > >  
> > > @@ -5017,9 +5163,9 @@ gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
> > >  static inline tree
> > >  gimple_omp_teams_clauses (const_gimple gs)
> > >  {
> > > -  const gimple_statement_omp_single *omp_single_stmt =
> > > -    as_a <const gimple_statement_omp_single> (gs);
> > > -  return omp_single_stmt->clauses;
> > > +  const gimple_statement_omp_teams *omp_teams_stmt =
> > > +    as_a <const gimple_statement_omp_teams> (gs);
> > > +  return omp_teams_stmt->clauses;
> > >  }
> > >  
> > >  
> > > @@ -5028,9 +5174,9 @@ gimple_omp_teams_clauses (const_gimple gs)
> > >  static inline tree *
> > >  gimple_omp_teams_clauses_ptr (gimple gs)
> > >  {
> > > -  gimple_statement_omp_single *omp_single_stmt =
> > > -    as_a <gimple_statement_omp_single> (gs);
> > > -  return &omp_single_stmt->clauses;
> > > +  gimple_statement_omp_teams *omp_teams_stmt =
> > > +    as_a <gimple_statement_omp_teams> (gs);
> > > +  return &omp_teams_stmt->clauses;
> > >  }
> > >  
> > >  
> > > @@ -5039,9 +5185,9 @@ gimple_omp_teams_clauses_ptr (gimple gs)
> > >  static inline void
> > >  gimple_omp_teams_set_clauses (gimple gs, tree clauses)
> > >  {
> > > -  gimple_statement_omp_single *omp_single_stmt =
> > > -    as_a <gimple_statement_omp_single> (gs);
> > > -  omp_single_stmt->clauses = clauses;
> > > +  gimple_statement_omp_teams *omp_teams_stmt =
> > > +    as_a <gimple_statement_omp_teams> (gs);
> > > +  omp_teams_stmt->clauses = clauses;
> > >  }
> > >  
> > >  
> > > diff --git a/gcc/gsstruct.def b/gcc/gsstruct.def
> > > index 91738f4..82f1f52 100644
> > > --- a/gcc/gsstruct.def
> > > +++ b/gcc/gsstruct.def
> > > @@ -43,11 +43,11 @@ DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false)
> > >  DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
> > >  DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false)
> > >  DEFGSSTRUCT(GSS_OMP_FOR, gimple_statement_omp_for, false)
> > > -DEFGSSTRUCT(GSS_OMP_PARALLEL, gimple_statement_omp_parallel, false)
> > > +DEFGSSTRUCT(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout, false)
> > >  DEFGSSTRUCT(GSS_OMP_TASK, gimple_statement_omp_task, false)
> > >  DEFGSSTRUCT(GSS_OMP_SECTIONS, gimple_statement_omp_sections, false)
> > > -DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_statement_omp_single, false)
> > > +DEFGSSTRUCT(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout, false)
> > >  DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false)
> > >  DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false)
> > > -DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false)
> > > +DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store, false)
> > >  DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false)


Grüße,
 Thomas
diff mbox

Patch

commit 9a0c36081b3baecfc16a8500464df3a94c8dd145
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Thu Nov 21 21:46:58 2013 -0500

    Fix as_a<> helpers for gimple
    
    	* gengtype.c (struct seen_tag): New.
    	(already_seen_tag): New.
    	(mark_tag_as_seen): New.
    	(walk_subclasses): Support having multiple subclasses using the
    	same tag by tracking which tags have already been seen, and using
    	this to avoid adding duplicate cases to the "switch" statement.
    	The call to already_seen_tag introduces an O(N^2) when running
    	gengtype on N, the number of tags, due to the repeated linear
    	search, but currently max(N) is relatively small (the number of
    	GSS codes, which is 26).
    	(walk_type): Pass in a seen_tag for use by the walk_subclasses
    	recursion.
    
    	* gimple.def (GIMPLE_OMP_ATOMIC_STORE, GIMPLE_OMP_RETURN): Rename
    	underlying GSS values for these codes (from GSS_OMP_ATOMIC_STORE to
    	GSS_OMP_ATOMIC_STORE_LAYOUT) to make clear that although
    	GIMPLE_OMP_RETURN happens to share the data layout of
    	GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related.
    	(GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET): Likewise, rename
    	underlying GSS value from GSS_OMP_PARALLEL to
    	GSS_OMP_PARALLEL_LAYOUT to make clear that these gimple codes are
    	not directly related; they merely share in-memory layout.
    	(GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS): Likewise, rename GSS values
    	for these two codes from GSS_OMP_SINGLE to GSS_OMP_SINGLE_LAYOUT.
    
    	* gsstruct.def (GSS_OMP_PARALLEL, gimple_statement_omp_parallel):
    	Rename to...
    	(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout):
    	...these.
    	(GSS_OMP_SINGLE, gimple_statement_omp_single): Rename to...
    	(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout):
    	...these.
    	(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store): Rename
    	to...
    	(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store):
    	...these.
    
    	* gimple.h (gimple_statement_resx): New subclass of
    	gimple_statement_eh_ctrl, with the invariant that
    	stmt->code == GIMPLE_RESX.
    	(gimple_statement_eh_dispatch): New subclass of
    	gimple_statement_eh_ctrl, with the invariant that
    	stmt->code == GIMPLE_EH_DISPATH.
    
    	(gimple_statement_omp_parallel): The existing class expressed
    	a layout (GSS_OMP_PARALLEL), but the codes with that layout
    	are not all related, so it makes more sense for this class to
    	express a *code* (GIMPLE_OMP_PARALLEL).  GSS_OMP_PARALLEL has
    	been renamed to GSS_OMP_PARALLEL_LAYOUT to express this, so
    	rename the existing gimple_statement_omp_parallel class to...
    	(gimple_statement_omp_parallel_layout): ...this, expressing
    	a statement of structure layout GSS_OMP_PARALLEL_LAYOUT.
    	(gimple_statement_omp_taskreg): New subclass of
    	gimple_statement_omp_parallel_layout, expressing the invariant
    	that the code is one of GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
    	as used by the various gimple_omp_taskreg_ accessors.
    	(gimple_statement_omp_parallel): Reintroduce this class, this time
    	as a subclass of gimple_statement_omp_taskreg to express the
    	invariant stmt->code == GIMPLE_OMP_PARALLEL.
    	(gimple_statement_omp_target) New class, subclassing
    	gimple_statement_omp_parallel_layout, to express the invariant
    	stmt->code == GIMPLE_OMP_TARGET.
    	(gimple_statement_omp_task): Update to inherit from
    	gimple_statement_omp_taskreg rather than
    	gimple_statement_omp_parallel.
    
    	(gimple_statement_omp_single): Rename to...
    	(gimple_statement_omp_single_layout): ...this, expressing the
    	invariant that the layout is GSS_OMP_SINGLE_LAYOUT.
    	(gimple_statement_omp_single): ...and reintroduce this name as
    	a subclass of gimple_statement_omp_single_layout, expressing
    	the invariant that code == GIMPLE_OMP_SINGLE.
    	(gimple_statement_omp_teams): New class, subclassing
    	gimple_statement_omp_single_layout, for the code GIMPLE_OMP_TEAMS.
    
    	(gimple_statement_omp_atomic_store): Rename to...
    	(gimple_statement_omp_atomic_store_layout): ...this, expressing
    	the invariant that the layout is GSS_OMP_ATOMIC_STORE_LAYOUT.
    	(gimple_statement_omp_atomic_store): ...and reintroduce this
    	name as a subclass of gimple_statement_omp_atomic_store_layout
    	with code == GIMPLE_OMP_ATOMIC_STORE.
    	(gimple_statement_omp_return): New class, subclassing
    	gimple_statement_omp_atomic_store_layout for the code
    	GIMPLE_OMP_RETURN.
    
    	(is_a_helper <gimple_statement_eh_ctrl>::test): Delete.
    	(is_a_helper <gimple_statement_resx>::test): New.
    	(is_a_helper <gimple_statement_eh_dispatch>::test): New.
    	(is_a_helper <gimple_statement_omp_atomic_store>::test): Only
    	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
    	(is_a_helper <gimple_statement_omp_return>::test): New.
    	(is_a_helper <gimple_statement_omp_taskreg>::test): New.
    	(is_a_helper <gimple_statement_omp_parallel>::test): Only check
    	for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
    	GIMPLE_OMP_TARGET.
    	(is_a_helper <gimple_statement_omp_target>::test): New.
    	(is_a_helper <gimple_statement_omp_single>::test): Only check
    	for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
    	(is_a_helper <gimple_statement_omp_teams>::test): New.
    
    	(is_a_helper <const gimple_statement_eh_ctrl>::test): Delete.
    	(is_a_helper <const gimple_statement_resx>::test): New.
    	(is_a_helper <const gimple_statement_eh_dispatch>::test): New.
    	(is_a_helper <const gimple_statement_omp_atomic_store>::test): Only
    	check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN.
    	(is_a_helper <const gimple_statement_omp_return>::test): New.
    	(is_a_helper <const gimple_statement_omp_taskreg>::test): New.
    	(is_a_helper <const gimple_statement_omp_parallel>::test): Only
    	check for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or
    	GIMPLE_OMP_TARGET.
    	(is_a_helper <const gimple_statement_omp_target>::test): New.
    	(is_a_helper <const gimple_statement_omp_single>::test): Only
    	check for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS.
    	(is_a_helper <const gimple_statement_omp_teams>::test): New.
    
    	(gimple_omp_return_set_lhs, gimple_omp_return_lhs,
    	gimple_omp_return_lhs_ptr): Replace bogus downcasts to
    	gimple_statement_omp_atomic_store with downcasts to
    	gimple_statement_omp_return, thus requiring that the code be
    	GIMPLE_OMP_RETURN.
    	(gimple_resx_region, gimple_resx_set_region): Replace bogus
    	downcasts to gimple_statement_eh_ctrl with downcasts to
    	gimple_statement_resx, thus requiring that the code be
    	GIMPLE_RESX.
    	(gimple_eh_dispatch_region, gimple_eh_dispatch_set_region):
    	Replace bogus downcasts to const gimple_statement_eh_ctrl with
    	downcasts to gimple_statement_eh_dispatch, thus requiring that
    	the code be GIMPLE_EH_DISPATCH.
    	(gimple_omp_taskreg_clauses, gimple_omp_taskreg_clauses_ptr)
    	gimple_omp_taskreg_set_clauses, gimple_omp_taskreg_child_fn,
    	gimple_omp_taskreg_child_fn_ptr, gimple_omp_taskreg_set_child_fn,
    	gimple_omp_taskreg_data_arg, gimple_omp_taskreg_data_arg_ptr,
    	gimple_omp_taskreg_set_data_arg): Replace bogus downcasts to
    	gimple_statement_omp_parallel with downcasts to
    	gimple_statement_omp_taskreg, thus requiring that the code be
    	either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK.
    	(gimple_omp_target_clauses, gimple_omp_target_clauses_ptr
    	gimple_omp_target_set_clauses, gimple_omp_target_child_fn
    	gimple_omp_target_child_fn_ptr, gimple_omp_target_set_child_fn
    	gimple_omp_target_data_arg, gimple_omp_target_data_arg_ptr
    	gimple_omp_target_set_data_arg): Replace bogus downcasts to
    	gimple_statement_omp_parallel with downcasts to
    	gimple_statement_omp_target, thus requiring that the code be
    	GIMPLE_OMP_TARGET.
    	(gimple_omp_teams_clauses, gimple_omp_teams_clauses_ptr
    	gimple_omp_teams_set_clauses): Replace bogus downcasts to
    	gimple_statement_omp_single with downcasts to
    	gimple_statement_omp_teams, thus requiring that the code be
    	GIMPLE_OMP_TEAMS.
    
    	* gimple.c (gimple_build_resx): Fix bogus as_a<> to use
    	gimple_statement_resx.
    	(gimple_build_eh_dispatch): Fix bogus as_a<> to use
    	gimple_statement_eh_dispatch.

diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 86e9ca2..6e675cc 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -2654,15 +2654,48 @@  get_string_option (options_p opt, const char *key)
   return NULL;
 }
 
+/* Machinery for avoiding duplicate tags within switch statements.  */
+struct seen_tag
+{
+  const char *tag;
+  struct seen_tag *next;
+};
+
+int
+already_seen_tag (struct seen_tag *seen_tags, const char *tag)
+{
+  /* Linear search, so O(n^2), but n is currently small.  */
+  while (seen_tags)
+    {
+      if (!strcmp (seen_tags->tag, tag))
+	return 1;
+      seen_tags = seen_tags->next;
+    }
+  /* Not yet seen this tag. */
+  return 0;
+}
+
+void
+mark_tag_as_seen (struct seen_tag **seen_tags, const char *tag)
+{
+  /* Add to front of linked list. */
+  struct seen_tag *new_node = XCNEW (struct seen_tag);
+  new_node->tag = tag;
+  new_node->next = *seen_tags;
+  *seen_tags = new_node;
+}
+
 static void
-walk_subclasses (type_p base, struct walk_type_data *d)
+walk_subclasses (type_p base, struct walk_type_data *d,
+		 struct seen_tag **seen_tags)
 {
   for (type_p sub = base->u.s.first_subclass; sub != NULL;
        sub = sub->u.s.next_sibling_class)
     {
       const char *type_tag = get_string_option (sub->u.s.opt, "tag");
-      if (type_tag)
+      if (type_tag && !already_seen_tag (*seen_tags, type_tag))
 	{
+	  mark_tag_as_seen (seen_tags, type_tag);
 	  oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
 	  d->indent += 2;
 	  oprintf (d->of, "%*s{\n", d->indent, "");
@@ -2678,7 +2711,7 @@  walk_subclasses (type_p base, struct walk_type_data *d)
 	  oprintf (d->of, "%*sbreak;\n", d->indent, "");
 	  d->indent -= 2;
 	}
-      walk_subclasses (sub, d);
+      walk_subclasses (sub, d, seen_tags);
     }
 }
 
@@ -3225,7 +3258,8 @@  walk_type (type_p t, struct walk_type_data *d)
 	else if (desc)
 	  {
 	    /* Add cases to handle subclasses.  */
-	    walk_subclasses (t, d);
+	    struct seen_tag *tags = NULL;
+	    walk_subclasses (t, d, &tags);
 
 	    /* Ensure that if someone forgets a "tag" option that we don't
 	       silent fail to traverse that subclass's fields.  */
diff --git a/gcc/gimple.c b/gcc/gimple.c
index d48ca6b..2e45f37 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -697,8 +697,8 @@  gimple_build_wce (gimple_seq cleanup)
 gimple
 gimple_build_resx (int region)
 {
-  gimple_statement_eh_ctrl *p =
-    as_a <gimple_statement_eh_ctrl> (
+  gimple_statement_resx *p =
+    as_a <gimple_statement_resx> (
       gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
   p->region = region;
   return p;
@@ -747,8 +747,8 @@  gimple_build_switch (tree index, tree default_label, vec<tree> args)
 gimple
 gimple_build_eh_dispatch (int region)
 {
-  gimple_statement_eh_ctrl *p =
-    as_a <gimple_statement_eh_ctrl> (
+  gimple_statement_eh_dispatch *p =
+    as_a <gimple_statement_eh_dispatch> (
       gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
   p->region = region;
   return p;
diff --git a/gcc/gimple.def b/gcc/gimple.def
index 07370ae..ff1ef43 100644
--- a/gcc/gimple.def
+++ b/gcc/gimple.def
@@ -221,7 +221,7 @@  DEFGSCODE(GIMPLE_NOP, "gimple_nop", GSS_BASE)
 DEFGSCODE(GIMPLE_OMP_ATOMIC_LOAD, "gimple_omp_atomic_load",
 	  GSS_OMP_ATOMIC_LOAD)
 DEFGSCODE(GIMPLE_OMP_ATOMIC_STORE, "gimple_omp_atomic_store",
-	  GSS_OMP_ATOMIC_STORE)
+	  GSS_OMP_ATOMIC_STORE_LAYOUT)
 
 /* GIMPLE_OMP_CONTINUE marks the location of the loop or sections
    iteration in partially lowered OpenMP code.  */
@@ -300,7 +300,7 @@  DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered", GSS_OMP)
    DATA_ARG is a local variable in the parent function containing data
    to be shared with CHILD_FN.  This is used to implement all the data
    sharing clauses.  */
-DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
+DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL_LAYOUT)
 
 /* GIMPLE_OMP_TASK <BODY, CLAUSES, CHILD_FN, DATA_ARG, COPY_FN,
 		    ARG_SIZE, ARG_ALIGN> represents
@@ -329,7 +329,7 @@  DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL)
 DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK)
 
 /* OMP_RETURN marks the end of an OpenMP directive.  */
-DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE)
+DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
 
 /* OMP_SECTION <BODY> represents #pragma omp section.
    BODY is the sequence of statements in the section body.  */
@@ -351,7 +351,7 @@  DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch", GSS_BASE)
 /* GIMPLE_OMP_SINGLE <BODY, CLAUSES> represents #pragma omp single
    BODY is the sequence of statements inside the single section.
    CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
-DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
+DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE_LAYOUT)
 
 /* GIMPLE_OMP_TARGET <BODY, CLAUSES, CHILD_FN> represents
    #pragma omp target {,data,update}
@@ -364,12 +364,12 @@  DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE)
    DATA_ARG is a vec of 3 local variables in the parent function
    containing data to be mapped to CHILD_FN.  This is used to
    implement the MAP clauses.  */
-DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL)
+DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)
 
 /* GIMPLE_OMP_TEAMS <BODY, CLAUSES> represents #pragma omp teams
    BODY is the sequence of statements inside the single section.
    CLAUSES is an OMP_CLAUSE chain holding the associated clauses.  */
-DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE)
+DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE_LAYOUT)
 
 /* GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction.
 
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 0eb23fc..0257576 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -420,6 +420,20 @@  struct GTY((tag("GSS_EH_CTRL")))
   int region;
 };
 
+struct GTY((tag("GSS_EH_CTRL")))
+  gimple_statement_resx : public gimple_statement_eh_ctrl
+{
+  /* No extra fields; adds invariant:
+       stmt->code == GIMPLE_RESX.  */
+};
+
+struct GTY((tag("GSS_EH_CTRL")))
+  gimple_statement_eh_dispatch : public gimple_statement_eh_ctrl
+{
+  /* No extra fields; adds invariant:
+       stmt->code == GIMPLE_EH_DISPATH.  */
+};
+
 
 /* GIMPLE_TRY */
 
@@ -547,10 +561,9 @@  struct GTY((tag("GSS_OMP_FOR")))
 };
 
 
-/* GIMPLE_OMP_PARALLEL */
-
-struct GTY((tag("GSS_OMP_PARALLEL")))
-  gimple_statement_omp_parallel : public gimple_statement_omp
+/* GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET */
+struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
+  gimple_statement_omp_parallel_layout : public gimple_statement_omp
 {
   /* [ WORD 1-7 ] : base class */
 
@@ -567,11 +580,35 @@  struct GTY((tag("GSS_OMP_PARALLEL")))
   tree data_arg;
 };
 
+/* GIMPLE_OMP_PARALLEL or GIMPLE_TASK */
+struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
+  gimple_statement_omp_taskreg : public gimple_statement_omp_parallel_layout
+{
+    /* No extra fields; adds invariant:
+         stmt->code == GIMPLE_OMP_PARALLEL
+	 || stmt->code == GIMPLE_OMP_TASK.  */
+};
+
+
+/* GIMPLE_OMP_PARALLEL */
+struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
+  gimple_statement_omp_parallel : public gimple_statement_omp_taskreg
+{
+    /* No extra fields; adds invariant:
+         stmt->code == GIMPLE_OMP_PARALLEL.  */
+};
+
+struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
+  gimple_statement_omp_target : public gimple_statement_omp_parallel_layout
+{
+    /* No extra fields; adds invariant:
+         stmt->code == GIMPLE_OMP_TARGET.  */
+};
 
 /* GIMPLE_OMP_TASK */
 
 struct GTY((tag("GSS_OMP_TASK")))
-  gimple_statement_omp_task : public gimple_statement_omp_parallel
+  gimple_statement_omp_task : public gimple_statement_omp_taskreg
 {
   /* [ WORD 1-10 ] : base class */
 
@@ -623,10 +660,10 @@  struct GTY((tag("GSS_OMP_CONTINUE")))
   tree control_use;
 };
 
-/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS */
+/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS */
 
-struct GTY((tag("GSS_OMP_SINGLE")))
-  gimple_statement_omp_single : public gimple_statement_omp
+struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
+  gimple_statement_omp_single_layout : public gimple_statement_omp
 {
   /* [ WORD 1-7 ] : base class */
 
@@ -634,6 +671,20 @@  struct GTY((tag("GSS_OMP_SINGLE")))
   tree clauses;
 };
 
+struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
+  gimple_statement_omp_single : public gimple_statement_omp_single_layout
+{
+    /* No extra fields; adds invariant:
+         stmt->code == GIMPLE_OMP_SINGLE.  */
+};
+
+struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
+  gimple_statement_omp_teams : public gimple_statement_omp_single_layout
+{
+    /* No extra fields; adds invariant:
+         stmt->code == GIMPLE_OMP_TEAMS.  */
+};
+
 
 /* GIMPLE_OMP_ATOMIC_LOAD.
    Note: This is based on gimple_statement_base, not g_s_omp, because g_s_omp
@@ -651,8 +702,8 @@  struct GTY((tag("GSS_OMP_ATOMIC_LOAD")))
 /* GIMPLE_OMP_ATOMIC_STORE.
    See note on GIMPLE_OMP_ATOMIC_LOAD.  */
 
-struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
-  gimple_statement_omp_atomic_store : public gimple_statement_base
+struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
+  gimple_statement_omp_atomic_store_layout : public gimple_statement_base
 {
   /* [ WORD 1-6 ] : base class */
 
@@ -660,6 +711,22 @@  struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
   tree val;
 };
 
+struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
+  gimple_statement_omp_atomic_store :
+    public gimple_statement_omp_atomic_store_layout
+{
+    /* No extra fields; adds invariant:
+         stmt->code == GIMPLE_OMP_ATOMIC_STORE.  */
+};
+
+struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT")))
+  gimple_statement_omp_return :
+    public gimple_statement_omp_atomic_store_layout
+{
+    /* No extra fields; adds invariant:
+         stmt->code == GIMPLE_OMP_RETURN.  */
+};
+
 /* GIMPLE_TRANSACTION.  */
 
 /* Bits to be stored in the GIMPLE_TRANSACTION subcode.  */
@@ -742,9 +809,17 @@  is_a_helper <gimple_statement_catch>::test (gimple gs)
 template <>
 template <>
 inline bool
-is_a_helper <gimple_statement_eh_ctrl>::test (gimple gs)
+is_a_helper <gimple_statement_resx>::test (gimple gs)
+{
+  return gs->code == GIMPLE_RESX;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_dispatch>::test (gimple gs)
 {
-  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
+  return gs->code == GIMPLE_EH_DISPATCH;
 }
 
 template <>
@@ -784,7 +859,15 @@  template <>
 inline bool
 is_a_helper <gimple_statement_omp_atomic_store>::test (gimple gs)
 {
-  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
+  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_return>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_RETURN;
 }
 
 template <>
@@ -814,9 +897,25 @@  is_a_helper <gimple_statement_omp_for>::test (gimple gs)
 template <>
 template <>
 inline bool
+is_a_helper <gimple_statement_omp_taskreg>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
+}
+
+template <>
+template <>
+inline bool
 is_a_helper <gimple_statement_omp_parallel>::test (gimple gs)
 {
-  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
+  return gs->code == GIMPLE_OMP_PARALLEL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_target>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TARGET;
 }
 
 template <>
@@ -832,7 +931,15 @@  template <>
 inline bool
 is_a_helper <gimple_statement_omp_single>::test (gimple gs)
 {
-  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
+  return gs->code == GIMPLE_OMP_SINGLE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_teams>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TEAMS;
 }
 
 template <>
@@ -910,9 +1017,17 @@  is_a_helper <const gimple_statement_catch>::test (const_gimple gs)
 template <>
 template <>
 inline bool
-is_a_helper <const gimple_statement_eh_ctrl>::test (const_gimple gs)
+is_a_helper <const gimple_statement_resx>::test (const_gimple gs)
 {
-  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
+  return gs->code == GIMPLE_RESX;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_eh_dispatch>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_EH_DISPATCH;
 }
 
 template <>
@@ -936,7 +1051,15 @@  template <>
 inline bool
 is_a_helper <const gimple_statement_omp_atomic_store>::test (const_gimple gs)
 {
-  return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN;
+  return gs->code == GIMPLE_OMP_ATOMIC_STORE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_return>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_RETURN;
 }
 
 template <>
@@ -966,9 +1089,25 @@  is_a_helper <const gimple_statement_omp_for>::test (const_gimple gs)
 template <>
 template <>
 inline bool
+is_a_helper <const gimple_statement_omp_taskreg>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK;
+}
+
+template <>
+template <>
+inline bool
 is_a_helper <const gimple_statement_omp_parallel>::test (const_gimple gs)
 {
-  return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET;
+  return gs->code == GIMPLE_OMP_PARALLEL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_target>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TARGET;
 }
 
 template <>
@@ -984,7 +1123,15 @@  template <>
 inline bool
 is_a_helper <const gimple_statement_omp_single>::test (const_gimple gs)
 {
-  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
+  return gs->code == GIMPLE_OMP_SINGLE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_teams>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TEAMS;
 }
 
 template <>
@@ -1766,9 +1913,9 @@  gimple_omp_return_nowait_p (const_gimple g)
 static inline void
 gimple_omp_return_set_lhs (gimple g, tree lhs)
 {
-  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
-    as_a <gimple_statement_omp_atomic_store> (g);
-  omp_atomic_store_stmt->val = lhs;
+  gimple_statement_omp_return *omp_return_stmt =
+    as_a <gimple_statement_omp_return> (g);
+  omp_return_stmt->val = lhs;
 }
 
 
@@ -1777,9 +1924,9 @@  gimple_omp_return_set_lhs (gimple g, tree lhs)
 static inline tree
 gimple_omp_return_lhs (const_gimple g)
 {
-  const gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
-    as_a <const gimple_statement_omp_atomic_store> (g);
-  return omp_atomic_store_stmt->val;
+  const gimple_statement_omp_return *omp_return_stmt =
+    as_a <const gimple_statement_omp_return> (g);
+  return omp_return_stmt->val;
 }
 
 
@@ -1788,9 +1935,9 @@  gimple_omp_return_lhs (const_gimple g)
 static inline tree *
 gimple_omp_return_lhs_ptr (gimple g)
 {
-  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
-    as_a <gimple_statement_omp_atomic_store> (g);
-  return &omp_atomic_store_stmt->val;
+  gimple_statement_omp_return *omp_return_stmt =
+    as_a <gimple_statement_omp_return> (g);
+  return &omp_return_stmt->val;
 }
 
 
@@ -3793,9 +3940,9 @@  gimple_phi_arg_has_location (gimple gs, size_t i)
 static inline int
 gimple_resx_region (const_gimple gs)
 {
-  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
-    as_a <const gimple_statement_eh_ctrl> (gs);
-  return eh_ctrl_stmt->region;
+  const gimple_statement_resx *resx_stmt =
+    as_a <const gimple_statement_resx> (gs);
+  return resx_stmt->region;
 }
 
 /* Set REGION to be the region number for GIMPLE_RESX GS.  */
@@ -3803,9 +3950,8 @@  gimple_resx_region (const_gimple gs)
 static inline void
 gimple_resx_set_region (gimple gs, int region)
 {
-  gimple_statement_eh_ctrl *eh_ctrl_stmt =
-    as_a <gimple_statement_eh_ctrl> (gs);
-  eh_ctrl_stmt->region = region;
+  gimple_statement_resx *resx_stmt = as_a <gimple_statement_resx> (gs);
+  resx_stmt->region = region;
 }
 
 /* Return the region number for GIMPLE_EH_DISPATCH GS.  */
@@ -3813,9 +3959,9 @@  gimple_resx_set_region (gimple gs, int region)
 static inline int
 gimple_eh_dispatch_region (const_gimple gs)
 {
-  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
-    as_a <const gimple_statement_eh_ctrl> (gs);
-  return eh_ctrl_stmt->region;
+  const gimple_statement_eh_dispatch *eh_dispatch_stmt =
+    as_a <const gimple_statement_eh_dispatch> (gs);
+  return eh_dispatch_stmt->region;
 }
 
 /* Set REGION to be the region number for GIMPLE_EH_DISPATCH GS.  */
@@ -3823,9 +3969,9 @@  gimple_eh_dispatch_region (const_gimple gs)
 static inline void
 gimple_eh_dispatch_set_region (gimple gs, int region)
 {
-  gimple_statement_eh_ctrl *eh_ctrl_stmt =
-    as_a <gimple_statement_eh_ctrl> (gs);
-  eh_ctrl_stmt->region = region;
+  gimple_statement_eh_dispatch *eh_dispatch_stmt =
+    as_a <gimple_statement_eh_dispatch> (gs);
+  eh_dispatch_stmt->region = region;
 }
 
 /* Return the number of labels associated with the switch statement GS.  */
@@ -4663,9 +4809,9 @@  gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_taskreg_clauses (const_gimple gs)
 {
-  const gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <const gimple_statement_omp_parallel> (gs);
-  return omp_parallel_stmt->clauses;
+  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <const gimple_statement_omp_taskreg> (gs);
+  return omp_taskreg_stmt->clauses;
 }
 
 
@@ -4674,9 +4820,9 @@  gimple_omp_taskreg_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_clauses_ptr (gimple gs)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  return &omp_parallel_stmt->clauses;
+  gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <gimple_statement_omp_taskreg> (gs);
+  return &omp_taskreg_stmt->clauses;
 }
 
 
@@ -4686,9 +4832,9 @@  gimple_omp_taskreg_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  omp_parallel_stmt->clauses = clauses;
+  gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <gimple_statement_omp_taskreg> (gs);
+  omp_taskreg_stmt->clauses = clauses;
 }
 
 
@@ -4697,9 +4843,9 @@  gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_taskreg_child_fn (const_gimple gs)
 {
-  const gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <const gimple_statement_omp_parallel> (gs);
-  return omp_parallel_stmt->child_fn;
+  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <const gimple_statement_omp_taskreg> (gs);
+  return omp_taskreg_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4708,9 +4854,9 @@  gimple_omp_taskreg_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_child_fn_ptr (gimple gs)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  return &omp_parallel_stmt->child_fn;
+  gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <gimple_statement_omp_taskreg> (gs);
+  return &omp_taskreg_stmt->child_fn;
 }
 
 
@@ -4719,9 +4865,9 @@  gimple_omp_taskreg_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  omp_parallel_stmt->child_fn = child_fn;
+  gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <gimple_statement_omp_taskreg> (gs);
+  omp_taskreg_stmt->child_fn = child_fn;
 }
 
 
@@ -4731,9 +4877,9 @@  gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_taskreg_data_arg (const_gimple gs)
 {
-  const gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <const gimple_statement_omp_parallel> (gs);
-  return omp_parallel_stmt->data_arg;
+  const gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <const gimple_statement_omp_taskreg> (gs);
+  return omp_taskreg_stmt->data_arg;
 }
 
 
@@ -4742,9 +4888,9 @@  gimple_omp_taskreg_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_data_arg_ptr (gimple gs)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  return &omp_parallel_stmt->data_arg;
+  gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <gimple_statement_omp_taskreg> (gs);
+  return &omp_taskreg_stmt->data_arg;
 }
 
 
@@ -4753,9 +4899,9 @@  gimple_omp_taskreg_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  omp_parallel_stmt->data_arg = data_arg;
+  gimple_statement_omp_taskreg *omp_taskreg_stmt =
+    as_a <gimple_statement_omp_taskreg> (gs);
+  omp_taskreg_stmt->data_arg = data_arg;
 }
 
 
@@ -4896,9 +5042,9 @@  gimple_omp_single_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_target_clauses (const_gimple gs)
 {
-  const gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <const gimple_statement_omp_parallel> (gs);
-  return omp_parallel_stmt->clauses;
+  const gimple_statement_omp_target *omp_target_stmt =
+    as_a <const gimple_statement_omp_target> (gs);
+  return omp_target_stmt->clauses;
 }
 
 
@@ -4907,9 +5053,9 @@  gimple_omp_target_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_target_clauses_ptr (gimple gs)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  return &omp_parallel_stmt->clauses;
+  gimple_statement_omp_target *omp_target_stmt =
+    as_a <gimple_statement_omp_target> (gs);
+  return &omp_target_stmt->clauses;
 }
 
 
@@ -4918,9 +5064,9 @@  gimple_omp_target_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_clauses (gimple gs, tree clauses)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  omp_parallel_stmt->clauses = clauses;
+  gimple_statement_omp_target *omp_target_stmt =
+    as_a <gimple_statement_omp_target> (gs);
+  omp_target_stmt->clauses = clauses;
 }
 
 
@@ -4950,9 +5096,9 @@  gimple_omp_target_set_kind (gimple g, int kind)
 static inline tree
 gimple_omp_target_child_fn (const_gimple gs)
 {
-  const gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <const gimple_statement_omp_parallel> (gs);
-  return omp_parallel_stmt->child_fn;
+  const gimple_statement_omp_target *omp_target_stmt =
+    as_a <const gimple_statement_omp_target> (gs);
+  return omp_target_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4961,9 +5107,9 @@  gimple_omp_target_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_target_child_fn_ptr (gimple gs)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  return &omp_parallel_stmt->child_fn;
+  gimple_statement_omp_target *omp_target_stmt =
+    as_a <gimple_statement_omp_target> (gs);
+  return &omp_target_stmt->child_fn;
 }
 
 
@@ -4972,9 +5118,9 @@  gimple_omp_target_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  omp_parallel_stmt->child_fn = child_fn;
+  gimple_statement_omp_target *omp_target_stmt =
+    as_a <gimple_statement_omp_target> (gs);
+  omp_target_stmt->child_fn = child_fn;
 }
 
 
@@ -4984,9 +5130,9 @@  gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_target_data_arg (const_gimple gs)
 {
-  const gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <const gimple_statement_omp_parallel> (gs);
-  return omp_parallel_stmt->data_arg;
+  const gimple_statement_omp_target *omp_target_stmt =
+    as_a <const gimple_statement_omp_target> (gs);
+  return omp_target_stmt->data_arg;
 }
 
 
@@ -4995,9 +5141,9 @@  gimple_omp_target_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_target_data_arg_ptr (gimple gs)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  return &omp_parallel_stmt->data_arg;
+  gimple_statement_omp_target *omp_target_stmt =
+    as_a <gimple_statement_omp_target> (gs);
+  return &omp_target_stmt->data_arg;
 }
 
 
@@ -5006,9 +5152,9 @@  gimple_omp_target_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
 {
-  gimple_statement_omp_parallel *omp_parallel_stmt =
-    as_a <gimple_statement_omp_parallel> (gs);
-  omp_parallel_stmt->data_arg = data_arg;
+  gimple_statement_omp_target *omp_target_stmt =
+    as_a <gimple_statement_omp_target> (gs);
+  omp_target_stmt->data_arg = data_arg;
 }
 
 
@@ -5017,9 +5163,9 @@  gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_teams_clauses (const_gimple gs)
 {
-  const gimple_statement_omp_single *omp_single_stmt =
-    as_a <const gimple_statement_omp_single> (gs);
-  return omp_single_stmt->clauses;
+  const gimple_statement_omp_teams *omp_teams_stmt =
+    as_a <const gimple_statement_omp_teams> (gs);
+  return omp_teams_stmt->clauses;
 }
 
 
@@ -5028,9 +5174,9 @@  gimple_omp_teams_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_teams_clauses_ptr (gimple gs)
 {
-  gimple_statement_omp_single *omp_single_stmt =
-    as_a <gimple_statement_omp_single> (gs);
-  return &omp_single_stmt->clauses;
+  gimple_statement_omp_teams *omp_teams_stmt =
+    as_a <gimple_statement_omp_teams> (gs);
+  return &omp_teams_stmt->clauses;
 }
 
 
@@ -5039,9 +5185,9 @@  gimple_omp_teams_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_teams_set_clauses (gimple gs, tree clauses)
 {
-  gimple_statement_omp_single *omp_single_stmt =
-    as_a <gimple_statement_omp_single> (gs);
-  omp_single_stmt->clauses = clauses;
+  gimple_statement_omp_teams *omp_teams_stmt =
+    as_a <gimple_statement_omp_teams> (gs);
+  omp_teams_stmt->clauses = clauses;
 }
 
 
diff --git a/gcc/gsstruct.def b/gcc/gsstruct.def
index 91738f4..82f1f52 100644
--- a/gcc/gsstruct.def
+++ b/gcc/gsstruct.def
@@ -43,11 +43,11 @@  DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false)
 DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
 DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false)
 DEFGSSTRUCT(GSS_OMP_FOR, gimple_statement_omp_for, false)
-DEFGSSTRUCT(GSS_OMP_PARALLEL, gimple_statement_omp_parallel, false)
+DEFGSSTRUCT(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout, false)
 DEFGSSTRUCT(GSS_OMP_TASK, gimple_statement_omp_task, false)
 DEFGSSTRUCT(GSS_OMP_SECTIONS, gimple_statement_omp_sections, false)
-DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_statement_omp_single, false)
+DEFGSSTRUCT(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout, false)
 DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false)
 DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false)
-DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false)
+DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store, false)
 DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false)