public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFC: gimple.[ch] break apart
@ 2013-10-31  5:45 Andrew MacLeod
  2013-10-31  6:15 ` Jeff Law
                   ` (2 more replies)
  0 siblings, 3 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-10-31  5:45 UTC (permalink / raw)
  To: gcc-patches

Hopefully the other attempts to send this aren't queued up...  in any 
case, maybe I can't even attach a .dot file?... So no attachments this 
time...

instead, the diagram is here:
http://gcc.gnu.org/wiki/rearch?action=AttachFile&do=view&target=gimple.png

-------------------------------------------------------------

I've made 4 attempts now to split gimple.[ch] into reasonable component
parts, and I've finally found something that I can make work and fits my
plans.

I've attached a diagram to (hopefully :-) clarify things.

The original purpose of gimple.[ch] was to provide gimple statements.
This replaces the tcc_statement tree kind during the gimplification
process. No other tree kinds have been converted to gimple
structs/classes.  That what the next stage of my project will do.

As a result, any gimple queries regarding types, decls, or expressions
are actually tree queries. They are sprinkled throughout gimple.[ch] and
gimplify.[ch], not to mention tree.[ch] as well as other parts of the
compiler where they happened to be needed.  This has caused various
ordering issues among the inline functions when I tried to split out the
stmt, iterator, and gimplification bits from gimple.[ch].  Not to
mention a lack of an obvious home for some of these functions.

I'd like to move these as I encounter them into a new file,
gimple-decl.[ch].  When I'm working on the other gimple classes, this
will be further split into gimple-decl, gimple-type and gimple-expr as
appropriate but it seems reasonable to create just the one file now to
clump them since there is no other formal organization. So any function
which is actually querying/setting/building a decl, type, or expression
for gimple would go here.

I also want to split out the structure and accessing bits of the gimple
statement structure into gimple-stmt.[ch].  This would be just the
struct decls as well as all the accessing/setting/building functions...

The gimple_stmt_iterators (gsi) themselves also break out into their own
file quite naturally.

I find that gimple_seq does not seem to be a very clearly defined
thing.  Although a gimple_seq is just a typedef for a gimple stmt (I
thought it use to be a container?), it provides some additional
statement queuing functionality.   Ie, you don't have to worry about
next and prev pointers in the stmt's you build, you simply queue them up
and attach them where you want.  In that sense, its a kind of overlay on
top of a gimple-stmt as it provides additional functionality.
gimple_seq also utilizes gimple_smt_iterators under the covers. They do
not expose the iterators to a function using a gimple_seq but they do
need that knowledge to mange the lists under the covers (thus a dashed
line in the diagram).

Its unclear to me whether gimple_seq's are intended to have a future, or
whether their functionality should be rolled right into statements
themselves.  I believe it may be possible to include gimple-iterator.h
in gimple-stmt.c to provide the implementation without affecting the
inheritance layout, although I haven't actually tried that path.

Or we can treat them as a different layer with their own gimple-seq.[ch]
files.

Or we could combine gimple_seq and gsi routines in the same file, but
that would have the downside of exposing the gsi routines to the
gimplifier, which should have no need of.   Either of the latter 2
options seem reasonable to me for now.

The remnants of gimple.[ch] would contain various general helper
routines (walkers, etc), much like tree-ssa.[ch] does for ssa.

And finally gimplify.[ch] would contain all the stuff required for the
front ends to generate gimple code.  This is actually a front end
interface.  At the moment it isn't obvious since all the current gimple
code also uses trees and calls the gimplifier frequently. As I push
gimple types and decls into the back end and remove trees, the backend
should simply generate gimple directly.  Gimplify should slowly become
usable only via tree based front ends...  (Thus the dotted line from BE
to gimplify.. it should be removed eventually)

Which means that all the front end files should be including *only*
gimplify.h, and getting everything they need from there. Currently a
number of them include gimple.h which should not be required.

How reasonable or unreasonable does this sound? :-)  I've been tearing
the file apart in different ways and orders, and this seems to be the
most workable solution I have come up with that doesn't involve hacks.

Andrew


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

* Re: RFC: gimple.[ch] break apart
  2013-10-31  5:45 RFC: gimple.[ch] break apart Andrew MacLeod
@ 2013-10-31  6:15 ` Jeff Law
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
  2013-11-05 16:58 ` [patch] Create gimple-expr..[ch] ... was Re: RFC: gimple.[ch] break apart Andrew MacLeod
  2 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-10-31  6:15 UTC (permalink / raw)
  To: Andrew MacLeod, gcc-patches

On 10/30/13 21:18, Andrew MacLeod wrote:
> Hopefully the other attempts to send this aren't queued up...  in any
> case, maybe I can't even attach a .dot file?... So no attachments this
> time...
>
> instead, the diagram is here:
> http://gcc.gnu.org/wiki/rearch?action=AttachFile&do=view&target=gimple.png
One was queued and went through with attachments :-)
jeff

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

* [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
@ 2013-10-31 16:27   ` David Malcolm
  2013-11-14  9:41     ` Jeff Law
  2013-10-31 16:27   ` [PATCH 1/6] Convert gimple types from a union to C++ inheritance David Malcolm
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-10-31 16:27 UTC (permalink / raw)
  To: gcc-patches, Andrew MacLeod; +Cc: David Malcolm

	* gimple.h (is_a_helper <const gimple_statement_with_ops>::test): New.
	(is_a_helper <gimple_statement_with_ops>::test): New.
	(is_a_helper <const gimple_statement_with_memory_ops>::test): New.
	(is_a_helper <gimple_statement_with_memory_ops>::test): New.
---
 gcc/gimple.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/gcc/gimple.h b/gcc/gimple.h
index f258992..710ce04 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1756,6 +1756,21 @@ gimple_has_ops (const_gimple g)
   return gimple_code (g) >= GIMPLE_COND && gimple_code (g) <= GIMPLE_RETURN;
 }
 
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_with_ops>::test (const_gimple gs)
+{
+  return gimple_has_ops (gs);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_with_ops>::test (gimple gs)
+{
+  return gimple_has_ops (gs);
+}
 
 /* Return true if GIMPLE statement G has memory operands.  */
 
@@ -1765,6 +1780,21 @@ gimple_has_mem_ops (const_gimple g)
   return gimple_code (g) >= GIMPLE_ASSIGN && gimple_code (g) <= GIMPLE_RETURN;
 }
 
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_with_memory_ops>::test (const_gimple gs)
+{
+  return gimple_has_mem_ops (gs);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_with_memory_ops>::test (gimple gs)
+{
+  return gimple_has_mem_ops (gs);
+}
 
 /* Return the set of USE operands for statement G.  */
 
-- 
1.7.11.7

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

* [PATCH 1/6] Convert gimple types from a union to C++ inheritance
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
  2013-10-31 16:27   ` [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types David Malcolm
@ 2013-10-31 16:27   ` David Malcolm
  2013-11-14 23:00     ` Jeff Law
  2013-10-31 16:27   ` [PATCH 2/6] Hand-written port of various accessors within gimple.h David Malcolm
                     ` (7 subsequent siblings)
  9 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-10-31 16:27 UTC (permalink / raw)
  To: gcc-patches, Andrew MacLeod; +Cc: David Malcolm

	* Makefile.in (GIMPLE_H): Add dep on is-a.h.
	* coretypes.h (union gimple_statement_d): Remove declaration.
	(gimple): Convert from being a "union gimple_statement_d *"
	to a "struct gimple_statement_base *".
	(const_gimple): Likewise (with "const").
	* ggc.h (ggc_alloc_cleared_gimple_statement_d_stat): Replace
	with...
	(ggc_alloc_cleared_gimple_statement_stat): ...this.
	* gimple-pretty-print.c (debug): Change parameter from a
	"gimple_statement_d &" to a "gimple_statement_base &".
	(debug): Change parameter from a "gimple_statement_d *" to
	a "gimple_statement_base *".
	* gimple-pretty-print.h (debug): Update declarations as above.
	* gimple.c (gimple_alloc_stat): Update for renaming of
	ggc_alloc_cleared_gimple_statement_d_stat to
	ggc_alloc_cleared_gimple_statement_stat.
	* gimple.h: Include "is-a.h" for use by is_a_helper
	specializations in followup autogenerated patch.
	(struct gimple statement_base): Make this type usable as a base
	class by adding "desc", "tag" and "variable_size" to GTY, thus
	using opting-in to gengtype's support for simple inheritance.
	(gimple_statement_with_ops_base): Convert to a subclass of
	gimple_statement_base, dropping initial "gsbase" field.  Note
	that this type is abstract, with no GSS_ value, and thus no GTY
	tag value.
	(gimple_statement_with_ops): Convert to a subclass of
	gimple_statement_with_ops_base, dropping initial "opbase" field.
	Add tag value to GTY marking.  Update marking of op field to
	reflect how num_ops field is accessed via inheritance.
	(gimple_statement_with_memory_ops_base): Convert to a subclass of
	gimple_statement_with_ops_base, dropping initial "opbase" field.
	Add tag value to GTY marking.
	(gimple_statement_with_memory_ops): Convert to a subclass of
	public gimple_statement_with_memory_ops_base, dropping initial
	"membase" field.  Add tag value to GTY marking.  Update marking
	of op field to reflect how num_ops field is accessed via
	inheritance.
	(gimple_statement_call): Analogous changes that also update the
	marking of the "u" union.
	(gimple_statement_omp): Convert to a subclass of
	gimple_statement_base, dropping initial "gsbase" field, adding
	tag value to GTY marking.
	(gimple_statement_bind): Likewise.
	(gimple_statement_catch): Likewise.
	(gimple_statement_eh_filter): Likewise.
	(gimple_statement_eh_else): Likewise.
	(gimple_statement_eh_mnt): Likewise.
	(gimple_statement_phi): Likewise.
	(gimple_statement_eh_ctrl): Likewise.
	(gimple_statement_try): Likewise.
	(gimple_statement_wce): Likewise.
	(gimple_statement_asm): Convert to a subclass of
	gimple_statement_with_memory_ops_base, dropping initial
	"membase" field, adding tag value to GTY marking, and updating
	marking of op field.
	(gimple_statement_omp_critical): Convert to a subclass of
	gimple_statement_omp, dropping initial "omp" field, adding tag
	value to GTY marking.
	(gimple_statement_omp_for): Likewise.
	(gimple_statement_omp_parallel): Likewise.
	(gimple_statement_omp_task): Convert to a subclass of
	gimple_statement_omp_parallel, dropping initial "par" field,
	adding tag value to GTY marking.
	(gimple_statement_omp_sections): Convert to a subclass of
	gimple_statement_omp, dropping initial "omp" field, adding
	tag value to GTY marking.
	(gimple_statement_omp_continue): Convert to a subclass of
	gimple_statement_base, dropping initial "gsbase" field, adding
	tag value to GTY marking.
	(gimple_statement_omp_single): Convert to a subclass of
	gimple_statement_omp, dropping initial "omp" field, adding
	tag value to GTY marking.
	(gimple_statement_omp_atomic_load): Convert to a subclass of
	gimple_statement_base, dropping initial "gsbase" field, adding
	tag value to GTY marking.
	(gimple_statement_omp_atomic_store): Convert to a subclass of
	gimple_statement_base, dropping initial "gsbase" field, adding
	tag value to GTY marking.
	(gimple_statement_transaction): Convert to a subclass of
	gimple_statement_with_memory_ops_base, dropping initial "gsbase"
	field, adding tag value to GTY marking.
	(union gimple_statement_d): Remove.
	* system.h (CONST_CAST_GIMPLE): Update to use
	"struct gimple_statement_base *" rather than
	"union gimple_statement_d *".
	* tree-ssa-ccp.c (gimple_htab): Convert underlying type from
	gimple_statement_d to gimple_statement_base.
---
 gcc/Makefile.in           |   2 +-
 gcc/coretypes.h           |   5 +-
 gcc/ggc.h                 |   6 +-
 gcc/gimple-pretty-print.c |   4 +-
 gcc/gimple-pretty-print.h |   4 +-
 gcc/gimple.c              |   2 +-
 gcc/gimple.h              | 226 ++++++++++++++++++++++------------------------
 gcc/system.h              |   2 +-
 gcc/tree-ssa-ccp.c        |   2 +-
 9 files changed, 121 insertions(+), 132 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index cc88fb8..7fbb533 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -887,7 +887,7 @@ BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) \
 	cfg-flags.def cfghooks.h
 GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
 	$(GGC_H) $(BASIC_BLOCK_H) $(TREE_H) tree-ssa-operands.h \
-	tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H)
+	tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H) is-a.h
 GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
 RECOG_H = recog.h
 EMIT_RTL_H = emit-rtl.h
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index f7ef8d7..5d60240 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -61,9 +61,8 @@ typedef const struct rtvec_def *const_rtvec;
 union tree_node;
 typedef union tree_node *tree;
 typedef const union tree_node *const_tree;
-union gimple_statement_d;
-typedef union gimple_statement_d *gimple;
-typedef const union gimple_statement_d *const_gimple;
+typedef struct gimple_statement_base *gimple;
+typedef const struct gimple_statement_base *const_gimple;
 typedef gimple gimple_seq;
 struct gimple_stmt_iterator_d;
 typedef struct gimple_stmt_iterator_d gimple_stmt_iterator;
diff --git a/gcc/ggc.h b/gcc/ggc.h
index b31bc80..bb8f939 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -269,10 +269,10 @@ ggc_alloc_cleared_tree_node_stat (size_t s MEM_STAT_DECL)
   return (union tree_node *) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
 }
 
-static inline union gimple_statement_d *
-ggc_alloc_cleared_gimple_statement_d_stat (size_t s MEM_STAT_DECL)
+static inline struct gimple_statement_base *
+ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL)
 {
-  return (union gimple_statement_d *)
+  return (struct gimple_statement_base *)
     ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
 }
 
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 248dfea..881ff04 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -86,13 +86,13 @@ print_gimple_stmt (FILE *file, gimple g, int spc, int flags)
 }
 
 DEBUG_FUNCTION void
-debug (gimple_statement_d &ref)
+debug (gimple_statement_base &ref)
 {
   print_gimple_stmt (stderr, &ref, 0, 0);
 }
 
 DEBUG_FUNCTION void
-debug (gimple_statement_d *ptr)
+debug (gimple_statement_base *ptr)
 {
   if (ptr)
     debug (*ptr);
diff --git a/gcc/gimple-pretty-print.h b/gcc/gimple-pretty-print.h
index 5227eb8..edb23e6 100644
--- a/gcc/gimple-pretty-print.h
+++ b/gcc/gimple-pretty-print.h
@@ -29,8 +29,8 @@ extern void debug_gimple_stmt (gimple);
 extern void debug_gimple_seq (gimple_seq);
 extern void print_gimple_seq (FILE *, gimple_seq, int, int);
 extern void print_gimple_stmt (FILE *, gimple, int, int);
-extern void debug (gimple_statement_d &ref);
-extern void debug (gimple_statement_d *ptr);
+extern void debug (gimple_statement_base &ref);
+extern void debug (gimple_statement_base *ptr);
 extern void print_gimple_expr (FILE *, gimple, int, int);
 extern void pp_gimple_stmt_1 (pretty_printer *, gimple, int, int);
 extern void gimple_dump_bb (FILE *, basic_block, int, int);
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 20f6010..958514c 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -126,7 +126,7 @@ gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
       gimple_alloc_sizes[(int) kind] += size;
     }
 
-  stmt = ggc_alloc_cleared_gimple_statement_d_stat (size PASS_MEM_STAT);
+  stmt = ggc_alloc_cleared_gimple_statement_stat (size PASS_MEM_STAT);
   gimple_set_code (stmt, code);
   gimple_set_num_ops (stmt, num_ops);
 
diff --git a/gcc/gimple.h b/gcc/gimple.h
index b34424c..f288e81 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "internal-fn.h"
 #include "gimple-fold.h"
 #include "tree-eh.h"
+#include "is-a.h"
 
 typedef gimple gimple_seq_node;
 
@@ -158,7 +159,10 @@ struct gimple_stmt_iterator_d
 /* Data structure definitions for GIMPLE tuples.  NOTE: word markers
    are for 64 bit hosts.  */
 
-struct GTY((chain_next ("%h.next"))) gimple_statement_base {
+struct GTY((desc ("gimple_statement_structure (&%h)"), tag ("GSS_BASE"),
+	    chain_next ("%h.next"), variable_size))
+  gimple_statement_base
+{
   /* [ WORD 1 ]
      Main identifying code for a tuple.  */
   ENUM_BITFIELD(gimple_code) code : 8;
@@ -222,10 +226,11 @@ struct GTY((chain_next ("%h.next"))) gimple_statement_base {
 
 /* Base structure for tuples with operands.  */
 
-struct GTY(()) gimple_statement_with_ops_base
+/* This gimple subclass has no tag value.  */
+struct GTY(())
+  gimple_statement_with_ops_base : public gimple_statement_base
 {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]
      SSA operand vectors.  NOTE: It should be possible to
@@ -238,25 +243,25 @@ struct GTY(()) gimple_statement_with_ops_base
 
 /* Statements that take register operands.  */
 
-struct GTY(()) gimple_statement_with_ops
+struct GTY((tag("GSS_WITH_OPS")))
+  gimple_statement_with_ops : public gimple_statement_with_ops_base
 {
-  /* [ WORD 1-7 ]  */
-  struct gimple_statement_with_ops_base opbase;
+  /* [ WORD 1-7 ] : base class */
 
   /* [ WORD 8 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
-  tree GTY((length ("%h.opbase.gsbase.num_ops"))) op[1];
+  tree GTY((length ("%h.num_ops"))) op[1];
 };
 
 
 /* Base for statements that take both memory and register operands.  */
 
-struct GTY(()) gimple_statement_with_memory_ops_base
+struct GTY((tag("GSS_WITH_MEM_OPS_BASE")))
+  gimple_statement_with_memory_ops_base : public gimple_statement_with_ops_base
 {
-  /* [ WORD 1-7 ]  */
-  struct gimple_statement_with_ops_base opbase;
+  /* [ WORD 1-7 ] : base class */
 
   /* [ WORD 8-9 ]
      Virtual operands for this statement.  The GC will pick them
@@ -268,32 +273,33 @@ struct GTY(()) gimple_statement_with_memory_ops_base
 
 /* Statements that take both memory and register operands.  */
 
-struct GTY(()) gimple_statement_with_memory_ops
+struct GTY((tag("GSS_WITH_MEM_OPS")))
+  gimple_statement_with_memory_ops :
+    public gimple_statement_with_memory_ops_base
 {
-  /* [ WORD 1-9 ]  */
-  struct gimple_statement_with_memory_ops_base membase;
+  /* [ WORD 1-9 ] : base class */
 
   /* [ WORD 10 ]
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
-  tree GTY((length ("%h.membase.opbase.gsbase.num_ops"))) op[1];
+  tree GTY((length ("%h.num_ops"))) op[1];
 };
 
 
 /* Call statements that take both memory and register operands.  */
 
-struct GTY(()) gimple_statement_call
+struct GTY((tag("GSS_CALL")))
+  gimple_statement_call : public gimple_statement_with_memory_ops_base
 {
-  /* [ WORD 1-9 ]  */
-  struct gimple_statement_with_memory_ops_base membase;
+  /* [ WORD 1-9 ] : base class */
 
   /* [ WORD 10-13 ]  */
   struct pt_solution call_used;
   struct pt_solution call_clobbered;
 
   /* [ WORD 14 ]  */
-  union GTY ((desc ("%1.membase.opbase.gsbase.subcode & GF_CALL_INTERNAL"))) {
+  union GTY ((desc ("%1.subcode & GF_CALL_INTERNAL"))) {
     tree GTY ((tag ("0"))) fntype;
     enum internal_fn GTY ((tag ("GF_CALL_INTERNAL"))) internal_fn;
   } u;
@@ -302,15 +308,16 @@ struct GTY(()) gimple_statement_call
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
-  tree GTY((length ("%h.membase.opbase.gsbase.num_ops"))) op[1];
+  tree GTY((length ("%h.num_ops"))) op[1];
 };
 
 
 /* OpenMP statements (#pragma omp).  */
 
-struct GTY(()) gimple_statement_omp {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_OMP")))
+  gimple_statement_omp : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]  */
   gimple_seq body;
@@ -319,9 +326,10 @@ struct GTY(()) gimple_statement_omp {
 
 /* GIMPLE_BIND */
 
-struct GTY(()) gimple_statement_bind {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_BIND")))
+  gimple_statement_bind : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]
      Variables declared in this scope.  */
@@ -342,9 +350,10 @@ struct GTY(()) gimple_statement_bind {
 
 /* GIMPLE_CATCH */
 
-struct GTY(()) gimple_statement_catch {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_CATCH")))
+  gimple_statement_catch : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]  */
   tree types;
@@ -356,9 +365,10 @@ struct GTY(()) gimple_statement_catch {
 
 /* GIMPLE_EH_FILTER */
 
-struct GTY(()) gimple_statement_eh_filter {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_EH_FILTER")))
+  gimple_statement_eh_filter : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]
      Filter types.  */
@@ -371,9 +381,10 @@ struct GTY(()) gimple_statement_eh_filter {
 
 /* GIMPLE_EH_ELSE */
 
-struct GTY(()) gimple_statement_eh_else {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_EH_ELSE")))
+  gimple_statement_eh_else : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7,8 ] */
   gimple_seq n_body, e_body;
@@ -381,9 +392,10 @@ struct GTY(()) gimple_statement_eh_else {
 
 /* GIMPLE_EH_MUST_NOT_THROW */
 
-struct GTY(()) gimple_statement_eh_mnt {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_EH_MNT")))
+  gimple_statement_eh_mnt : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ] Abort function decl.  */
   tree fndecl;
@@ -391,9 +403,10 @@ struct GTY(()) gimple_statement_eh_mnt {
 
 /* GIMPLE_PHI */
 
-struct GTY(()) gimple_statement_phi {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_PHI")))
+  gimple_statement_phi : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]  */
   unsigned capacity;
@@ -409,10 +422,10 @@ struct GTY(()) gimple_statement_phi {
 
 /* GIMPLE_RESX, GIMPLE_EH_DISPATCH */
 
-struct GTY(()) gimple_statement_eh_ctrl
+struct GTY((tag("GSS_EH_CTRL")))
+  gimple_statement_eh_ctrl : public gimple_statement_base
 {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]
      Exception region number.  */
@@ -422,9 +435,10 @@ struct GTY(()) gimple_statement_eh_ctrl
 
 /* GIMPLE_TRY */
 
-struct GTY(()) gimple_statement_try {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_TRY")))
+  gimple_statement_try : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]
      Expression to evaluate.  */
@@ -451,9 +465,10 @@ enum gimple_try_flags
 
 /* GIMPLE_WITH_CLEANUP_EXPR */
 
-struct GTY(()) gimple_statement_wce {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_WCE")))
+  gimple_statement_wce : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* Subcode: CLEANUP_EH_ONLY.  True if the cleanup should only be
 	      executed if an exception is thrown, not on normal exit of its
@@ -468,10 +483,10 @@ struct GTY(()) gimple_statement_wce {
 
 /* GIMPLE_ASM  */
 
-struct GTY(()) gimple_statement_asm
+struct GTY((tag("GSS_ASM")))
+  gimple_statement_asm : public gimple_statement_with_memory_ops_base
 {
-  /* [ WORD 1-9 ]  */
-  struct gimple_statement_with_memory_ops_base membase;
+  /* [ WORD 1-9 ] : base class */
 
   /* [ WORD 10 ]
      __asm__ statement.  */
@@ -488,14 +503,15 @@ struct GTY(()) gimple_statement_asm
      Operand vector.  NOTE!  This must always be the last field
      of this structure.  In particular, this means that this
      structure cannot be embedded inside another one.  */
-  tree GTY((length ("%h.membase.opbase.gsbase.num_ops"))) op[1];
+  tree GTY((length ("%h.num_ops"))) op[1];
 };
 
 /* GIMPLE_OMP_CRITICAL */
 
-struct GTY(()) gimple_statement_omp_critical {
-  /* [ WORD 1-7 ]  */
-  struct gimple_statement_omp omp;
+struct GTY((tag("GSS_OMP_CRITICAL")))
+  gimple_statement_omp_critical : public gimple_statement_omp
+{
+  /* [ WORD 1-7 ] : base class */
 
   /* [ WORD 8 ]
      Critical section name.  */
@@ -522,9 +538,10 @@ struct GTY(()) gimple_omp_for_iter {
 
 /* GIMPLE_OMP_FOR */
 
-struct GTY(()) gimple_statement_omp_for {
-  /* [ WORD 1-7 ]  */
-  struct gimple_statement_omp omp;
+struct GTY((tag("GSS_OMP_FOR")))
+  gimple_statement_omp_for : public gimple_statement_omp
+{
+  /* [ WORD 1-7 ] : base class */
 
   /* [ WORD 8 ]  */
   tree clauses;
@@ -544,9 +561,10 @@ struct GTY(()) gimple_statement_omp_for {
 
 /* GIMPLE_OMP_PARALLEL */
 
-struct GTY(()) gimple_statement_omp_parallel {
-  /* [ WORD 1-7 ]  */
-  struct gimple_statement_omp omp;
+struct GTY((tag("GSS_OMP_PARALLEL")))
+  gimple_statement_omp_parallel : public gimple_statement_omp
+{
+  /* [ WORD 1-7 ] : base class */
 
   /* [ WORD 8 ]
      Clauses.  */
@@ -564,9 +582,10 @@ struct GTY(()) gimple_statement_omp_parallel {
 
 /* GIMPLE_OMP_TASK */
 
-struct GTY(()) gimple_statement_omp_task {
-  /* [ WORD 1-10 ]  */
-  struct gimple_statement_omp_parallel par;
+struct GTY((tag("GSS_OMP_TASK")))
+  gimple_statement_omp_task : public gimple_statement_omp_parallel
+{
+  /* [ WORD 1-10 ] : base class */
 
   /* [ WORD 11 ]
      Child function holding firstprivate initialization if needed.  */
@@ -585,9 +604,10 @@ struct GTY(()) gimple_statement_omp_task {
 
 /* GIMPLE_OMP_SECTIONS */
 
-struct GTY(()) gimple_statement_omp_sections {
-  /* [ WORD 1-7 ]  */
-  struct gimple_statement_omp omp;
+struct GTY((tag("GSS_OMP_SECTIONS")))
+  gimple_statement_omp_sections : public gimple_statement_omp
+{
+  /* [ WORD 1-7 ] : base class */
 
   /* [ WORD 8 ]  */
   tree clauses;
@@ -603,9 +623,10 @@ struct GTY(()) gimple_statement_omp_sections {
    Note: This does not inherit from gimple_statement_omp, because we
          do not need the body field.  */
 
-struct GTY(()) gimple_statement_omp_continue {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_OMP_CONTINUE")))
+  gimple_statement_omp_continue : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]  */
   tree control_def;
@@ -616,9 +637,10 @@ struct GTY(()) gimple_statement_omp_continue {
 
 /* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS */
 
-struct GTY(()) gimple_statement_omp_single {
-  /* [ WORD 1-7 ]  */
-  struct gimple_statement_omp omp;
+struct GTY((tag("GSS_OMP_SINGLE")))
+  gimple_statement_omp_single : public gimple_statement_omp
+{
+  /* [ WORD 1-7 ] : base class */
 
   /* [ WORD 7 ]  */
   tree clauses;
@@ -629,9 +651,10 @@ struct GTY(()) gimple_statement_omp_single {
    Note: This is based on gimple_statement_base, not g_s_omp, because g_s_omp
    contains a sequence, which we don't need here.  */
 
-struct GTY(()) gimple_statement_omp_atomic_load {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_OMP_ATOMIC_LOAD")))
+  gimple_statement_omp_atomic_load : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7-8 ]  */
   tree rhs, lhs;
@@ -640,9 +663,10 @@ struct GTY(()) gimple_statement_omp_atomic_load {
 /* GIMPLE_OMP_ATOMIC_STORE.
    See note on GIMPLE_OMP_ATOMIC_LOAD.  */
 
-struct GTY(()) gimple_statement_omp_atomic_store {
-  /* [ WORD 1-6 ]  */
-  struct gimple_statement_base gsbase;
+struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
+  gimple_statement_omp_atomic_store : public gimple_statement_base
+{
+  /* [ WORD 1-6 ] : base class */
 
   /* [ WORD 7 ]  */
   tree val;
@@ -676,10 +700,10 @@ struct GTY(()) gimple_statement_omp_atomic_store {
    likely because it is guaranteed to go irrevocable upon entry.  */
 #define GTMA_HAS_NO_INSTRUMENTATION	(1u << 7)
 
-struct GTY(()) gimple_statement_transaction
+struct GTY((tag("GSS_TRANSACTION")))
+  gimple_statement_transaction : public gimple_statement_with_memory_ops_base
 {
-  /* [ WORD 1-9 ]  */
-  struct gimple_statement_with_memory_ops_base gsbase;
+  /* [ WORD 1-9 ] : base class */
 
   /* [ WORD 10 ] */
   gimple_seq body;
@@ -695,40 +719,6 @@ enum gimple_statement_structure_enum {
 };
 #undef DEFGSSTRUCT
 
-
-/* Define the overall contents of a gimple tuple.  It may be any of the
-   structures declared above for various types of tuples.  */
-
-union GTY ((desc ("gimple_statement_structure (&%h)"),
-	    chain_next ("%h.gsbase.next"), variable_size)) gimple_statement_d {
-  struct gimple_statement_base GTY ((tag ("GSS_BASE"))) gsbase;
-  struct gimple_statement_with_ops GTY ((tag ("GSS_WITH_OPS"))) gsops;
-  struct gimple_statement_with_memory_ops_base GTY ((tag ("GSS_WITH_MEM_OPS_BASE"))) gsmembase;
-  struct gimple_statement_with_memory_ops GTY ((tag ("GSS_WITH_MEM_OPS"))) gsmem;
-  struct gimple_statement_call GTY ((tag ("GSS_CALL"))) gimple_call;
-  struct gimple_statement_omp GTY ((tag ("GSS_OMP"))) omp;
-  struct gimple_statement_bind GTY ((tag ("GSS_BIND"))) gimple_bind;
-  struct gimple_statement_catch GTY ((tag ("GSS_CATCH"))) gimple_catch;
-  struct gimple_statement_eh_filter GTY ((tag ("GSS_EH_FILTER"))) gimple_eh_filter;
-  struct gimple_statement_eh_mnt GTY ((tag ("GSS_EH_MNT"))) gimple_eh_mnt;
-  struct gimple_statement_eh_else GTY ((tag ("GSS_EH_ELSE"))) gimple_eh_else;
-  struct gimple_statement_phi GTY ((tag ("GSS_PHI"))) gimple_phi;
-  struct gimple_statement_eh_ctrl GTY ((tag ("GSS_EH_CTRL"))) gimple_eh_ctrl;
-  struct gimple_statement_try GTY ((tag ("GSS_TRY"))) gimple_try;
-  struct gimple_statement_wce GTY ((tag ("GSS_WCE"))) gimple_wce;
-  struct gimple_statement_asm GTY ((tag ("GSS_ASM"))) gimple_asm;
-  struct gimple_statement_omp_critical GTY ((tag ("GSS_OMP_CRITICAL"))) gimple_omp_critical;
-  struct gimple_statement_omp_for GTY ((tag ("GSS_OMP_FOR"))) gimple_omp_for;
-  struct gimple_statement_omp_parallel GTY ((tag ("GSS_OMP_PARALLEL"))) gimple_omp_parallel;
-  struct gimple_statement_omp_task GTY ((tag ("GSS_OMP_TASK"))) gimple_omp_task;
-  struct gimple_statement_omp_sections GTY ((tag ("GSS_OMP_SECTIONS"))) gimple_omp_sections;
-  struct gimple_statement_omp_single GTY ((tag ("GSS_OMP_SINGLE"))) gimple_omp_single;
-  struct gimple_statement_omp_continue GTY ((tag ("GSS_OMP_CONTINUE"))) gimple_omp_continue;
-  struct gimple_statement_omp_atomic_load GTY ((tag ("GSS_OMP_ATOMIC_LOAD"))) gimple_omp_atomic_load;
-  struct gimple_statement_omp_atomic_store GTY ((tag ("GSS_OMP_ATOMIC_STORE"))) gimple_omp_atomic_store;
-  struct gimple_statement_transaction GTY((tag ("GSS_TRANSACTION"))) gimple_transaction;
-};
-
 /* Offset in bytes to the location of the operand vector.
    Zero if there is no operand vector for this tuple structure.  */
 extern size_t const gimple_ops_offset_[];
diff --git a/gcc/system.h b/gcc/system.h
index a1fc6de..87ebe3c 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1013,7 +1013,7 @@ helper_const_non_const_cast (const char *p)
 #define CONST_CAST_TREE(X) CONST_CAST (union tree_node *, (X))
 #define CONST_CAST_RTX(X) CONST_CAST (struct rtx_def *, (X))
 #define CONST_CAST_BB(X) CONST_CAST (struct basic_block_def *, (X))
-#define CONST_CAST_GIMPLE(X) CONST_CAST (union gimple_statement_d *, (X))
+#define CONST_CAST_GIMPLE(X) CONST_CAST (struct gimple_statement_base *, (X))
 
 /* Activate certain diagnostics as warnings (not errors via the
    -Werror flag).  */
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index d30bd8b..c01af60 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1693,7 +1693,7 @@ evaluate_stmt (gimple stmt)
   return val;
 }
 
-typedef hash_table <pointer_hash <gimple_statement_d> > gimple_htab;
+typedef hash_table <pointer_hash <gimple_statement_base> > gimple_htab;
 
 /* Given a BUILT_IN_STACK_SAVE value SAVED_VAL, insert a clobber of VAR before
    each matching BUILT_IN_STACK_RESTORE.  Mark visited phis in VISITED.  */
-- 
1.7.11.7

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

* [PATCH 2/6] Hand-written port of various accessors within gimple.h
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
  2013-10-31 16:27   ` [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types David Malcolm
  2013-10-31 16:27   ` [PATCH 1/6] Convert gimple types from a union to C++ inheritance David Malcolm
@ 2013-10-31 16:27   ` David Malcolm
  2013-11-14  9:53     ` Jeff Law
  2013-10-31 16:31   ` [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance David Malcolm
                     ` (6 subsequent siblings)
  9 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-10-31 16:27 UTC (permalink / raw)
  To: gcc-patches, Andrew MacLeod; +Cc: David Malcolm

	* gimple.h (gimple_use_ops): Port from union to usage of
	dyn_cast.
	(gimple_set_use_ops): Port from union to usage of as_a.
	(gimple_set_vuse): Likewise.
	(gimple_set_vdef): Likewise.
	(gimple_call_internal_fn): Port from union to a static_cast,
	given that the type has already been asserted.
	(gimple_omp_body_ptr): Port from unchecked union usage to
	a static_cast.
	(gimple_omp_set_body): Likewise.
---
 gcc/gimple.h | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/gcc/gimple.h b/gcc/gimple.h
index f288e81..6ff7602 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1467,9 +1467,11 @@ gimple_has_mem_ops (const_gimple g)
 static inline struct use_optype_d *
 gimple_use_ops (const_gimple g)
 {
-  if (!gimple_has_ops (g))
+  const gimple_statement_with_ops *ops_stmt =
+    dyn_cast <const gimple_statement_with_ops> (g);
+  if (!ops_stmt)
     return NULL;
-  return g->gsops.opbase.use_ops;
+  return ops_stmt->use_ops;
 }
 
 
@@ -1478,8 +1480,9 @@ gimple_use_ops (const_gimple g)
 static inline void
 gimple_set_use_ops (gimple g, struct use_optype_d *use)
 {
-  gcc_gimple_checking_assert (gimple_has_ops (g));
-  g->gsops.opbase.use_ops = use;
+  gimple_statement_with_ops *ops_stmt =
+    as_a <gimple_statement_with_ops> (g);
+  ops_stmt->use_ops = use;
 }
 
 
@@ -1528,8 +1531,9 @@ gimple_vdef_ptr (gimple g)
 static inline void
 gimple_set_vuse (gimple g, tree vuse)
 {
-  gcc_gimple_checking_assert (gimple_has_mem_ops (g));
-  g->gsmembase.vuse = vuse;
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+    as_a <gimple_statement_with_memory_ops> (g);
+  mem_ops_stmt->vuse = vuse;
 }
 
 /* Set the single VDEF operand of the statement G.  */
@@ -1537,8 +1541,9 @@ gimple_set_vuse (gimple g, tree vuse)
 static inline void
 gimple_set_vdef (gimple g, tree vdef)
 {
-  gcc_gimple_checking_assert (gimple_has_mem_ops (g));
-  g->gsmembase.vdef = vdef;
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+    as_a <gimple_statement_with_memory_ops> (g);
+  mem_ops_stmt->vdef = vdef;
 }
 
 
@@ -2226,7 +2231,7 @@ static inline enum internal_fn
 gimple_call_internal_fn (const_gimple gs)
 {
   gcc_gimple_checking_assert (gimple_call_internal_p (gs));
-  return gs->gimple_call.u.internal_fn;
+  return static_cast <const gimple_statement_call *> (gs)->u.internal_fn;
 }
 
 
@@ -4031,7 +4036,7 @@ get_lineno (const_gimple stmt)
 static inline gimple_seq *
 gimple_omp_body_ptr (gimple gs)
 {
-  return &gs->omp.body;
+  return &static_cast <gimple_statement_omp *> (gs)->body;
 }
 
 /* Return the body for the OMP statement GS.  */
@@ -4047,7 +4052,7 @@ gimple_omp_body (gimple gs)
 static inline void
 gimple_omp_set_body (gimple gs, gimple_seq body)
 {
-  gs->omp.body = body;
+  static_cast <gimple_statement_omp *> (gs)->body = body;
 }
 
 
-- 
1.7.11.7

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

* [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
                     ` (2 preceding siblings ...)
  2013-10-31 16:27   ` [PATCH 2/6] Hand-written port of various accessors within gimple.h David Malcolm
@ 2013-10-31 16:31   ` David Malcolm
  2013-11-14  9:43     ` Jeff Law
  2013-10-31 16:46   ` [PATCH 6/6] Update gdb hooks to reflect changes to " David Malcolm
                     ` (5 subsequent siblings)
  9 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-10-31 16:31 UTC (permalink / raw)
  To: gcc-patches, Andrew MacLeod; +Cc: David Malcolm

gcc/

	Patch autogenerated by refactor_gimple.py from
	https://github.com/davidmalcolm/gcc-refactoring-scripts
	revision 74cd3d5f06565c318749d0fb9f35b565dae28daa

	* gimple-iterator.c (update_bb_for_stmts): Update for conversion of
	gimple types to a true class hierarchy.
	(update_call_edge_frequencies): Likewise.
	(gsi_insert_seq_nodes_before): Likewise.
	(gsi_insert_seq_nodes_after): Likewise.
	(gsi_split_seq_after): Likewise.
	(gsi_set_stmt): Likewise.
	(gsi_split_seq_before): Likewise.
	(gsi_remove): Likewise.
	* gimple-pretty-print.c (dump_gimple_debug): Likewise.
	* gimple-ssa.h (gimple_vuse_op): Likewise.
	(gimple_vdef_op): Likewise.
	* gimple-streamer-in.c (input_gimple_stmt): Likewise.
	* gimple-streamer-out.c (output_gimple_stmt): Likewise.
	* gimple.c (gimple_set_code): Likewise.
	(gimple_alloc_stat): Likewise.
	(gimple_set_subcode): Likewise.
	(gimple_build_call_internal_1): Likewise.
	(gimple_check_failed): Likewise.
	(gimple_call_flags): Likewise.
	(gimple_set_bb): Likewise.
	* gimple.h (is_a_helper <gimple_statement_asm> (gimple)): New.
	(is_a_helper <gimple_statement_bind> (gimple)): Likewise.
	(is_a_helper <gimple_statement_call> (gimple)): Likewise.
	(is_a_helper <gimple_statement_catch> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_ctrl> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_else> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_filter> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_mnt> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_atomic_load> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_atomic_store> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_continue> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_critical> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_for> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_parallel> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_sections> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_single> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_task> (gimple)): Likewise.
	(is_a_helper <gimple_statement_phi> (gimple)): Likewise.
	(is_a_helper <gimple_statement_transaction> (gimple)): Likewise.
	(is_a_helper <gimple_statement_try> (gimple)): Likewise.
	(is_a_helper <gimple_statement_wce> (gimple)): Likewise.
	(is_a_helper <const gimple_statement_asm> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_bind> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_call> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_catch> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_eh_ctrl> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_eh_filter> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_atomic_load> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_atomic_store>
	(const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_omp_continue> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_critical> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_for> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_parallel> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_sections> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_single> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_task> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_phi> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_transaction> (const_gimple)):
	Likewise.
	(gimple_seq_last): Update for conversion of gimple types to a true
	class hierarchy.
	(gimple_seq_set_last): Likewise.
	(gimple_code): Likewise.
	(gimple_bb): Likewise.
	(gimple_block): Likewise.
	(gimple_set_block): Likewise.
	(gimple_location): Likewise.
	(gimple_location_ptr): Likewise.
	(gimple_set_location): Likewise.
	(gimple_no_warning_p): Likewise.
	(gimple_set_no_warning): Likewise.
	(gimple_set_visited): Likewise.
	(gimple_visited_p): Likewise.
	(gimple_set_plf): Likewise.
	(gimple_plf): Likewise.
	(gimple_set_uid): Likewise.
	(gimple_uid): Likewise.
	(gimple_init_singleton): Likewise.
	(gimple_modified_p): Likewise.
	(gimple_set_modified): Likewise.
	(gimple_expr_code): Likewise.
	(gimple_has_volatile_ops): Likewise.
	(gimple_set_has_volatile_ops): Likewise.
	(gimple_omp_subcode): Likewise.
	(gimple_omp_set_subcode): Likewise.
	(gimple_omp_return_set_nowait): Likewise.
	(gimple_omp_section_set_last): Likewise.
	(gimple_omp_parallel_set_combined_p): Likewise.
	(gimple_omp_atomic_set_need_value): Likewise.
	(gimple_omp_atomic_set_seq_cst): Likewise.
	(gimple_num_ops): Likewise.
	(gimple_set_num_ops): Likewise.
	(gimple_assign_nontemporal_move_p): Likewise.
	(gimple_assign_set_nontemporal_move): Likewise.
	(gimple_assign_rhs_code): Likewise.
	(gimple_assign_set_rhs_code): Likewise.
	(gimple_call_internal_p): Likewise.
	(gimple_call_set_tail): Likewise.
	(gimple_call_tail_p): Likewise.
	(gimple_call_set_return_slot_opt): Likewise.
	(gimple_call_return_slot_opt_p): Likewise.
	(gimple_call_set_from_thunk): Likewise.
	(gimple_call_from_thunk_p): Likewise.
	(gimple_call_set_va_arg_pack): Likewise.
	(gimple_call_va_arg_pack_p): Likewise.
	(gimple_call_set_nothrow): Likewise.
	(gimple_call_set_alloca_for_var): Likewise.
	(gimple_call_alloca_for_var_p): Likewise.
	(gimple_call_copy_flags): Likewise.
	(gimple_cond_code): Likewise.
	(gimple_cond_set_code): Likewise.
	(gimple_cond_make_false): Likewise.
	(gimple_cond_make_true): Likewise.
	(gimple_asm_volatile_p): Likewise.
	(gimple_asm_set_volatile): Likewise.
	(gimple_asm_set_input): Likewise.
	(gimple_asm_input_p): Likewise.
	(gimple_try_kind): Likewise.
	(gimple_try_set_kind): Likewise.
	(gimple_try_catch_is_cleanup): Likewise.
	(gimple_try_set_catch_is_cleanup): Likewise.
	(gimple_wce_cleanup_eh_only): Likewise.
	(gimple_wce_set_cleanup_eh_only): Likewise.
	(gimple_debug_bind_p): Likewise.
	(gimple_debug_source_bind_p): Likewise.
	(gimple_omp_for_set_kind): Likewise.
	(gimple_omp_for_set_combined_p): Likewise.
	(gimple_omp_for_set_combined_into_p): Likewise.
	(gimple_omp_target_set_kind): Likewise.
	(gimple_transaction_subcode): Likewise.
	(gimple_transaction_set_subcode): Likewise.
	(gimple_predict_predictor): Likewise.
	(gimple_predict_set_predictor): Likewise.
	(gimple_predict_outcome): Likewise.
	(gimple_predict_set_outcome): Likewise.
	(gsi_one_before_end_p): Likewise.
	(gsi_next): Likewise.
	(gsi_prev): Likewise.
	(gimple_transaction_set_label): Likewise.
	(gimple_transaction_set_body): Likewise.
	(gimple_transaction_label_ptr): Likewise.
	(gimple_transaction_label): Likewise.
	(gimple_transaction_body_ptr): Likewise.
	(gimple_omp_continue_set_control_use): Likewise.
	(gimple_omp_continue_control_use_ptr): Likewise.
	(gimple_omp_continue_control_use): Likewise.
	(gimple_omp_continue_set_control_def): Likewise.
	(gimple_omp_continue_control_def_ptr): Likewise.
	(gimple_omp_continue_control_def): Likewise.
	(gimple_omp_atomic_load_rhs_ptr): Likewise.
	(gimple_omp_atomic_load_rhs): Likewise.
	(gimple_omp_atomic_load_set_rhs): Likewise.
	(gimple_omp_atomic_load_lhs_ptr): Likewise.
	(gimple_omp_atomic_load_lhs): Likewise.
	(gimple_omp_atomic_load_set_lhs): Likewise.
	(gimple_omp_atomic_store_val_ptr): Likewise.
	(gimple_omp_atomic_store_val): Likewise.
	(gimple_omp_atomic_store_set_val): Likewise.
	(gimple_omp_for_cond): Likewise.
	(gimple_omp_for_set_cond): Likewise.
	(gimple_omp_sections_set_control): Likewise.
	(gimple_omp_sections_control_ptr): Likewise.
	(gimple_omp_sections_control): Likewise.
	(gimple_omp_sections_set_clauses): Likewise.
	(gimple_omp_sections_clauses_ptr): Likewise.
	(gimple_omp_sections_clauses): Likewise.
	(gimple_omp_teams_set_clauses): Likewise.
	(gimple_omp_teams_clauses_ptr): Likewise.
	(gimple_omp_teams_clauses): Likewise.
	(gimple_omp_target_set_data_arg): Likewise.
	(gimple_omp_target_data_arg_ptr): Likewise.
	(gimple_omp_target_data_arg): Likewise.
	(gimple_omp_target_set_child_fn): Likewise.
	(gimple_omp_target_child_fn_ptr): Likewise.
	(gimple_omp_target_child_fn): Likewise.
	(gimple_omp_target_set_clauses): Likewise.
	(gimple_omp_target_clauses_ptr): Likewise.
	(gimple_omp_target_clauses): Likewise.
	(gimple_omp_single_set_clauses): Likewise.
	(gimple_omp_single_clauses_ptr): Likewise.
	(gimple_omp_single_clauses): Likewise.
	(gimple_omp_task_set_arg_align): Likewise.
	(gimple_omp_task_arg_align_ptr): Likewise.
	(gimple_omp_task_arg_align): Likewise.
	(gimple_omp_task_set_arg_size): Likewise.
	(gimple_omp_task_arg_size_ptr): Likewise.
	(gimple_omp_task_arg_size): Likewise.
	(gimple_omp_task_set_copy_fn): Likewise.
	(gimple_omp_task_copy_fn_ptr): Likewise.
	(gimple_omp_task_copy_fn): Likewise.
	(gimple_omp_task_set_data_arg): Likewise.
	(gimple_omp_task_data_arg_ptr): Likewise.
	(gimple_omp_task_data_arg): Likewise.
	(gimple_omp_task_set_child_fn): Likewise.
	(gimple_omp_task_child_fn_ptr): Likewise.
	(gimple_omp_task_child_fn): Likewise.
	(gimple_omp_task_set_clauses): Likewise.
	(gimple_omp_task_clauses_ptr): Likewise.
	(gimple_omp_task_clauses): Likewise.
	(gimple_omp_parallel_set_data_arg): Likewise.
	(gimple_omp_parallel_data_arg_ptr): Likewise.
	(gimple_omp_parallel_data_arg): Likewise.
	(gimple_omp_parallel_set_child_fn): Likewise.
	(gimple_omp_parallel_child_fn_ptr): Likewise.
	(gimple_omp_parallel_child_fn): Likewise.
	(gimple_omp_parallel_set_clauses): Likewise.
	(gimple_omp_parallel_clauses_ptr): Likewise.
	(gimple_omp_parallel_clauses): Likewise.
	(gimple_omp_for_set_pre_body): Likewise.
	(gimple_omp_for_pre_body_ptr): Likewise.
	(gimple_omp_for_set_incr): Likewise.
	(gimple_omp_for_incr_ptr): Likewise.
	(gimple_omp_for_incr): Likewise.
	(gimple_omp_for_set_final): Likewise.
	(gimple_omp_for_final_ptr): Likewise.
	(gimple_omp_for_final): Likewise.
	(gimple_omp_for_set_initial): Likewise.
	(gimple_omp_for_initial_ptr): Likewise.
	(gimple_omp_for_initial): Likewise.
	(gimple_omp_for_set_index): Likewise.
	(gimple_omp_for_index_ptr): Likewise.
	(gimple_omp_for_index): Likewise.
	(gimple_omp_for_collapse): Likewise.
	(gimple_omp_for_set_clauses): Likewise.
	(gimple_omp_for_clauses_ptr): Likewise.
	(gimple_omp_for_clauses): Likewise.
	(gimple_omp_critical_set_name): Likewise.
	(gimple_omp_critical_name_ptr): Likewise.
	(gimple_omp_critical_name): Likewise.
	(gimple_eh_dispatch_set_region): Likewise.
	(gimple_eh_dispatch_region): Likewise.
	(gimple_resx_set_region): Likewise.
	(gimple_resx_region): Likewise.
	(gimple_phi_set_arg): Likewise.
	(gimple_phi_arg): Likewise.
	(gimple_phi_set_result): Likewise.
	(gimple_phi_result_ptr): Likewise.
	(gimple_phi_result): Likewise.
	(gimple_phi_num_args): Likewise.
	(gimple_phi_capacity): Likewise.
	(gimple_wce_set_cleanup): Likewise.
	(gimple_wce_cleanup_ptr): Likewise.
	(gimple_try_set_cleanup): Likewise.
	(gimple_try_set_eval): Likewise.
	(gimple_try_cleanup_ptr): Likewise.
	(gimple_try_eval_ptr): Likewise.
	(gimple_eh_else_set_e_body): Likewise.
	(gimple_eh_else_set_n_body): Likewise.
	(gimple_eh_else_e_body_ptr): Likewise.
	(gimple_eh_else_n_body_ptr): Likewise.
	(gimple_eh_must_not_throw_set_fndecl): Likewise.
	(gimple_eh_must_not_throw_fndecl): Likewise.
	(gimple_eh_filter_set_failure): Likewise.
	(gimple_eh_filter_set_types): Likewise.
	(gimple_eh_filter_failure_ptr): Likewise.
	(gimple_eh_filter_types_ptr): Likewise.
	(gimple_eh_filter_types): Likewise.
	(gimple_catch_set_handler): Likewise.
	(gimple_catch_set_types): Likewise.
	(gimple_catch_handler_ptr): Likewise.
	(gimple_catch_types_ptr): Likewise.
	(gimple_catch_types): Likewise.
	(gimple_asm_string): Likewise.
	(gimple_asm_set_label_op): Likewise.
	(gimple_asm_label_op): Likewise.
	(gimple_asm_set_clobber_op): Likewise.
	(gimple_asm_clobber_op): Likewise.
	(gimple_asm_set_output_op): Likewise.
	(gimple_asm_output_op_ptr): Likewise.
	(gimple_asm_output_op): Likewise.
	(gimple_asm_set_input_op): Likewise.
	(gimple_asm_input_op_ptr): Likewise.
	(gimple_asm_input_op): Likewise.
	(gimple_asm_nlabels): Likewise.
	(gimple_asm_nclobbers): Likewise.
	(gimple_asm_noutputs): Likewise.
	(gimple_asm_ninputs): Likewise.
	(gimple_bind_set_block): Likewise.
	(gimple_bind_block): Likewise.
	(gimple_bind_add_seq): Likewise.
	(gimple_bind_add_stmt): Likewise.
	(gimple_bind_set_body): Likewise.
	(gimple_bind_body_ptr): Likewise.
	(gimple_bind_append_vars): Likewise.
	(gimple_bind_set_vars): Likewise.
	(gimple_bind_vars): Likewise.
	(gimple_call_clobber_set): Likewise.
	(gimple_call_use_set): Likewise.
	(gimple_call_set_internal_fn): Likewise.
	(gimple_call_set_fntype): Likewise.
	(gimple_call_fntype): Likewise.
	(gimple_omp_return_lhs_ptr): Likewise.
	(gimple_omp_return_lhs): Likewise.
	(gimple_omp_return_set_lhs): Likewise.
	(gimple_omp_taskreg_set_data_arg): Likewise.
	(gimple_omp_taskreg_data_arg_ptr): Likewise.
	(gimple_omp_taskreg_data_arg): Likewise.
	(gimple_omp_taskreg_set_child_fn): Likewise.
	(gimple_omp_taskreg_child_fn_ptr): Likewise.
	(gimple_omp_taskreg_child_fn): Likewise.
	(gimple_omp_taskreg_set_clauses): Likewise.
	(gimple_omp_taskreg_clauses_ptr): Likewise.
	(gimple_omp_taskreg_clauses): Likewise.
	(gimple_vuse): Likewise.
	(gimple_vdef): Likewise.
	(gimple_vuse_ptr): Likewise.
	(gimple_vdef_ptr): Likewise.
	* tree-inline.c (copy_debug_stmt): Likewise.
	* tree-phinodes.c (make_phi_node): Likewise.
---
 gcc/gimple-iterator.c     |   72 +--
 gcc/gimple-pretty-print.c |    2 +-
 gcc/gimple-ssa.h          |   16 +-
 gcc/gimple-streamer-in.c  |    8 +-
 gcc/gimple-streamer-out.c |    2 +-
 gcc/gimple.c              |   16 +-
 gcc/gimple.h              | 1369 ++++++++++++++++++++++++++++++---------------
 gcc/tree-inline.c         |    2 +-
 gcc/tree-phinodes.c       |    2 +-
 9 files changed, 965 insertions(+), 524 deletions(-)

diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
index e430050..ed0d6df 100644
--- a/gcc/gimple-iterator.c
+++ b/gcc/gimple-iterator.c
@@ -67,7 +67,7 @@ update_bb_for_stmts (gimple_seq_node first, gimple_seq_node last,
 {
   gimple_seq_node n;
 
-  for (n = first; n; n = n->gsbase.next)
+  for (n = first; n; n = n->next)
     {
       gimple_set_bb (n, bb);
       if (n == last)
@@ -85,7 +85,7 @@ update_call_edge_frequencies (gimple_seq_node first, basic_block bb)
   int bb_freq = 0;
   gimple_seq_node n;
 
-  for (n = first; n ; n = n->gsbase.next)
+  for (n = first; n ; n = n->next)
     if (is_gimple_call (n))
       {
 	struct cgraph_edge *e;
@@ -123,7 +123,7 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
   basic_block bb;
   gimple_seq_node cur = i->ptr;
 
-  gcc_assert (!cur || cur->gsbase.prev);
+  gcc_assert (!cur || cur->prev);
 
   if ((bb = gsi_bb (*i)) != NULL)
     update_bb_for_stmts (first, last, bb);
@@ -131,13 +131,13 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
   /* Link SEQ before CUR in the sequence.  */
   if (cur)
     {
-      first->gsbase.prev = cur->gsbase.prev;
-      if (first->gsbase.prev->gsbase.next)
-	first->gsbase.prev->gsbase.next = first;
+      first->prev = cur->prev;
+      if (first->prev->next)
+	first->prev->next = first;
       else
 	gimple_seq_set_first (i->seq, first);
-      last->gsbase.next = cur;
-      cur->gsbase.prev = last;
+      last->next = cur;
+      cur->prev = last;
     }
   else
     {
@@ -148,11 +148,11 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
 	 labels, so it returns an iterator after the end of the block, and
 	 we need to insert before it; it might be cleaner to add a flag to the
 	 iterator saying whether we are at the start or end of the list).  */
-      last->gsbase.next = NULL;
+      last->next = NULL;
       if (itlast)
 	{
-	  first->gsbase.prev = itlast;
-	  itlast->gsbase.next = first;
+	  first->prev = itlast;
+	  itlast->next = first;
 	}
       else
 	gimple_seq_set_first (i->seq, first);
@@ -241,7 +241,7 @@ gsi_insert_seq_nodes_after (gimple_stmt_iterator *i,
   basic_block bb;
   gimple_seq_node cur = i->ptr;
 
-  gcc_assert (!cur || cur->gsbase.prev);
+  gcc_assert (!cur || cur->prev);
 
   /* If the iterator is inside a basic block, we need to update the
      basic block information for all the nodes between FIRST and LAST.  */
@@ -251,20 +251,20 @@ gsi_insert_seq_nodes_after (gimple_stmt_iterator *i,
   /* Link SEQ after CUR.  */
   if (cur)
     {
-      last->gsbase.next = cur->gsbase.next;
-      if (last->gsbase.next)
+      last->next = cur->next;
+      if (last->next)
 	{
-	  last->gsbase.next->gsbase.prev = last;
+	  last->next->prev = last;
 	}
       else
 	gimple_seq_set_last (i->seq, last);
-      first->gsbase.prev = cur;
-      cur->gsbase.next = first;
+      first->prev = cur;
+      cur->next = first;
     }
   else
     {
       gcc_assert (!gimple_seq_last (*i->seq));
-      last->gsbase.next = NULL;
+      last->next = NULL;
       gimple_seq_set_first (i->seq, first);
       gimple_seq_set_last (i->seq, last);
     }
@@ -346,15 +346,15 @@ gsi_split_seq_after (gimple_stmt_iterator i)
   cur = i.ptr;
 
   /* How can we possibly split after the end, or before the beginning?  */
-  gcc_assert (cur && cur->gsbase.next);
-  next = cur->gsbase.next;
+  gcc_assert (cur && cur->next);
+  next = cur->next;
 
   pold_seq = i.seq;
 
   gimple_seq_set_first (&new_seq, next);
   gimple_seq_set_last (&new_seq, gimple_seq_last (*pold_seq));
   gimple_seq_set_last (pold_seq, cur);
-  cur->gsbase.next = NULL;
+  cur->next = NULL;
 
   return new_seq;
 }
@@ -370,17 +370,17 @@ gsi_set_stmt (gimple_stmt_iterator *gsi, gimple stmt)
   gimple orig_stmt = gsi_stmt (*gsi);
   gimple prev, next;
 
-  stmt->gsbase.next = next = orig_stmt->gsbase.next;
-  stmt->gsbase.prev = prev = orig_stmt->gsbase.prev;
+  stmt->next = next = orig_stmt->next;
+  stmt->prev = prev = orig_stmt->prev;
   /* Note how we don't clear next/prev of orig_stmt.  This is so that
      copies of *GSI our callers might still hold (to orig_stmt)
      can be advanced as if they too were replaced.  */
-  if (prev->gsbase.next)
-    prev->gsbase.next = stmt;
+  if (prev->next)
+    prev->next = stmt;
   else
     gimple_seq_set_first (gsi->seq, stmt);
   if (next)
-    next->gsbase.prev = stmt;
+    next->prev = stmt;
   else
     gimple_seq_set_last (gsi->seq, stmt);
 
@@ -401,10 +401,10 @@ gsi_split_seq_before (gimple_stmt_iterator *i, gimple_seq *pnew_seq)
 
   /* How can we possibly split after the end?  */
   gcc_assert (cur);
-  prev = cur->gsbase.prev;
+  prev = cur->prev;
 
   old_seq = *i->seq;
-  if (!prev->gsbase.next)
+  if (!prev->next)
     *i->seq = NULL;
   i->seq = pnew_seq;
 
@@ -414,8 +414,8 @@ gsi_split_seq_before (gimple_stmt_iterator *i, gimple_seq *pnew_seq)
 
   /* Cut OLD_SEQ before I.  */
   gimple_seq_set_last (&old_seq, prev);
-  if (prev->gsbase.next)
-    prev->gsbase.next = NULL;
+  if (prev->next)
+    prev->next = NULL;
 }
 
 
@@ -575,20 +575,20 @@ gsi_remove (gimple_stmt_iterator *i, bool remove_permanently)
 
   /* Update the iterator and re-wire the links in I->SEQ.  */
   cur = i->ptr;
-  next = cur->gsbase.next;
-  prev = cur->gsbase.prev;
+  next = cur->next;
+  prev = cur->prev;
   /* See gsi_set_stmt for why we don't reset prev/next of STMT.  */
 
   if (next)
     /* Cur is not last.  */
-    next->gsbase.prev = prev;
-  else if (prev->gsbase.next)
+    next->prev = prev;
+  else if (prev->next)
     /* Cur is last but not first.  */
     gimple_seq_set_last (i->seq, prev);
 
-  if (prev->gsbase.next)
+  if (prev->next)
     /* Cur is not first.  */
-    prev->gsbase.next = next;
+    prev->next = next;
   else
     /* Cur is first.  */
     *i->seq = next;
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 881ff04..b9bbdc7 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1061,7 +1061,7 @@ dump_gimple_eh_dispatch (pretty_printer *buffer, gimple gs, int spc, int flags)
 static void
 dump_gimple_debug (pretty_printer *buffer, gimple gs, int spc, int flags)
 {
-  switch (gs->gsbase.subcode)
+  switch (gs->subcode)
     {
     case GIMPLE_DEBUG_BIND:
       if (flags & TDF_RAW)
diff --git a/gcc/gimple-ssa.h b/gcc/gimple-ssa.h
index 23aa099..50b48bb 100644
--- a/gcc/gimple-ssa.h
+++ b/gcc/gimple-ssa.h
@@ -108,11 +108,13 @@ static inline use_operand_p
 gimple_vuse_op (const_gimple g)
 {
   struct use_optype_d *ops;
-  if (!gimple_has_mem_ops (g))
+  const gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <const gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_USE_OPERAND_P;
-  ops = g->gsops.opbase.use_ops;
+  ops = mem_ops_stmt->use_ops;
   if (ops
-      && USE_OP_PTR (ops)->use == &g->gsmembase.vuse)
+      && USE_OP_PTR (ops)->use == &mem_ops_stmt->vuse)
     return USE_OP_PTR (ops);
   return NULL_USE_OPERAND_P;
 }
@@ -122,10 +124,12 @@ gimple_vuse_op (const_gimple g)
 static inline def_operand_p
 gimple_vdef_op (gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_DEF_OPERAND_P;
-  if (g->gsmembase.vdef)
-    return &g->gsmembase.vdef;
+  if (mem_ops_stmt->vdef)
+    return &mem_ops_stmt->vdef;
   return NULL_DEF_OPERAND_P;
 }
 
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index 2a19aab..4f31b83 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -98,12 +98,12 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
   bp = streamer_read_bitpack (ib);
   num_ops = bp_unpack_var_len_unsigned (&bp);
   stmt = gimple_alloc (code, num_ops);
-  stmt->gsbase.no_warning = bp_unpack_value (&bp, 1);
+  stmt->no_warning = bp_unpack_value (&bp, 1);
   if (is_gimple_assign (stmt))
-    stmt->gsbase.nontemporal_move = bp_unpack_value (&bp, 1);
-  stmt->gsbase.has_volatile_ops = bp_unpack_value (&bp, 1);
+    stmt->nontemporal_move = bp_unpack_value (&bp, 1);
+  stmt->has_volatile_ops = bp_unpack_value (&bp, 1);
   has_hist = bp_unpack_value (&bp, 1);
-  stmt->gsbase.subcode = bp_unpack_var_len_unsigned (&bp);
+  stmt->subcode = bp_unpack_var_len_unsigned (&bp);
 
   /* Read location information.  */
   gimple_set_location (stmt, stream_input_location (&bp, data_in));
diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index 976f57e..e7a7de0 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -77,7 +77,7 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
   bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
   hist = gimple_histogram_value (cfun, stmt);
   bp_pack_value (&bp, hist != NULL, 1);
-  bp_pack_var_len_unsigned (&bp, stmt->gsbase.subcode);
+  bp_pack_var_len_unsigned (&bp, stmt->subcode);
 
   /* Emit location information for the statement.  */
   stream_output_location (ob, &bp, LOCATION_LOCUS (gimple_location (stmt)));
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 958514c..9b1337a 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -94,7 +94,7 @@ extern void gimple_set_loaded_syms (gimple, bitmap, bitmap_obstack *);
 static inline void
 gimple_set_code (gimple g, enum gimple_code code)
 {
-  g->gsbase.code = code;
+  g->code = code;
 }
 
 /* Return the number of bytes needed to hold a GIMPLE statement with
@@ -132,7 +132,7 @@ gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
 
   /* Do not call gimple_set_modified here as it has other side
      effects and this tuple is still not completely built.  */
-  stmt->gsbase.modified = 1;
+  stmt->modified = 1;
   gimple_init_singleton (stmt);
 
   return stmt;
@@ -146,7 +146,7 @@ gimple_set_subcode (gimple g, unsigned subcode)
   /* We only have 16 bits for the RHS code.  Assert that we are not
      overflowing it.  */
   gcc_assert (subcode < (1 << 16));
-  g->gsbase.subcode = subcode;
+  g->subcode = subcode;
 }
 
 
@@ -281,7 +281,7 @@ static inline gimple
 gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
 {
   gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
-  s->gsbase.subcode |= GF_CALL_INTERNAL;
+  s->subcode |= GF_CALL_INTERNAL;
   gimple_call_set_internal_fn (s, fn);
   gimple_call_reset_alias_info (s);
   return s;
@@ -1222,8 +1222,8 @@ gimple_check_failed (const_gimple gs, const char *file, int line,
       		  gimple_code_name[code],
 		  get_tree_code_name (subcode),
 		  gimple_code_name[gimple_code (gs)],
-		  gs->gsbase.subcode > 0
-		    ? get_tree_code_name ((enum tree_code) gs->gsbase.subcode)
+		  gs->subcode > 0
+		    ? get_tree_code_name ((enum tree_code) gs->subcode)
 		    : "",
 		  function, trim_filename (file), line);
 }
@@ -1975,7 +1975,7 @@ gimple_call_flags (const_gimple stmt)
   else
     flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
 
-  if (stmt->gsbase.subcode & GF_CALL_NOTHROW)
+  if (stmt->subcode & GF_CALL_NOTHROW)
     flags |= ECF_NOTHROW;
 
   return flags;
@@ -2116,7 +2116,7 @@ gimple_assign_unary_nop_p (gimple gs)
 void
 gimple_set_bb (gimple stmt, basic_block bb)
 {
-  stmt->gsbase.bb = bb;
+  stmt->bb = bb;
 
   /* If the statement is a label, add the label to block-to-labels map
      so that we can speed up edge creation for GIMPLE_GOTOs.  */
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 6ff7602..f258992 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -719,6 +719,310 @@ enum gimple_statement_structure_enum {
 };
 #undef DEFGSSTRUCT
 
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_asm>::test (gimple gs)
+{
+  return gs->code == GIMPLE_ASM;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_bind>::test (gimple gs)
+{
+  return gs->code == GIMPLE_BIND;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_call>::test (gimple gs)
+{
+  return gs->code == GIMPLE_CALL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_catch>::test (gimple gs)
+{
+  return gs->code == GIMPLE_CATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_ctrl>::test (gimple gs)
+{
+  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_else>::test (gimple gs)
+{
+  return gs->code == GIMPLE_EH_ELSE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_filter>::test (gimple gs)
+{
+  return gs->code == GIMPLE_EH_FILTER;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_mnt>::test (gimple gs)
+{
+  return gs->code == GIMPLE_EH_MUST_NOT_THROW;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_atomic_load>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_ATOMIC_LOAD;
+}
+
+template <>
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_continue>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CONTINUE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_critical>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CRITICAL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_for>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_FOR;
+}
+
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_sections>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_SECTIONS;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_single>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_task>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TASK;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_phi>::test (gimple gs)
+{
+  return gs->code == GIMPLE_PHI;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_transaction>::test (gimple gs)
+{
+  return gs->code == GIMPLE_TRANSACTION;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_try>::test (gimple gs)
+{
+  return gs->code == GIMPLE_TRY;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_wce>::test (gimple gs)
+{
+  return gs->code == GIMPLE_WITH_CLEANUP_EXPR;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_asm>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_ASM;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_bind>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_BIND;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_call>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_CALL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_catch>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_CATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_eh_ctrl>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_eh_filter>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_EH_FILTER;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_atomic_load>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_ATOMIC_LOAD;
+}
+
+template <>
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_continue>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CONTINUE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_critical>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CRITICAL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_for>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_FOR;
+}
+
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_sections>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_SECTIONS;
+}
+
+template <>
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_task>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TASK;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_phi>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_PHI;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_transaction>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_TRANSACTION;
+}
+
 /* Offset in bytes to the location of the operand vector.
    Zero if there is no operand vector for this tuple structure.  */
 extern size_t const gimple_ops_offset_[];
@@ -1121,7 +1425,7 @@ gimple_seq_first_stmt (gimple_seq s)
 static inline gimple_seq_node
 gimple_seq_last (gimple_seq s)
 {
-  return s ? s->gsbase.prev : NULL;
+  return s ? s->prev : NULL;
 }
 
 
@@ -1140,7 +1444,7 @@ gimple_seq_last_stmt (gimple_seq s)
 static inline void
 gimple_seq_set_last (gimple_seq *ps, gimple_seq_node last)
 {
-  (*ps)->gsbase.prev = last;
+  (*ps)->prev = last;
 }
 
 
@@ -1210,7 +1514,7 @@ set_bb_seq (basic_block bb, gimple_seq seq)
 static inline enum gimple_code
 gimple_code (const_gimple g)
 {
-  return g->gsbase.code;
+  return g->code;
 }
 
 
@@ -1273,7 +1577,7 @@ gimple_has_substatements (gimple g)
 static inline basic_block
 gimple_bb (const_gimple g)
 {
-  return g->gsbase.bb;
+  return g->bb;
 }
 
 
@@ -1282,7 +1586,7 @@ gimple_bb (const_gimple g)
 static inline tree
 gimple_block (const_gimple g)
 {
-  return LOCATION_BLOCK (g->gsbase.location);
+  return LOCATION_BLOCK (g->location);
 }
 
 
@@ -1292,10 +1596,10 @@ static inline void
 gimple_set_block (gimple g, tree block)
 {
   if (block)
-    g->gsbase.location =
-	COMBINE_LOCATION_DATA (line_table, g->gsbase.location, block);
+    g->location =
+	COMBINE_LOCATION_DATA (line_table, g->location, block);
   else
-    g->gsbase.location = LOCATION_LOCUS (g->gsbase.location);
+    g->location = LOCATION_LOCUS (g->location);
 }
 
 
@@ -1304,7 +1608,7 @@ gimple_set_block (gimple g, tree block)
 static inline location_t
 gimple_location (const_gimple g)
 {
-  return g->gsbase.location;
+  return g->location;
 }
 
 /* Return pointer to location information for statement G.  */
@@ -1312,7 +1616,7 @@ gimple_location (const_gimple g)
 static inline const location_t *
 gimple_location_ptr (const_gimple g)
 {
-  return &g->gsbase.location;
+  return &g->location;
 }
 
 
@@ -1321,7 +1625,7 @@ gimple_location_ptr (const_gimple g)
 static inline void
 gimple_set_location (gimple g, location_t location)
 {
-  g->gsbase.location = location;
+  g->location = location;
 }
 
 
@@ -1366,7 +1670,7 @@ gimple_seq_singleton_p (gimple_seq seq)
 static inline bool
 gimple_no_warning_p (const_gimple stmt)
 {
-  return stmt->gsbase.no_warning;
+  return stmt->no_warning;
 }
 
 /* Set the no_warning flag of STMT to NO_WARNING.  */
@@ -1374,7 +1678,7 @@ gimple_no_warning_p (const_gimple stmt)
 static inline void
 gimple_set_no_warning (gimple stmt, bool no_warning)
 {
-  stmt->gsbase.no_warning = (unsigned) no_warning;
+  stmt->no_warning = (unsigned) no_warning;
 }
 
 /* Set the visited status on statement STMT to VISITED_P.  */
@@ -1382,7 +1686,7 @@ gimple_set_no_warning (gimple stmt, bool no_warning)
 static inline void
 gimple_set_visited (gimple stmt, bool visited_p)
 {
-  stmt->gsbase.visited = (unsigned) visited_p;
+  stmt->visited = (unsigned) visited_p;
 }
 
 
@@ -1391,7 +1695,7 @@ gimple_set_visited (gimple stmt, bool visited_p)
 static inline bool
 gimple_visited_p (gimple stmt)
 {
-  return stmt->gsbase.visited;
+  return stmt->visited;
 }
 
 
@@ -1401,9 +1705,9 @@ static inline void
 gimple_set_plf (gimple stmt, enum plf_mask plf, bool val_p)
 {
   if (val_p)
-    stmt->gsbase.plf |= (unsigned int) plf;
+    stmt->plf |= (unsigned int) plf;
   else
-    stmt->gsbase.plf &= ~((unsigned int) plf);
+    stmt->plf &= ~((unsigned int) plf);
 }
 
 
@@ -1412,7 +1716,7 @@ gimple_set_plf (gimple stmt, enum plf_mask plf, bool val_p)
 static inline unsigned int
 gimple_plf (gimple stmt, enum plf_mask plf)
 {
-  return stmt->gsbase.plf & ((unsigned int) plf);
+  return stmt->plf & ((unsigned int) plf);
 }
 
 
@@ -1421,7 +1725,7 @@ gimple_plf (gimple stmt, enum plf_mask plf)
 static inline void
 gimple_set_uid (gimple g, unsigned uid)
 {
-  g->gsbase.uid = uid;
+  g->uid = uid;
 }
 
 
@@ -1430,7 +1734,7 @@ gimple_set_uid (gimple g, unsigned uid)
 static inline unsigned
 gimple_uid (const_gimple g)
 {
-  return g->gsbase.uid;
+  return g->uid;
 }
 
 
@@ -1439,8 +1743,8 @@ gimple_uid (const_gimple g)
 static inline void
 gimple_init_singleton (gimple g)
 {
-  g->gsbase.next = NULL;
-  g->gsbase.prev = g;
+  g->next = NULL;
+  g->prev = g;
 }
 
 
@@ -1491,9 +1795,11 @@ gimple_set_use_ops (gimple g, struct use_optype_d *use)
 static inline tree
 gimple_vuse (const_gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  const gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <const gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_TREE;
-  return g->gsmembase.vuse;
+  return mem_ops_stmt->vuse;
 }
 
 /* Return the single VDEF operand of the statement G.  */
@@ -1501,9 +1807,11 @@ gimple_vuse (const_gimple g)
 static inline tree
 gimple_vdef (const_gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  const gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <const gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_TREE;
-  return g->gsmembase.vdef;
+  return mem_ops_stmt->vdef;
 }
 
 /* Return the single VUSE operand of the statement G.  */
@@ -1511,9 +1819,11 @@ gimple_vdef (const_gimple g)
 static inline tree *
 gimple_vuse_ptr (gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL;
-  return &g->gsmembase.vuse;
+  return &mem_ops_stmt->vuse;
 }
 
 /* Return the single VDEF operand of the statement G.  */
@@ -1521,9 +1831,11 @@ gimple_vuse_ptr (gimple g)
 static inline tree *
 gimple_vdef_ptr (gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL;
-  return &g->gsmembase.vdef;
+  return &mem_ops_stmt->vdef;
 }
 
 /* Set the single VUSE operand of the statement G.  */
@@ -1553,7 +1865,7 @@ gimple_set_vdef (gimple g, tree vdef)
 static inline bool
 gimple_modified_p (const_gimple g)
 {
-  return (gimple_has_ops (g)) ? (bool) g->gsbase.modified : false;
+  return (gimple_has_ops (g)) ? (bool) g->modified : false;
 }
 
 
@@ -1564,7 +1876,7 @@ static inline void
 gimple_set_modified (gimple s, bool modifiedp)
 {
   if (gimple_has_ops (s))
-    s->gsbase.modified = (unsigned) modifiedp;
+    s->modified = (unsigned) modifiedp;
 }
 
 
@@ -1579,7 +1891,7 @@ gimple_expr_code (const_gimple stmt)
 {
   enum gimple_code code = gimple_code (stmt);
   if (code == GIMPLE_ASSIGN || code == GIMPLE_COND)
-    return (enum tree_code) stmt->gsbase.subcode;
+    return (enum tree_code) stmt->subcode;
   else
     {
       gcc_gimple_checking_assert (code == GIMPLE_CALL);
@@ -1594,7 +1906,7 @@ static inline bool
 gimple_has_volatile_ops (const_gimple stmt)
 {
   if (gimple_has_mem_ops (stmt))
-    return stmt->gsbase.has_volatile_ops;
+    return stmt->has_volatile_ops;
   else
     return false;
 }
@@ -1606,7 +1918,7 @@ static inline void
 gimple_set_has_volatile_ops (gimple stmt, bool volatilep)
 {
   if (gimple_has_mem_ops (stmt))
-    stmt->gsbase.has_volatile_ops = (unsigned) volatilep;
+    stmt->has_volatile_ops = (unsigned) volatilep;
 }
 
 /* Return true if BB is in a transaction.  */
@@ -1641,7 +1953,7 @@ gimple_omp_subcode (const_gimple s)
 {
   gcc_gimple_checking_assert (gimple_code (s) >= GIMPLE_OMP_ATOMIC_LOAD
 	      && gimple_code (s) <= GIMPLE_OMP_TEAMS);
-  return s->gsbase.subcode;
+  return s->subcode;
 }
 
 /* Set the subcode for OMP statement S to SUBCODE.  */
@@ -1652,7 +1964,7 @@ gimple_omp_set_subcode (gimple s, unsigned int subcode)
   /* We only have 16 bits for the subcode.  Assert that we are not
      overflowing it.  */
   gcc_gimple_checking_assert (subcode < (1 << 16));
-  s->gsbase.subcode = subcode;
+  s->subcode = subcode;
 }
 
 /* Set the nowait flag on OMP_RETURN statement S.  */
@@ -1661,7 +1973,7 @@ static inline void
 gimple_omp_return_set_nowait (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_OMP_RETURN);
-  s->gsbase.subcode |= GF_OMP_RETURN_NOWAIT;
+  s->subcode |= GF_OMP_RETURN_NOWAIT;
 }
 
 
@@ -1681,8 +1993,9 @@ gimple_omp_return_nowait_p (const_gimple g)
 static inline void
 gimple_omp_return_set_lhs (gimple g, tree lhs)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
-  g->gimple_omp_atomic_store.val = lhs;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  omp_atomic_store_stmt->val = lhs;
 }
 
 
@@ -1691,8 +2004,9 @@ gimple_omp_return_set_lhs (gimple g, tree lhs)
 static inline tree
 gimple_omp_return_lhs (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
-  return g->gimple_omp_atomic_store.val;
+  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;
 }
 
 
@@ -1701,8 +2015,9 @@ gimple_omp_return_lhs (const_gimple g)
 static inline tree *
 gimple_omp_return_lhs_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
-  return &g->gimple_omp_atomic_store.val;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  return &omp_atomic_store_stmt->val;
 }
 
 
@@ -1723,7 +2038,7 @@ static inline void
 gimple_omp_section_set_last (gimple g)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_SECTION);
-  g->gsbase.subcode |= GF_OMP_SECTION_LAST;
+  g->subcode |= GF_OMP_SECTION_LAST;
 }
 
 
@@ -1746,9 +2061,9 @@ gimple_omp_parallel_set_combined_p (gimple g, bool combined_p)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_PARALLEL);
   if (combined_p)
-    g->gsbase.subcode |= GF_OMP_PARALLEL_COMBINED;
+    g->subcode |= GF_OMP_PARALLEL_COMBINED;
   else
-    g->gsbase.subcode &= ~GF_OMP_PARALLEL_COMBINED;
+    g->subcode &= ~GF_OMP_PARALLEL_COMBINED;
 }
 
 
@@ -1771,7 +2086,7 @@ gimple_omp_atomic_set_need_value (gimple g)
 {
   if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
     GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  g->gsbase.subcode |= GF_OMP_ATOMIC_NEED_VALUE;
+  g->subcode |= GF_OMP_ATOMIC_NEED_VALUE;
 }
 
 
@@ -1794,7 +2109,7 @@ gimple_omp_atomic_set_seq_cst (gimple g)
 {
   if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
     GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  g->gsbase.subcode |= GF_OMP_ATOMIC_SEQ_CST;
+  g->subcode |= GF_OMP_ATOMIC_SEQ_CST;
 }
 
 
@@ -1803,7 +2118,7 @@ gimple_omp_atomic_set_seq_cst (gimple g)
 static inline unsigned
 gimple_num_ops (const_gimple gs)
 {
-  return gs->gsbase.num_ops;
+  return gs->num_ops;
 }
 
 
@@ -1812,7 +2127,7 @@ gimple_num_ops (const_gimple gs)
 static inline void
 gimple_set_num_ops (gimple gs, unsigned num_ops)
 {
-  gs->gsbase.num_ops = num_ops;
+  gs->num_ops = num_ops;
 }
 
 
@@ -2055,7 +2370,7 @@ static inline bool
 gimple_assign_nontemporal_move_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gs->gsbase.nontemporal_move;
+  return gs->nontemporal_move;
 }
 
 /* Sets nontemporal move flag of GS to NONTEMPORAL.  */
@@ -2064,7 +2379,7 @@ static inline void
 gimple_assign_set_nontemporal_move (gimple gs, bool nontemporal)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  gs->gsbase.nontemporal_move = nontemporal;
+  gs->nontemporal_move = nontemporal;
 }
 
 
@@ -2078,7 +2393,7 @@ gimple_assign_rhs_code (const_gimple gs)
   enum tree_code code;
   GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
 
-  code = (enum tree_code) gs->gsbase.subcode;
+  code = (enum tree_code) gs->subcode;
   /* While we initially set subcode to the TREE_CODE of the rhs for
      GIMPLE_SINGLE_RHS assigns we do not update that subcode to stay
      in sync when we rewrite stmts into SSA form or do SSA propagations.  */
@@ -2096,7 +2411,7 @@ static inline void
 gimple_assign_set_rhs_code (gimple s, enum tree_code code)
 {
   GIMPLE_CHECK (s, GIMPLE_ASSIGN);
-  s->gsbase.subcode = code;
+  s->subcode = code;
 }
 
 
@@ -2221,7 +2536,7 @@ static inline bool
 gimple_call_internal_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
-  return (gs->gsbase.subcode & GF_CALL_INTERNAL) != 0;
+  return (gs->subcode & GF_CALL_INTERNAL) != 0;
 }
 
 
@@ -2240,10 +2555,11 @@ gimple_call_internal_fn (const_gimple gs)
 static inline tree
 gimple_call_fntype (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  const gimple_statement_call *call_stmt =
+    as_a <const gimple_statement_call> (gs);
   if (gimple_call_internal_p (gs))
     return NULL_TREE;
-  return gs->gimple_call.u.fntype;
+  return call_stmt->u.fntype;
 }
 
 /* Set the type of the function called by GS to FNTYPE.  */
@@ -2251,9 +2567,9 @@ gimple_call_fntype (const_gimple gs)
 static inline void
 gimple_call_set_fntype (gimple gs, tree fntype)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (gs);
   gcc_gimple_checking_assert (!gimple_call_internal_p (gs));
-  gs->gimple_call.u.fntype = fntype;
+  call_stmt->u.fntype = fntype;
 }
 
 
@@ -2305,9 +2621,9 @@ gimple_call_set_fndecl (gimple gs, tree decl)
 static inline void
 gimple_call_set_internal_fn (gimple gs, enum internal_fn fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (gs);
   gcc_gimple_checking_assert (gimple_call_internal_p (gs));
-  gs->gimple_call.u.internal_fn = fn;
+  call_stmt->u.internal_fn = fn;
 }
 
 
@@ -2465,9 +2781,9 @@ gimple_call_set_tail (gimple s, bool tail_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (tail_p)
-    s->gsbase.subcode |= GF_CALL_TAILCALL;
+    s->subcode |= GF_CALL_TAILCALL;
   else
-    s->gsbase.subcode &= ~GF_CALL_TAILCALL;
+    s->subcode &= ~GF_CALL_TAILCALL;
 }
 
 
@@ -2477,7 +2793,7 @@ static inline bool
 gimple_call_tail_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_TAILCALL) != 0;
+  return (s->subcode & GF_CALL_TAILCALL) != 0;
 }
 
 
@@ -2490,9 +2806,9 @@ gimple_call_set_return_slot_opt (gimple s, bool return_slot_opt_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (return_slot_opt_p)
-    s->gsbase.subcode |= GF_CALL_RETURN_SLOT_OPT;
+    s->subcode |= GF_CALL_RETURN_SLOT_OPT;
   else
-    s->gsbase.subcode &= ~GF_CALL_RETURN_SLOT_OPT;
+    s->subcode &= ~GF_CALL_RETURN_SLOT_OPT;
 }
 
 
@@ -2502,7 +2818,7 @@ static inline bool
 gimple_call_return_slot_opt_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_RETURN_SLOT_OPT) != 0;
+  return (s->subcode & GF_CALL_RETURN_SLOT_OPT) != 0;
 }
 
 
@@ -2514,9 +2830,9 @@ gimple_call_set_from_thunk (gimple s, bool from_thunk_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (from_thunk_p)
-    s->gsbase.subcode |= GF_CALL_FROM_THUNK;
+    s->subcode |= GF_CALL_FROM_THUNK;
   else
-    s->gsbase.subcode &= ~GF_CALL_FROM_THUNK;
+    s->subcode &= ~GF_CALL_FROM_THUNK;
 }
 
 
@@ -2526,7 +2842,7 @@ static inline bool
 gimple_call_from_thunk_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_FROM_THUNK) != 0;
+  return (s->subcode & GF_CALL_FROM_THUNK) != 0;
 }
 
 
@@ -2538,9 +2854,9 @@ gimple_call_set_va_arg_pack (gimple s, bool pass_arg_pack_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (pass_arg_pack_p)
-    s->gsbase.subcode |= GF_CALL_VA_ARG_PACK;
+    s->subcode |= GF_CALL_VA_ARG_PACK;
   else
-    s->gsbase.subcode &= ~GF_CALL_VA_ARG_PACK;
+    s->subcode &= ~GF_CALL_VA_ARG_PACK;
 }
 
 
@@ -2551,7 +2867,7 @@ static inline bool
 gimple_call_va_arg_pack_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_VA_ARG_PACK) != 0;
+  return (s->subcode & GF_CALL_VA_ARG_PACK) != 0;
 }
 
 
@@ -2573,9 +2889,9 @@ gimple_call_set_nothrow (gimple s, bool nothrow_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (nothrow_p)
-    s->gsbase.subcode |= GF_CALL_NOTHROW;
+    s->subcode |= GF_CALL_NOTHROW;
   else
-    s->gsbase.subcode &= ~GF_CALL_NOTHROW;
+    s->subcode &= ~GF_CALL_NOTHROW;
 }
 
 /* Return true if S is a nothrow call.  */
@@ -2597,9 +2913,9 @@ gimple_call_set_alloca_for_var (gimple s, bool for_var)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (for_var)
-    s->gsbase.subcode |= GF_CALL_ALLOCA_FOR_VAR;
+    s->subcode |= GF_CALL_ALLOCA_FOR_VAR;
   else
-    s->gsbase.subcode &= ~GF_CALL_ALLOCA_FOR_VAR;
+    s->subcode &= ~GF_CALL_ALLOCA_FOR_VAR;
 }
 
 /* Return true of S is a call to builtin_alloca emitted for VLA objects.  */
@@ -2608,7 +2924,7 @@ static inline bool
 gimple_call_alloca_for_var_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_ALLOCA_FOR_VAR) != 0;
+  return (s->subcode & GF_CALL_ALLOCA_FOR_VAR) != 0;
 }
 
 /* Copy all the GF_CALL_* flags from ORIG_CALL to DEST_CALL.  */
@@ -2618,7 +2934,7 @@ gimple_call_copy_flags (gimple dest_call, gimple orig_call)
 {
   GIMPLE_CHECK (dest_call, GIMPLE_CALL);
   GIMPLE_CHECK (orig_call, GIMPLE_CALL);
-  dest_call->gsbase.subcode = orig_call->gsbase.subcode;
+  dest_call->subcode = orig_call->subcode;
 }
 
 
@@ -2628,8 +2944,8 @@ gimple_call_copy_flags (gimple dest_call, gimple orig_call)
 static inline struct pt_solution *
 gimple_call_use_set (gimple call)
 {
-  GIMPLE_CHECK (call, GIMPLE_CALL);
-  return &call->gimple_call.call_used;
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (call);
+  return &call_stmt->call_used;
 }
 
 
@@ -2639,8 +2955,8 @@ gimple_call_use_set (gimple call)
 static inline struct pt_solution *
 gimple_call_clobber_set (gimple call)
 {
-  GIMPLE_CHECK (call, GIMPLE_CALL);
-  return &call->gimple_call.call_clobbered;
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (call);
+  return &call_stmt->call_clobbered;
 }
 
 
@@ -2662,7 +2978,7 @@ static inline enum tree_code
 gimple_cond_code (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_COND);
-  return (enum tree_code) gs->gsbase.subcode;
+  return (enum tree_code) gs->subcode;
 }
 
 
@@ -2672,7 +2988,7 @@ static inline void
 gimple_cond_set_code (gimple gs, enum tree_code code)
 {
   GIMPLE_CHECK (gs, GIMPLE_COND);
-  gs->gsbase.subcode = code;
+  gs->subcode = code;
 }
 
 
@@ -2788,7 +3104,7 @@ gimple_cond_make_false (gimple gs)
 {
   gimple_cond_set_lhs (gs, boolean_true_node);
   gimple_cond_set_rhs (gs, boolean_false_node);
-  gs->gsbase.subcode = EQ_EXPR;
+  gs->subcode = EQ_EXPR;
 }
 
 
@@ -2799,7 +3115,7 @@ gimple_cond_make_true (gimple gs)
 {
   gimple_cond_set_lhs (gs, boolean_true_node);
   gimple_cond_set_rhs (gs, boolean_true_node);
-  gs->gsbase.subcode = EQ_EXPR;
+  gs->subcode = EQ_EXPR;
 }
 
 /* Check if conditional statemente GS is of the form 'if (1 == 1)',
@@ -2908,8 +3224,9 @@ gimple_goto_set_dest (gimple gs, tree dest)
 static inline tree
 gimple_bind_vars (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  return gs->gimple_bind.vars;
+  const gimple_statement_bind *bind_stmt =
+    as_a <const gimple_statement_bind> (gs);
+  return bind_stmt->vars;
 }
 
 
@@ -2919,8 +3236,8 @@ gimple_bind_vars (const_gimple gs)
 static inline void
 gimple_bind_set_vars (gimple gs, tree vars)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gs->gimple_bind.vars = vars;
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  bind_stmt->vars = vars;
 }
 
 
@@ -2930,16 +3247,16 @@ gimple_bind_set_vars (gimple gs, tree vars)
 static inline void
 gimple_bind_append_vars (gimple gs, tree vars)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gs->gimple_bind.vars = chainon (gs->gimple_bind.vars, vars);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  bind_stmt->vars = chainon (bind_stmt->vars, vars);
 }
 
 
 static inline gimple_seq *
 gimple_bind_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  return &gs->gimple_bind.body;
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  return &bind_stmt->body;
 }
 
 /* Return the GIMPLE sequence contained in the GIMPLE_BIND statement GS.  */
@@ -2957,8 +3274,8 @@ gimple_bind_body (gimple gs)
 static inline void
 gimple_bind_set_body (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gs->gimple_bind.body = seq;
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  bind_stmt->body = seq;
 }
 
 
@@ -2967,8 +3284,8 @@ gimple_bind_set_body (gimple gs, gimple_seq seq)
 static inline void
 gimple_bind_add_stmt (gimple gs, gimple stmt)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gimple_seq_add_stmt (&gs->gimple_bind.body, stmt);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  gimple_seq_add_stmt (&bind_stmt->body, stmt);
 }
 
 
@@ -2977,8 +3294,8 @@ gimple_bind_add_stmt (gimple gs, gimple stmt)
 static inline void
 gimple_bind_add_seq (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gimple_seq_add_seq (&gs->gimple_bind.body, seq);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  gimple_seq_add_seq (&bind_stmt->body, seq);
 }
 
 
@@ -2988,8 +3305,9 @@ gimple_bind_add_seq (gimple gs, gimple_seq seq)
 static inline tree
 gimple_bind_block (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  return gs->gimple_bind.block;
+  const gimple_statement_bind *bind_stmt =
+    as_a <const gimple_statement_bind> (gs);
+  return bind_stmt->block;
 }
 
 
@@ -2999,10 +3317,10 @@ gimple_bind_block (const_gimple gs)
 static inline void
 gimple_bind_set_block (gimple gs, tree block)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
   gcc_gimple_checking_assert (block == NULL_TREE
 			      || TREE_CODE (block) == BLOCK);
-  gs->gimple_bind.block = block;
+  bind_stmt->block = block;
 }
 
 
@@ -3011,8 +3329,9 @@ gimple_bind_set_block (gimple gs, tree block)
 static inline unsigned
 gimple_asm_ninputs (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.ni;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->ni;
 }
 
 
@@ -3021,8 +3340,9 @@ gimple_asm_ninputs (const_gimple gs)
 static inline unsigned
 gimple_asm_noutputs (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.no;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->no;
 }
 
 
@@ -3031,8 +3351,9 @@ gimple_asm_noutputs (const_gimple gs)
 static inline unsigned
 gimple_asm_nclobbers (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.nc;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->nc;
 }
 
 /* Return the number of label operands for GIMPLE_ASM GS.  */
@@ -3040,8 +3361,9 @@ gimple_asm_nclobbers (const_gimple gs)
 static inline unsigned
 gimple_asm_nlabels (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.nl;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->nl;
 }
 
 /* Return input operand INDEX of GIMPLE_ASM GS.  */
@@ -3049,9 +3371,10 @@ gimple_asm_nlabels (const_gimple gs)
 static inline tree
 gimple_asm_input_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.ni);
-  return gimple_op (gs, index + gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->ni);
+  return gimple_op (gs, index + asm_stmt->no);
 }
 
 /* Return a pointer to input operand INDEX of GIMPLE_ASM GS.  */
@@ -3059,9 +3382,10 @@ gimple_asm_input_op (const_gimple gs, unsigned index)
 static inline tree *
 gimple_asm_input_op_ptr (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.ni);
-  return gimple_op_ptr (gs, index + gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->ni);
+  return gimple_op_ptr (gs, index + asm_stmt->no);
 }
 
 
@@ -3070,10 +3394,10 @@ gimple_asm_input_op_ptr (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_input_op (gimple gs, unsigned index, tree in_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.ni
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->ni
 			      && TREE_CODE (in_op) == TREE_LIST);
-  gimple_set_op (gs, index + gs->gimple_asm.no, in_op);
+  gimple_set_op (gs, index + asm_stmt->no, in_op);
 }
 
 
@@ -3082,8 +3406,9 @@ gimple_asm_set_input_op (gimple gs, unsigned index, tree in_op)
 static inline tree
 gimple_asm_output_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->no);
   return gimple_op (gs, index);
 }
 
@@ -3092,8 +3417,9 @@ gimple_asm_output_op (const_gimple gs, unsigned index)
 static inline tree *
 gimple_asm_output_op_ptr (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->no);
   return gimple_op_ptr (gs, index);
 }
 
@@ -3103,8 +3429,8 @@ gimple_asm_output_op_ptr (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_output_op (gimple gs, unsigned index, tree out_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.no
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->no
 			      && TREE_CODE (out_op) == TREE_LIST);
   gimple_set_op (gs, index, out_op);
 }
@@ -3115,9 +3441,10 @@ gimple_asm_set_output_op (gimple gs, unsigned index, tree out_op)
 static inline tree
 gimple_asm_clobber_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nc);
-  return gimple_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nc);
+  return gimple_op (gs, index + asm_stmt->ni + asm_stmt->no);
 }
 
 
@@ -3126,10 +3453,10 @@ gimple_asm_clobber_op (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_clobber_op (gimple gs, unsigned index, tree clobber_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nc
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nc
 			      && TREE_CODE (clobber_op) == TREE_LIST);
-  gimple_set_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.no, clobber_op);
+  gimple_set_op (gs, index + asm_stmt->ni + asm_stmt->no, clobber_op);
 }
 
 /* Return label operand INDEX of GIMPLE_ASM GS.  */
@@ -3137,9 +3464,10 @@ gimple_asm_set_clobber_op (gimple gs, unsigned index, tree clobber_op)
 static inline tree
 gimple_asm_label_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nl);
-  return gimple_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.nc);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nl);
+  return gimple_op (gs, index + asm_stmt->ni + asm_stmt->nc);
 }
 
 /* Set LABEL_OP to be label operand INDEX in GIMPLE_ASM GS.  */
@@ -3147,10 +3475,10 @@ gimple_asm_label_op (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_label_op (gimple gs, unsigned index, tree label_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nl
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nl
 			      && TREE_CODE (label_op) == TREE_LIST);
-  gimple_set_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.nc, label_op);
+  gimple_set_op (gs, index + asm_stmt->ni + asm_stmt->nc, label_op);
 }
 
 /* Return the string representing the assembly instruction in
@@ -3159,8 +3487,9 @@ gimple_asm_set_label_op (gimple gs, unsigned index, tree label_op)
 static inline const char *
 gimple_asm_string (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.string;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->string;
 }
 
 
@@ -3170,7 +3499,7 @@ static inline bool
 gimple_asm_volatile_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return (gs->gsbase.subcode & GF_ASM_VOLATILE) != 0;
+  return (gs->subcode & GF_ASM_VOLATILE) != 0;
 }
 
 
@@ -3181,9 +3510,9 @@ gimple_asm_set_volatile (gimple gs, bool volatile_p)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   if (volatile_p)
-    gs->gsbase.subcode |= GF_ASM_VOLATILE;
+    gs->subcode |= GF_ASM_VOLATILE;
   else
-    gs->gsbase.subcode &= ~GF_ASM_VOLATILE;
+    gs->subcode &= ~GF_ASM_VOLATILE;
 }
 
 
@@ -3194,9 +3523,9 @@ gimple_asm_set_input (gimple gs, bool input_p)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   if (input_p)
-    gs->gsbase.subcode |= GF_ASM_INPUT;
+    gs->subcode |= GF_ASM_INPUT;
   else
-    gs->gsbase.subcode &= ~GF_ASM_INPUT;
+    gs->subcode &= ~GF_ASM_INPUT;
 }
 
 
@@ -3206,7 +3535,7 @@ static inline bool
 gimple_asm_input_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return (gs->gsbase.subcode & GF_ASM_INPUT) != 0;
+  return (gs->subcode & GF_ASM_INPUT) != 0;
 }
 
 
@@ -3215,8 +3544,9 @@ gimple_asm_input_p (const_gimple gs)
 static inline tree
 gimple_catch_types (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  return gs->gimple_catch.types;
+  const gimple_statement_catch *catch_stmt =
+    as_a <const gimple_statement_catch> (gs);
+  return catch_stmt->types;
 }
 
 
@@ -3225,8 +3555,8 @@ gimple_catch_types (const_gimple gs)
 static inline tree *
 gimple_catch_types_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  return &gs->gimple_catch.types;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  return &catch_stmt->types;
 }
 
 
@@ -3236,8 +3566,8 @@ gimple_catch_types_ptr (gimple gs)
 static inline gimple_seq *
 gimple_catch_handler_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  return &gs->gimple_catch.handler;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  return &catch_stmt->handler;
 }
 
 
@@ -3256,8 +3586,8 @@ gimple_catch_handler (gimple gs)
 static inline void
 gimple_catch_set_types (gimple gs, tree t)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  gs->gimple_catch.types = t;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  catch_stmt->types = t;
 }
 
 
@@ -3266,8 +3596,8 @@ gimple_catch_set_types (gimple gs, tree t)
 static inline void
 gimple_catch_set_handler (gimple gs, gimple_seq handler)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  gs->gimple_catch.handler = handler;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  catch_stmt->handler = handler;
 }
 
 
@@ -3276,8 +3606,9 @@ gimple_catch_set_handler (gimple gs, gimple_seq handler)
 static inline tree
 gimple_eh_filter_types (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  return gs->gimple_eh_filter.types;
+  const gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <const gimple_statement_eh_filter> (gs);
+  return eh_filter_stmt->types;
 }
 
 
@@ -3287,8 +3618,9 @@ gimple_eh_filter_types (const_gimple gs)
 static inline tree *
 gimple_eh_filter_types_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  return &gs->gimple_eh_filter.types;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  return &eh_filter_stmt->types;
 }
 
 
@@ -3298,8 +3630,9 @@ gimple_eh_filter_types_ptr (gimple gs)
 static inline gimple_seq *
 gimple_eh_filter_failure_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  return &gs->gimple_eh_filter.failure;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  return &eh_filter_stmt->failure;
 }
 
 
@@ -3318,8 +3651,9 @@ gimple_eh_filter_failure (gimple gs)
 static inline void
 gimple_eh_filter_set_types (gimple gs, tree types)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  gs->gimple_eh_filter.types = types;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  eh_filter_stmt->types = types;
 }
 
 
@@ -3329,8 +3663,9 @@ gimple_eh_filter_set_types (gimple gs, tree types)
 static inline void
 gimple_eh_filter_set_failure (gimple gs, gimple_seq failure)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  gs->gimple_eh_filter.failure = failure;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  eh_filter_stmt->failure = failure;
 }
 
 /* Get the function decl to be called by the MUST_NOT_THROW region.  */
@@ -3338,8 +3673,8 @@ gimple_eh_filter_set_failure (gimple gs, gimple_seq failure)
 static inline tree
 gimple_eh_must_not_throw_fndecl (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_MUST_NOT_THROW);
-  return gs->gimple_eh_mnt.fndecl;
+  gimple_statement_eh_mnt *eh_mnt_stmt = as_a <gimple_statement_eh_mnt> (gs);
+  return eh_mnt_stmt->fndecl;
 }
 
 /* Set the function decl to be called by GS to DECL.  */
@@ -3347,8 +3682,8 @@ gimple_eh_must_not_throw_fndecl (gimple gs)
 static inline void
 gimple_eh_must_not_throw_set_fndecl (gimple gs, tree decl)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_MUST_NOT_THROW);
-  gs->gimple_eh_mnt.fndecl = decl;
+  gimple_statement_eh_mnt *eh_mnt_stmt = as_a <gimple_statement_eh_mnt> (gs);
+  eh_mnt_stmt->fndecl = decl;
 }
 
 /* GIMPLE_EH_ELSE accessors.  */
@@ -3356,8 +3691,9 @@ gimple_eh_must_not_throw_set_fndecl (gimple gs, tree decl)
 static inline gimple_seq *
 gimple_eh_else_n_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  return &gs->gimple_eh_else.n_body;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  return &eh_else_stmt->n_body;
 }
 
 static inline gimple_seq
@@ -3369,8 +3705,9 @@ gimple_eh_else_n_body (gimple gs)
 static inline gimple_seq *
 gimple_eh_else_e_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  return &gs->gimple_eh_else.e_body;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  return &eh_else_stmt->e_body;
 }
 
 static inline gimple_seq
@@ -3382,15 +3719,17 @@ gimple_eh_else_e_body (gimple gs)
 static inline void
 gimple_eh_else_set_n_body (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  gs->gimple_eh_else.n_body = seq;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  eh_else_stmt->n_body = seq;
 }
 
 static inline void
 gimple_eh_else_set_e_body (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  gs->gimple_eh_else.e_body = seq;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  eh_else_stmt->e_body = seq;
 }
 
 /* GIMPLE_TRY accessors. */
@@ -3402,7 +3741,7 @@ static inline enum gimple_try_flags
 gimple_try_kind (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return (enum gimple_try_flags) (gs->gsbase.subcode & GIMPLE_TRY_KIND);
+  return (enum gimple_try_flags) (gs->subcode & GIMPLE_TRY_KIND);
 }
 
 
@@ -3415,7 +3754,7 @@ gimple_try_set_kind (gimple gs, enum gimple_try_flags kind)
   gcc_gimple_checking_assert (kind == GIMPLE_TRY_CATCH
 			      || kind == GIMPLE_TRY_FINALLY);
   if (gimple_try_kind (gs) != kind)
-    gs->gsbase.subcode = (unsigned int) kind;
+    gs->subcode = (unsigned int) kind;
 }
 
 
@@ -3425,7 +3764,7 @@ static inline bool
 gimple_try_catch_is_cleanup (const_gimple gs)
 {
   gcc_gimple_checking_assert (gimple_try_kind (gs) == GIMPLE_TRY_CATCH);
-  return (gs->gsbase.subcode & GIMPLE_TRY_CATCH_IS_CLEANUP) != 0;
+  return (gs->subcode & GIMPLE_TRY_CATCH_IS_CLEANUP) != 0;
 }
 
 
@@ -3435,8 +3774,8 @@ gimple_try_catch_is_cleanup (const_gimple gs)
 static inline gimple_seq *
 gimple_try_eval_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return &gs->gimple_try.eval;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  return &try_stmt->eval;
 }
 
 
@@ -3455,8 +3794,8 @@ gimple_try_eval (gimple gs)
 static inline gimple_seq *
 gimple_try_cleanup_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return &gs->gimple_try.cleanup;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  return &try_stmt->cleanup;
 }
 
 
@@ -3477,9 +3816,9 @@ gimple_try_set_catch_is_cleanup (gimple g, bool catch_is_cleanup)
 {
   gcc_gimple_checking_assert (gimple_try_kind (g) == GIMPLE_TRY_CATCH);
   if (catch_is_cleanup)
-    g->gsbase.subcode |= GIMPLE_TRY_CATCH_IS_CLEANUP;
+    g->subcode |= GIMPLE_TRY_CATCH_IS_CLEANUP;
   else
-    g->gsbase.subcode &= ~GIMPLE_TRY_CATCH_IS_CLEANUP;
+    g->subcode &= ~GIMPLE_TRY_CATCH_IS_CLEANUP;
 }
 
 
@@ -3489,8 +3828,8 @@ gimple_try_set_catch_is_cleanup (gimple g, bool catch_is_cleanup)
 static inline void
 gimple_try_set_eval (gimple gs, gimple_seq eval)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  gs->gimple_try.eval = eval;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  try_stmt->eval = eval;
 }
 
 
@@ -3500,8 +3839,8 @@ gimple_try_set_eval (gimple gs, gimple_seq eval)
 static inline void
 gimple_try_set_cleanup (gimple gs, gimple_seq cleanup)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  gs->gimple_try.cleanup = cleanup;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  try_stmt->cleanup = cleanup;
 }
 
 
@@ -3510,8 +3849,8 @@ gimple_try_set_cleanup (gimple gs, gimple_seq cleanup)
 static inline gimple_seq *
 gimple_wce_cleanup_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  return &gs->gimple_wce.cleanup;
+  gimple_statement_wce *wce_stmt = as_a <gimple_statement_wce> (gs);
+  return &wce_stmt->cleanup;
 }
 
 
@@ -3529,8 +3868,8 @@ gimple_wce_cleanup (gimple gs)
 static inline void
 gimple_wce_set_cleanup (gimple gs, gimple_seq cleanup)
 {
-  GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  gs->gimple_wce.cleanup = cleanup;
+  gimple_statement_wce *wce_stmt = as_a <gimple_statement_wce> (gs);
+  wce_stmt->cleanup = cleanup;
 }
 
 
@@ -3540,7 +3879,7 @@ static inline bool
 gimple_wce_cleanup_eh_only (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  return gs->gsbase.subcode != 0;
+  return gs->subcode != 0;
 }
 
 
@@ -3550,7 +3889,7 @@ static inline void
 gimple_wce_set_cleanup_eh_only (gimple gs, bool eh_only_p)
 {
   GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  gs->gsbase.subcode = (unsigned int) eh_only_p;
+  gs->subcode = (unsigned int) eh_only_p;
 }
 
 
@@ -3559,8 +3898,9 @@ gimple_wce_set_cleanup_eh_only (gimple gs, bool eh_only_p)
 static inline unsigned
 gimple_phi_capacity (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return gs->gimple_phi.capacity;
+  const gimple_statement_phi *phi_stmt =
+    as_a <const gimple_statement_phi> (gs);
+  return phi_stmt->capacity;
 }
 
 
@@ -3571,8 +3911,9 @@ gimple_phi_capacity (const_gimple gs)
 static inline unsigned
 gimple_phi_num_args (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return gs->gimple_phi.nargs;
+  const gimple_statement_phi *phi_stmt =
+    as_a <const gimple_statement_phi> (gs);
+  return phi_stmt->nargs;
 }
 
 
@@ -3581,8 +3922,9 @@ gimple_phi_num_args (const_gimple gs)
 static inline tree
 gimple_phi_result (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return gs->gimple_phi.result;
+  const gimple_statement_phi *phi_stmt =
+    as_a <const gimple_statement_phi> (gs);
+  return phi_stmt->result;
 }
 
 /* Return a pointer to the SSA name created by GIMPLE_PHI GS.  */
@@ -3590,8 +3932,8 @@ gimple_phi_result (const_gimple gs)
 static inline tree *
 gimple_phi_result_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return &gs->gimple_phi.result;
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  return &phi_stmt->result;
 }
 
 /* Set RESULT to be the SSA name created by GIMPLE_PHI GS.  */
@@ -3599,8 +3941,8 @@ gimple_phi_result_ptr (gimple gs)
 static inline void
 gimple_phi_set_result (gimple gs, tree result)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  gs->gimple_phi.result = result;
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  phi_stmt->result = result;
   if (result && TREE_CODE (result) == SSA_NAME)
     SSA_NAME_DEF_STMT (result) = gs;
 }
@@ -3612,9 +3954,9 @@ gimple_phi_set_result (gimple gs, tree result)
 static inline struct phi_arg_d *
 gimple_phi_arg (gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  gcc_gimple_checking_assert (index <= gs->gimple_phi.capacity);
-  return &(gs->gimple_phi.args[index]);
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  gcc_gimple_checking_assert (index <= phi_stmt->capacity);
+  return &(phi_stmt->args[index]);
 }
 
 /* Set PHIARG to be the argument corresponding to incoming edge INDEX
@@ -3623,9 +3965,9 @@ gimple_phi_arg (gimple gs, unsigned index)
 static inline void
 gimple_phi_set_arg (gimple gs, unsigned index, struct phi_arg_d * phiarg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  gcc_gimple_checking_assert (index <= gs->gimple_phi.nargs);
-  gs->gimple_phi.args[index] = *phiarg;
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  gcc_gimple_checking_assert (index <= phi_stmt->nargs);
+  phi_stmt->args[index] = *phiarg;
 }
 
 /* PHI nodes should contain only ssa_names and invariants.  A test
@@ -3723,8 +4065,9 @@ gimple_phi_arg_has_location (gimple gs, size_t i)
 static inline int
 gimple_resx_region (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_RESX);
-  return gs->gimple_eh_ctrl.region;
+  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <const gimple_statement_eh_ctrl> (gs);
+  return eh_ctrl_stmt->region;
 }
 
 /* Set REGION to be the region number for GIMPLE_RESX GS.  */
@@ -3732,8 +4075,9 @@ gimple_resx_region (const_gimple gs)
 static inline void
 gimple_resx_set_region (gimple gs, int region)
 {
-  GIMPLE_CHECK (gs, GIMPLE_RESX);
-  gs->gimple_eh_ctrl.region = region;
+  gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <gimple_statement_eh_ctrl> (gs);
+  eh_ctrl_stmt->region = region;
 }
 
 /* Return the region number for GIMPLE_EH_DISPATCH GS.  */
@@ -3741,8 +4085,9 @@ gimple_resx_set_region (gimple gs, int region)
 static inline int
 gimple_eh_dispatch_region (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_DISPATCH);
-  return gs->gimple_eh_ctrl.region;
+  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <const gimple_statement_eh_ctrl> (gs);
+  return eh_ctrl_stmt->region;
 }
 
 /* Set REGION to be the region number for GIMPLE_EH_DISPATCH GS.  */
@@ -3750,8 +4095,9 @@ gimple_eh_dispatch_region (const_gimple gs)
 static inline void
 gimple_eh_dispatch_set_region (gimple gs, int region)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_DISPATCH);
-  gs->gimple_eh_ctrl.region = region;
+  gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <gimple_statement_eh_ctrl> (gs);
+  eh_ctrl_stmt->region = region;
 }
 
 /* Return the number of labels associated with the switch statement GS.  */
@@ -3864,7 +4210,7 @@ static inline bool
 gimple_debug_bind_p (const_gimple s)
 {
   if (is_gimple_debug (s))
-    return s->gsbase.subcode == GIMPLE_DEBUG_BIND;
+    return s->subcode == GIMPLE_DEBUG_BIND;
 
   return false;
 }
@@ -3956,7 +4302,7 @@ static inline bool
 gimple_debug_source_bind_p (const_gimple s)
 {
   if (is_gimple_debug (s))
-    return s->gsbase.subcode == GIMPLE_DEBUG_SOURCE_BIND;
+    return s->subcode == GIMPLE_DEBUG_SOURCE_BIND;
 
   return false;
 }
@@ -4061,8 +4407,9 @@ gimple_omp_set_body (gimple gs, gimple_seq body)
 static inline tree
 gimple_omp_critical_name (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_CRITICAL);
-  return gs->gimple_omp_critical.name;
+  const gimple_statement_omp_critical *omp_critical_stmt =
+    as_a <const gimple_statement_omp_critical> (gs);
+  return omp_critical_stmt->name;
 }
 
 
@@ -4071,8 +4418,9 @@ gimple_omp_critical_name (const_gimple gs)
 static inline tree *
 gimple_omp_critical_name_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_CRITICAL);
-  return &gs->gimple_omp_critical.name;
+  gimple_statement_omp_critical *omp_critical_stmt =
+    as_a <gimple_statement_omp_critical> (gs);
+  return &omp_critical_stmt->name;
 }
 
 
@@ -4081,8 +4429,9 @@ gimple_omp_critical_name_ptr (gimple gs)
 static inline void
 gimple_omp_critical_set_name (gimple gs, tree name)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_CRITICAL);
-  gs->gimple_omp_critical.name = name;
+  gimple_statement_omp_critical *omp_critical_stmt =
+    as_a <gimple_statement_omp_critical> (gs);
+  omp_critical_stmt->name = name;
 }
 
 
@@ -4102,7 +4451,7 @@ static inline void
 gimple_omp_for_set_kind (gimple g, int kind)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
-  g->gsbase.subcode = (g->gsbase.subcode & ~GF_OMP_FOR_KIND_MASK)
+  g->subcode = (g->subcode & ~GF_OMP_FOR_KIND_MASK)
 		      | (kind & GF_OMP_FOR_KIND_MASK);
 }
 
@@ -4126,9 +4475,9 @@ gimple_omp_for_set_combined_p (gimple g, bool combined_p)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
   if (combined_p)
-    g->gsbase.subcode |= GF_OMP_FOR_COMBINED;
+    g->subcode |= GF_OMP_FOR_COMBINED;
   else
-    g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED;
+    g->subcode &= ~GF_OMP_FOR_COMBINED;
 }
 
 
@@ -4151,9 +4500,9 @@ gimple_omp_for_set_combined_into_p (gimple g, bool combined_p)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
   if (combined_p)
-    g->gsbase.subcode |= GF_OMP_FOR_COMBINED_INTO;
+    g->subcode |= GF_OMP_FOR_COMBINED_INTO;
   else
-    g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED_INTO;
+    g->subcode &= ~GF_OMP_FOR_COMBINED_INTO;
 }
 
 
@@ -4162,8 +4511,9 @@ gimple_omp_for_set_combined_into_p (gimple g, bool combined_p)
 static inline tree
 gimple_omp_for_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return gs->gimple_omp_for.clauses;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  return omp_for_stmt->clauses;
 }
 
 
@@ -4172,8 +4522,9 @@ gimple_omp_for_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_for_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return &gs->gimple_omp_for.clauses;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  return &omp_for_stmt->clauses;
 }
 
 
@@ -4182,8 +4533,9 @@ gimple_omp_for_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_for_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gs->gimple_omp_for.clauses = clauses;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  omp_for_stmt->clauses = clauses;
 }
 
 
@@ -4192,8 +4544,9 @@ gimple_omp_for_set_clauses (gimple gs, tree clauses)
 static inline size_t
 gimple_omp_for_collapse (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return gs->gimple_omp_for.collapse;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  return omp_for_stmt->collapse;
 }
 
 
@@ -4202,9 +4555,10 @@ gimple_omp_for_collapse (gimple gs)
 static inline tree
 gimple_omp_for_index (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].index;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].index;
 }
 
 
@@ -4213,9 +4567,10 @@ gimple_omp_for_index (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_index_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].index;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].index;
 }
 
 
@@ -4224,9 +4579,10 @@ gimple_omp_for_index_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_index (gimple gs, size_t i, tree index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].index = index;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].index = index;
 }
 
 
@@ -4235,9 +4591,10 @@ gimple_omp_for_set_index (gimple gs, size_t i, tree index)
 static inline tree
 gimple_omp_for_initial (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].initial;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].initial;
 }
 
 
@@ -4246,9 +4603,10 @@ gimple_omp_for_initial (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_initial_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].initial;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].initial;
 }
 
 
@@ -4257,9 +4615,10 @@ gimple_omp_for_initial_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_initial (gimple gs, size_t i, tree initial)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].initial = initial;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].initial = initial;
 }
 
 
@@ -4268,9 +4627,10 @@ gimple_omp_for_set_initial (gimple gs, size_t i, tree initial)
 static inline tree
 gimple_omp_for_final (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].final;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].final;
 }
 
 
@@ -4279,9 +4639,10 @@ gimple_omp_for_final (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_final_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].final;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].final;
 }
 
 
@@ -4290,9 +4651,10 @@ gimple_omp_for_final_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_final (gimple gs, size_t i, tree final)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].final = final;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].final = final;
 }
 
 
@@ -4301,9 +4663,10 @@ gimple_omp_for_set_final (gimple gs, size_t i, tree final)
 static inline tree
 gimple_omp_for_incr (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].incr;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].incr;
 }
 
 
@@ -4312,9 +4675,10 @@ gimple_omp_for_incr (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_incr_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].incr;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].incr;
 }
 
 
@@ -4323,9 +4687,10 @@ gimple_omp_for_incr_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_incr (gimple gs, size_t i, tree incr)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].incr = incr;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].incr = incr;
 }
 
 
@@ -4335,8 +4700,9 @@ gimple_omp_for_set_incr (gimple gs, size_t i, tree incr)
 static inline gimple_seq *
 gimple_omp_for_pre_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return &gs->gimple_omp_for.pre_body;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  return &omp_for_stmt->pre_body;
 }
 
 
@@ -4356,8 +4722,9 @@ gimple_omp_for_pre_body (gimple gs)
 static inline void
 gimple_omp_for_set_pre_body (gimple gs, gimple_seq pre_body)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gs->gimple_omp_for.pre_body = pre_body;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  omp_for_stmt->pre_body = pre_body;
 }
 
 
@@ -4366,8 +4733,9 @@ gimple_omp_for_set_pre_body (gimple gs, gimple_seq pre_body)
 static inline tree
 gimple_omp_parallel_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->clauses;
 }
 
 
@@ -4376,8 +4744,9 @@ gimple_omp_parallel_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_parallel_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->clauses;
 }
 
 
@@ -4387,8 +4756,9 @@ gimple_omp_parallel_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_parallel_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->clauses = clauses;
 }
 
 
@@ -4397,8 +4767,9 @@ gimple_omp_parallel_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_parallel_child_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4407,8 +4778,9 @@ gimple_omp_parallel_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_parallel_child_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->child_fn;
 }
 
 
@@ -4417,8 +4789,9 @@ gimple_omp_parallel_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_parallel_set_child_fn (gimple gs, tree child_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->child_fn = child_fn;
 }
 
 
@@ -4428,8 +4801,9 @@ gimple_omp_parallel_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_parallel_data_arg (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->data_arg;
 }
 
 
@@ -4438,8 +4812,9 @@ gimple_omp_parallel_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_parallel_data_arg_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->data_arg;
 }
 
 
@@ -4448,8 +4823,9 @@ gimple_omp_parallel_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_parallel_set_data_arg (gimple gs, tree data_arg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->data_arg = data_arg;
 }
 
 
@@ -4458,8 +4834,9 @@ gimple_omp_parallel_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_task_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->clauses;
 }
 
 
@@ -4468,8 +4845,9 @@ gimple_omp_task_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_task_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->clauses;
 }
 
 
@@ -4479,8 +4857,9 @@ gimple_omp_task_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->clauses = clauses;
 }
 
 
@@ -4489,8 +4868,9 @@ gimple_omp_task_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_task_child_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4499,8 +4879,9 @@ gimple_omp_task_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_task_child_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->child_fn;
 }
 
 
@@ -4509,8 +4890,9 @@ gimple_omp_task_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_child_fn (gimple gs, tree child_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->child_fn = child_fn;
 }
 
 
@@ -4520,8 +4902,9 @@ gimple_omp_task_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_task_data_arg (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->data_arg;
 }
 
 
@@ -4530,8 +4913,9 @@ gimple_omp_task_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_task_data_arg_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->data_arg;
 }
 
 
@@ -4540,8 +4924,9 @@ gimple_omp_task_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->data_arg = data_arg;
 }
 
 
@@ -4550,9 +4935,9 @@ gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_taskreg_clauses (const_gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->clauses;
 }
 
 
@@ -4561,9 +4946,9 @@ gimple_omp_taskreg_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_clauses_ptr (gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->clauses;
 }
 
 
@@ -4573,9 +4958,9 @@ gimple_omp_taskreg_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->clauses = clauses;
 }
 
 
@@ -4584,9 +4969,9 @@ gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_taskreg_child_fn (const_gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4595,9 +4980,9 @@ gimple_omp_taskreg_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_child_fn_ptr (gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->child_fn;
 }
 
 
@@ -4606,9 +4991,9 @@ gimple_omp_taskreg_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->child_fn = child_fn;
 }
 
 
@@ -4618,9 +5003,9 @@ gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_taskreg_data_arg (const_gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->data_arg;
 }
 
 
@@ -4629,9 +5014,9 @@ gimple_omp_taskreg_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_data_arg_ptr (gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->data_arg;
 }
 
 
@@ -4640,9 +5025,9 @@ gimple_omp_taskreg_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->data_arg = data_arg;
 }
 
 
@@ -4651,8 +5036,9 @@ gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_task_copy_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_task.copy_fn;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->copy_fn;
 }
 
 /* Return a pointer to the copy function used to hold the body of
@@ -4661,8 +5047,9 @@ gimple_omp_task_copy_fn (const_gimple gs)
 static inline tree *
 gimple_omp_task_copy_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_task.copy_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->copy_fn;
 }
 
 
@@ -4671,8 +5058,9 @@ gimple_omp_task_copy_fn_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_copy_fn (gimple gs, tree copy_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_task.copy_fn = copy_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->copy_fn = copy_fn;
 }
 
 
@@ -4681,8 +5069,9 @@ gimple_omp_task_set_copy_fn (gimple gs, tree copy_fn)
 static inline tree
 gimple_omp_task_arg_size (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_task.arg_size;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->arg_size;
 }
 
 
@@ -4691,8 +5080,9 @@ gimple_omp_task_arg_size (const_gimple gs)
 static inline tree *
 gimple_omp_task_arg_size_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_task.arg_size;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->arg_size;
 }
 
 
@@ -4701,8 +5091,9 @@ gimple_omp_task_arg_size_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_arg_size (gimple gs, tree arg_size)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_task.arg_size = arg_size;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->arg_size = arg_size;
 }
 
 
@@ -4711,8 +5102,9 @@ gimple_omp_task_set_arg_size (gimple gs, tree arg_size)
 static inline tree
 gimple_omp_task_arg_align (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_task.arg_align;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->arg_align;
 }
 
 
@@ -4721,8 +5113,9 @@ gimple_omp_task_arg_align (const_gimple gs)
 static inline tree *
 gimple_omp_task_arg_align_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_task.arg_align;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->arg_align;
 }
 
 
@@ -4731,8 +5124,9 @@ gimple_omp_task_arg_align_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_arg_align (gimple gs, tree arg_align)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_task.arg_align = arg_align;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->arg_align = arg_align;
 }
 
 
@@ -4741,8 +5135,9 @@ gimple_omp_task_set_arg_align (gimple gs, tree arg_align)
 static inline tree
 gimple_omp_single_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SINGLE);
-  return gs->gimple_omp_single.clauses;
+  const gimple_statement_omp_single *omp_single_stmt =
+    as_a <const gimple_statement_omp_single> (gs);
+  return omp_single_stmt->clauses;
 }
 
 
@@ -4751,8 +5146,9 @@ gimple_omp_single_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_single_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SINGLE);
-  return &gs->gimple_omp_single.clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  return &omp_single_stmt->clauses;
 }
 
 
@@ -4761,8 +5157,9 @@ gimple_omp_single_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_single_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SINGLE);
-  gs->gimple_omp_single.clauses = clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  omp_single_stmt->clauses = clauses;
 }
 
 
@@ -4771,8 +5168,9 @@ gimple_omp_single_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_target_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->clauses;
 }
 
 
@@ -4781,8 +5179,9 @@ gimple_omp_target_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_target_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->clauses;
 }
 
 
@@ -4791,8 +5190,9 @@ gimple_omp_target_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->clauses = clauses;
 }
 
 
@@ -4812,7 +5212,7 @@ static inline void
 gimple_omp_target_set_kind (gimple g, int kind)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_TARGET);
-  g->gsbase.subcode = (g->gsbase.subcode & ~GF_OMP_TARGET_KIND_MASK)
+  g->subcode = (g->subcode & ~GF_OMP_TARGET_KIND_MASK)
 		      | (kind & GF_OMP_TARGET_KIND_MASK);
 }
 
@@ -4822,8 +5222,9 @@ gimple_omp_target_set_kind (gimple g, int kind)
 static inline tree
 gimple_omp_target_child_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4832,8 +5233,9 @@ gimple_omp_target_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_target_child_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->child_fn;
 }
 
 
@@ -4842,8 +5244,9 @@ gimple_omp_target_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->child_fn = child_fn;
 }
 
 
@@ -4853,8 +5256,9 @@ gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_target_data_arg (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->data_arg;
 }
 
 
@@ -4863,8 +5267,9 @@ gimple_omp_target_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_target_data_arg_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->data_arg;
 }
 
 
@@ -4873,8 +5278,9 @@ gimple_omp_target_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->data_arg = data_arg;
 }
 
 
@@ -4883,8 +5289,9 @@ gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_teams_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
-  return gs->gimple_omp_single.clauses;
+  const gimple_statement_omp_single *omp_single_stmt =
+    as_a <const gimple_statement_omp_single> (gs);
+  return omp_single_stmt->clauses;
 }
 
 
@@ -4893,8 +5300,9 @@ gimple_omp_teams_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_teams_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
-  return &gs->gimple_omp_single.clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  return &omp_single_stmt->clauses;
 }
 
 
@@ -4903,8 +5311,9 @@ gimple_omp_teams_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_teams_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
-  gs->gimple_omp_single.clauses = clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  omp_single_stmt->clauses = clauses;
 }
 
 
@@ -4913,8 +5322,9 @@ gimple_omp_teams_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_sections_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return gs->gimple_omp_sections.clauses;
+  const gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <const gimple_statement_omp_sections> (gs);
+  return omp_sections_stmt->clauses;
 }
 
 
@@ -4923,8 +5333,9 @@ gimple_omp_sections_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_sections_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return &gs->gimple_omp_sections.clauses;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  return &omp_sections_stmt->clauses;
 }
 
 
@@ -4934,8 +5345,9 @@ gimple_omp_sections_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_sections_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  gs->gimple_omp_sections.clauses = clauses;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  omp_sections_stmt->clauses = clauses;
 }
 
 
@@ -4945,8 +5357,9 @@ gimple_omp_sections_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_sections_control (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return gs->gimple_omp_sections.control;
+  const gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <const gimple_statement_omp_sections> (gs);
+  return omp_sections_stmt->control;
 }
 
 
@@ -4956,8 +5369,9 @@ gimple_omp_sections_control (const_gimple gs)
 static inline tree *
 gimple_omp_sections_control_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return &gs->gimple_omp_sections.control;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  return &omp_sections_stmt->control;
 }
 
 
@@ -4967,8 +5381,9 @@ gimple_omp_sections_control_ptr (gimple gs)
 static inline void
 gimple_omp_sections_set_control (gimple gs, tree control)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  gs->gimple_omp_sections.control = control;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  omp_sections_stmt->control = control;
 }
 
 
@@ -4977,10 +5392,11 @@ gimple_omp_sections_set_control (gimple gs, tree control)
 static inline void
 gimple_omp_for_set_cond (gimple gs, size_t i, enum tree_code cond)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
   gcc_gimple_checking_assert (TREE_CODE_CLASS (cond) == tcc_comparison
-			      && i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].cond = cond;
+			      && i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].cond = cond;
 }
 
 
@@ -4989,9 +5405,10 @@ gimple_omp_for_set_cond (gimple gs, size_t i, enum tree_code cond)
 static inline enum tree_code
 gimple_omp_for_cond (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].cond;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].cond;
 }
 
 
@@ -5000,8 +5417,9 @@ gimple_omp_for_cond (const_gimple gs, size_t i)
 static inline void
 gimple_omp_atomic_store_set_val (gimple g, tree val)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  g->gimple_omp_atomic_store.val = val;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  omp_atomic_store_stmt->val = val;
 }
 
 
@@ -5010,8 +5428,9 @@ gimple_omp_atomic_store_set_val (gimple g, tree val)
 static inline tree
 gimple_omp_atomic_store_val (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  return g->gimple_omp_atomic_store.val;
+  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;
 }
 
 
@@ -5020,8 +5439,9 @@ gimple_omp_atomic_store_val (const_gimple g)
 static inline tree *
 gimple_omp_atomic_store_val_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  return &g->gimple_omp_atomic_store.val;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  return &omp_atomic_store_stmt->val;
 }
 
 
@@ -5030,8 +5450,9 @@ gimple_omp_atomic_store_val_ptr (gimple g)
 static inline void
 gimple_omp_atomic_load_set_lhs (gimple g, tree lhs)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  g->gimple_omp_atomic_load.lhs = lhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  omp_atomic_load_stmt->lhs = lhs;
 }
 
 
@@ -5040,8 +5461,9 @@ gimple_omp_atomic_load_set_lhs (gimple g, tree lhs)
 static inline tree
 gimple_omp_atomic_load_lhs (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return g->gimple_omp_atomic_load.lhs;
+  const gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <const gimple_statement_omp_atomic_load> (g);
+  return omp_atomic_load_stmt->lhs;
 }
 
 
@@ -5050,8 +5472,9 @@ gimple_omp_atomic_load_lhs (const_gimple g)
 static inline tree *
 gimple_omp_atomic_load_lhs_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return &g->gimple_omp_atomic_load.lhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  return &omp_atomic_load_stmt->lhs;
 }
 
 
@@ -5060,8 +5483,9 @@ gimple_omp_atomic_load_lhs_ptr (gimple g)
 static inline void
 gimple_omp_atomic_load_set_rhs (gimple g, tree rhs)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  g->gimple_omp_atomic_load.rhs = rhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  omp_atomic_load_stmt->rhs = rhs;
 }
 
 
@@ -5070,8 +5494,9 @@ gimple_omp_atomic_load_set_rhs (gimple g, tree rhs)
 static inline tree
 gimple_omp_atomic_load_rhs (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return g->gimple_omp_atomic_load.rhs;
+  const gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <const gimple_statement_omp_atomic_load> (g);
+  return omp_atomic_load_stmt->rhs;
 }
 
 
@@ -5080,8 +5505,9 @@ gimple_omp_atomic_load_rhs (const_gimple g)
 static inline tree *
 gimple_omp_atomic_load_rhs_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return &g->gimple_omp_atomic_load.rhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  return &omp_atomic_load_stmt->rhs;
 }
 
 
@@ -5090,8 +5516,9 @@ gimple_omp_atomic_load_rhs_ptr (gimple g)
 static inline tree
 gimple_omp_continue_control_def (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return g->gimple_omp_continue.control_def;
+  const gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <const gimple_statement_omp_continue> (g);
+  return omp_continue_stmt->control_def;
 }
 
 /* The same as above, but return the address.  */
@@ -5099,8 +5526,9 @@ gimple_omp_continue_control_def (const_gimple g)
 static inline tree *
 gimple_omp_continue_control_def_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return &g->gimple_omp_continue.control_def;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  return &omp_continue_stmt->control_def;
 }
 
 /* Set the definition of the control variable in a GIMPLE_OMP_CONTINUE.  */
@@ -5108,8 +5536,9 @@ gimple_omp_continue_control_def_ptr (gimple g)
 static inline void
 gimple_omp_continue_set_control_def (gimple g, tree def)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  g->gimple_omp_continue.control_def = def;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  omp_continue_stmt->control_def = def;
 }
 
 
@@ -5118,8 +5547,9 @@ gimple_omp_continue_set_control_def (gimple g, tree def)
 static inline tree
 gimple_omp_continue_control_use (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return g->gimple_omp_continue.control_use;
+  const gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <const gimple_statement_omp_continue> (g);
+  return omp_continue_stmt->control_use;
 }
 
 
@@ -5128,8 +5558,9 @@ gimple_omp_continue_control_use (const_gimple g)
 static inline tree *
 gimple_omp_continue_control_use_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return &g->gimple_omp_continue.control_use;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  return &omp_continue_stmt->control_use;
 }
 
 
@@ -5138,8 +5569,9 @@ gimple_omp_continue_control_use_ptr (gimple g)
 static inline void
 gimple_omp_continue_set_control_use (gimple g, tree use)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  g->gimple_omp_continue.control_use = use;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  omp_continue_stmt->control_use = use;
 }
 
 /* Return a pointer to the body for the GIMPLE_TRANSACTION statement GS.  */
@@ -5147,8 +5579,9 @@ gimple_omp_continue_set_control_use (gimple g, tree use)
 static inline gimple_seq *
 gimple_transaction_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return &gs->gimple_transaction.body;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  return &transaction_stmt->body;
 }
 
 /* Return the body for the GIMPLE_TRANSACTION statement GS.  */
@@ -5164,15 +5597,17 @@ gimple_transaction_body (gimple gs)
 static inline tree
 gimple_transaction_label (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return gs->gimple_transaction.label;
+  const gimple_statement_transaction *transaction_stmt =
+    as_a <const gimple_statement_transaction> (gs);
+  return transaction_stmt->label;
 }
 
 static inline tree *
 gimple_transaction_label_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return &gs->gimple_transaction.label;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  return &transaction_stmt->label;
 }
 
 /* Return the subcode associated with a GIMPLE_TRANSACTION.  */
@@ -5181,7 +5616,7 @@ static inline unsigned int
 gimple_transaction_subcode (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return gs->gsbase.subcode;
+  return gs->subcode;
 }
 
 /* Set BODY to be the body for the GIMPLE_TRANSACTION statement GS.  */
@@ -5189,8 +5624,9 @@ gimple_transaction_subcode (const_gimple gs)
 static inline void
 gimple_transaction_set_body (gimple gs, gimple_seq body)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  gs->gimple_transaction.body = body;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  transaction_stmt->body = body;
 }
 
 /* Set the label associated with a GIMPLE_TRANSACTION.  */
@@ -5198,8 +5634,9 @@ gimple_transaction_set_body (gimple gs, gimple_seq body)
 static inline void
 gimple_transaction_set_label (gimple gs, tree label)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  gs->gimple_transaction.label = label;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  transaction_stmt->label = label;
 }
 
 /* Set the subcode associated with a GIMPLE_TRANSACTION.  */
@@ -5208,7 +5645,7 @@ static inline void
 gimple_transaction_set_subcode (gimple gs, unsigned int subcode)
 {
   GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  gs->gsbase.subcode = subcode;
+  gs->subcode = subcode;
 }
 
 
@@ -5318,7 +5755,7 @@ static inline enum br_predictor
 gimple_predict_predictor (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
-  return (enum br_predictor) (gs->gsbase.subcode & ~GF_PREDICT_TAKEN);
+  return (enum br_predictor) (gs->subcode & ~GF_PREDICT_TAKEN);
 }
 
 
@@ -5328,7 +5765,7 @@ static inline void
 gimple_predict_set_predictor (gimple gs, enum br_predictor predictor)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
-  gs->gsbase.subcode = (gs->gsbase.subcode & GF_PREDICT_TAKEN)
+  gs->subcode = (gs->subcode & GF_PREDICT_TAKEN)
 		       | (unsigned) predictor;
 }
 
@@ -5339,7 +5776,7 @@ static inline enum prediction
 gimple_predict_outcome (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
-  return (gs->gsbase.subcode & GF_PREDICT_TAKEN) ? TAKEN : NOT_TAKEN;
+  return (gs->subcode & GF_PREDICT_TAKEN) ? TAKEN : NOT_TAKEN;
 }
 
 
@@ -5350,9 +5787,9 @@ gimple_predict_set_outcome (gimple gs, enum prediction outcome)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
   if (outcome == TAKEN)
-    gs->gsbase.subcode |= GF_PREDICT_TAKEN;
+    gs->subcode |= GF_PREDICT_TAKEN;
   else
-    gs->gsbase.subcode &= ~GF_PREDICT_TAKEN;
+    gs->subcode &= ~GF_PREDICT_TAKEN;
 }
 
 
@@ -5491,7 +5928,7 @@ gsi_end_p (gimple_stmt_iterator i)
 static inline bool
 gsi_one_before_end_p (gimple_stmt_iterator i)
 {
-  return i.ptr != NULL && i.ptr->gsbase.next == NULL;
+  return i.ptr != NULL && i.ptr->next == NULL;
 }
 
 
@@ -5500,7 +5937,7 @@ gsi_one_before_end_p (gimple_stmt_iterator i)
 static inline void
 gsi_next (gimple_stmt_iterator *i)
 {
-  i->ptr = i->ptr->gsbase.next;
+  i->ptr = i->ptr->next;
 }
 
 /* Advance the iterator to the previous gimple statement.  */
@@ -5508,8 +5945,8 @@ gsi_next (gimple_stmt_iterator *i)
 static inline void
 gsi_prev (gimple_stmt_iterator *i)
 {
-  gimple prev = i->ptr->gsbase.prev;
-  if (prev->gsbase.next)
+  gimple prev = i->ptr->prev;
+  if (prev->next)
     i->ptr = prev;
   else
     i->ptr = NULL;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 74f333b..a600d3c 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2586,7 +2586,7 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
 		    && TREE_CODE ((**debug_args)[i + 1]) == DEBUG_EXPR_DECL)
 		  {
 		    t = (**debug_args)[i + 1];
-		    stmt->gsbase.subcode = GIMPLE_DEBUG_BIND;
+		    stmt->subcode = GIMPLE_DEBUG_BIND;
 		    gimple_debug_bind_set_value (stmt, t);
 		    break;
 		  }
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index 2cef1c4..65c636c 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -183,7 +183,7 @@ make_phi_node (tree var, int len)
   memset (phi, 0, (sizeof (struct gimple_statement_phi)
 		   - sizeof (struct phi_arg_d)
 		   + sizeof (struct phi_arg_d) * len));
-  phi->gsbase.code = GIMPLE_PHI;
+  phi->code = GIMPLE_PHI;
   gimple_init_singleton (phi);
   phi->gimple_phi.nargs = len;
   phi->gimple_phi.capacity = capacity;
-- 
1.7.11.7

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

* [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-10-31  5:45 RFC: gimple.[ch] break apart Andrew MacLeod
  2013-10-31  6:15 ` Jeff Law
@ 2013-10-31 16:41 ` David Malcolm
  2013-10-31 16:27   ` [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types David Malcolm
                     ` (9 more replies)
  2013-11-05 16:58 ` [patch] Create gimple-expr..[ch] ... was Re: RFC: gimple.[ch] break apart Andrew MacLeod
  2 siblings, 10 replies; 116+ messages in thread
From: David Malcolm @ 2013-10-31 16:41 UTC (permalink / raw)
  To: gcc-patches, Andrew MacLeod; +Cc: David Malcolm

[Shamelessly hijacking Andrew's thread about gimple.h refactoring,
since this seems on-topic for that, and I'm keen to hear from Andrew on
how the following would interact with his work - I *think* our two
cleanups are orthogonal.

[This is a revised version of the patches sent as:
  http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01788.html
and
  http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01954.html
which got bogged down in discussion of hand-written GTY hooks.  This
patch series updates things to make use of the new support in gengtype
for simple inheritance schemes]

The gimple statement types are currently implemented using a hand-coded
C inheritance scheme, with a "union gimple_statement_d" holding the
various possible structs for a statement.

The following series of patches convert it to a C++ hierarchy, using the
existing structs, eliminating the union. The "gimple" typedef changes
from being a
  (union gimple_statement_d *)
to being a:
  (struct gimple_statement_base *)

There are no virtual functions in the new code: the sizes of the various
structs are unchanged.

It makes use of "is-a.h", using the as_a <T> template function to
perform downcasts, which are checked (via gcc_checking_assert) in an
ENABLE_CHECKING build, and are simple casts in an unchecked build,
albeit it in an inlined function rather than a macro.

For example, one can write:

  gimple_statement_phi *phi =
    as_a <gimple_statement_phi> (gsi_stmt (gsi));

and then directly access the fields of the phi, as a phi.  The existing
accessor functions in gimple.h become somewhat redundant in this
scheme, but are preserved.

The earlier versions of the patches made all of the types GTY((user))
and provided hand-written implementations of the gc and pch marker
routines.  In this new version we rely on the support for simple
inheritance that I recently added to gengtype, by adding a "desc"
to the GTY marking for the base class, and a "tag" to the marking
for all of the concrete subclasses.  (I say "class", but all the types
remain structs since their fields are all publicly accessible).

As noted in the earlier patch, I believe this is a superior scheme to
the C implementation:

  * We can get closer to compile-time type-safety, checking the gimple
    code once and downcasting with an as_a, then directly accessing
    fields, rather than going through accessor functions that check
    each time.  In some places we may want to replace a "gimple" with
    a subclass e.g. phis are always of the phi subclass, to get full
    compile-time type-safety.

  * This scheme is likely to be easier for newbies to understand.
  
  * Currently in gdb, dereferencing a gimple leads to screenfuls of text,
    showing all the various union values.  With this, you get just the base
    class, and can cast it to the appropriate subclass.

  * With this, we're working directly with the language constructs,
    rather than rolling our own, and thus other tools can better
    understand the code. (e.g. doxygen).

Again, as noted in the earlier patch series, the names of the structs
are rather verbose.  I would prefer to also rename them all to eliminate
the "_statement" component:
  "gimple_statement_base" -> "gimple_base"
  "gimple_statement_phi"  -> "gimple_phi"
  "gimple_statement_omp"  -> "gimple_omp"
etc, but I didn't do this to mimimize the patch size.  But if the core
maintainers are up for that, I can redo the patch series with that
change also, or do that as a followup.

The patch is in 6 parts; all of them are needed together.

  * Patch 1 of 6: This patch adds inheritance to the various gimple
    types, eliminating the initial baseclass fields, and eliminating the
    union gimple_statement_d.   All the types remain structs.  They
    become marked with GTY(()), gaining GSS_ tag values.

  * Patch 2 of 6: This patch ports various accessor functions within
    gimple.h to the new scheme.

  * Patch 3 of 6: This patch is autogenerated by "refactor_gimple.py"
    from https://github.com/davidmalcolm/gcc-refactoring-scripts
    There is a test suite "test_refactor_gimple.py" which may give a
    clearer idea of the changes that the script makes (and add
    confidence that it's doing the right thing).
    The patch converts code of the form:
      {
        GIMPLE_CHECK (gs, SOME_CODE);
        gimple_subclass_get/set_some_field (gs, value);
      }
    to code of this form:
      {
        some_subclass *stmt = as_a <some_subclass> (gs);
        stmt->some_field = value;
      }
    It also autogenerates specializations of 
        is_a_helper <T>::test
    equivalent to a GIMPLE_CHECK() for use by is_a and as_a.

  * Patch 4 of 6: This patch implement further specializations of
    is_a_helper <T>::test, for gimple_has_ops and gimple_has_mem_ops.

  * Patch 5 of 6: This patch does the rest of porting from union access
    to subclass access (all the fiddly places that the script in patch 3
    couldn't handle).

  * Patch 6 of 6: This patch updates the gdb python pretty-printing
    hook.

Successfully bootstrapped and tested on x86_64-unknown-linux-gnu: all
testcases show the same results as an unpatched build (relative to
r204230).

OK for trunk?


David Malcolm (6):
  Convert gimple types from a union to C++ inheritance
  Hand-written port of various accessors within gimple.h
  Automated part of conversion of gimple types to use C++ inheritance
  Implement is_a_helper <>::test specializations for various gimple
    types
  Port various places from union access to subclass access.
  Update gdb hooks to reflect changes to gimple types

 gcc/Makefile.in           |    2 +-
 gcc/coretypes.h           |    5 +-
 gcc/gdbhooks.py           |    2 +-
 gcc/ggc.h                 |    6 +-
 gcc/gimple-iterator.c     |   72 +-
 gcc/gimple-pretty-print.c |    6 +-
 gcc/gimple-pretty-print.h |    4 +-
 gcc/gimple-ssa.h          |   16 +-
 gcc/gimple-streamer-in.c  |   19 +-
 gcc/gimple-streamer-out.c |    2 +-
 gcc/gimple.c              |   76 ++-
 gcc/gimple.h              | 1651 +++++++++++++++++++++++++++++----------------
 gcc/gimplify.c            |    4 +-
 gcc/system.h              |    2 +-
 gcc/tree-inline.c         |    2 +-
 gcc/tree-phinodes.c       |   39 +-
 gcc/tree-ssa-ccp.c        |    2 +-
 17 files changed, 1197 insertions(+), 713 deletions(-)

-- 
1.7.11.7

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

* [PATCH 6/6] Update gdb hooks to reflect changes to gimple types
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
                     ` (3 preceding siblings ...)
  2013-10-31 16:31   ` [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance David Malcolm
@ 2013-10-31 16:46   ` David Malcolm
  2013-11-14  9:10     ` Jeff Law
  2013-10-31 16:49   ` [PATCH 5/6] Port various places from union access to subclass access David Malcolm
                     ` (4 subsequent siblings)
  9 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-10-31 16:46 UTC (permalink / raw)
  To: gcc-patches, Andrew MacLeod; +Cc: David Malcolm

gcc/
	* gdbhooks.py (GimplePrinter.to_string): Update lookup of
	code field to reflect inheritance, rather than embedding of
	the base gimple type.
---
 gcc/gdbhooks.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index 53abf32..c05e574 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -240,7 +240,7 @@ class GimplePrinter:
     def to_string (self):
         if long(self.gdbval) == 0:
             return '<gimple 0x0>'
-        val_gimple_code = self.gdbval['gsbase']['code']
+        val_gimple_code = self.gdbval['code']
         val_gimple_code_name = gdb.parse_and_eval('gimple_code_name')
         val_code_name = val_gimple_code_name[long(val_gimple_code)]
         result = '<%s 0x%x' % (val_code_name.string(),
-- 
1.7.11.7

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

* [PATCH 5/6] Port various places from union access to subclass access.
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
                     ` (4 preceding siblings ...)
  2013-10-31 16:46   ` [PATCH 6/6] Update gdb hooks to reflect changes to " David Malcolm
@ 2013-10-31 16:49   ` David Malcolm
  2013-11-14  9:23     ` Jeff Law
  2013-10-31 18:43   ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) Basile Starynkevitch
                     ` (3 subsequent siblings)
  9 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-10-31 16:49 UTC (permalink / raw)
  To: gcc-patches, Andrew MacLeod; +Cc: David Malcolm

	* gimple-streamer-in.c (input_gimple_stmt): Port from union
	access to use of as_a.
	* gimple.c (gimple_build_asm_1): Likewise.
	(gimple_build_try): Likewise.  Also, return a specific subclass
	rather than just gimple.
	(gimple_build_resx): Port from union access to use of as_a.
	(gimple_build_eh_dispatch): Likewise.
	(gimple_build_omp_for): Likewise.  Also, convert allocation of iter
	now that gengtype no longer provides a typed allocator function.
	(gimple_copy): Likewise.
	* gimple.h (gimple_build_try): Return a specific subclass rather
	than just gimple.
	* gimplify.c (gimplify_cleanup_point_expr): Replace union access
	with subclass access by making use of new return type of
	gimple_build_try.
	* tree-phinodes.c: (allocate_phi_node): Return a
	"gimple_statement_phi *" rather than just a gimple.
	(resize_phi_node): Likewise.
	(make_phi_node): Replace union access with subclass access by
	making use of new return type of allocate_phi_node.
	(reserve_phi_args_for_new_edge): Replace union access with as_a.
	(remove_phi_arg_num): Accept a "gimple_statement_phi *" rather
	than just a gimple.
	(remove_phi_args): Update for change to remove_phi_arg_num.
---
 gcc/gimple-streamer-in.c | 11 ++++-----
 gcc/gimple.c             | 58 ++++++++++++++++++++++++++++++------------------
 gcc/gimple.h             |  3 ++-
 gcc/gimplify.c           |  4 ++--
 gcc/tree-phinodes.c      | 37 ++++++++++++++++--------------
 5 files changed, 66 insertions(+), 47 deletions(-)

diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index 4f31b83..2555dbe 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -129,13 +129,14 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
     case GIMPLE_ASM:
       {
 	/* FIXME lto.  Move most of this into a new gimple_asm_set_string().  */
+	gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (stmt);
 	tree str;
-	stmt->gimple_asm.ni = streamer_read_uhwi (ib);
-	stmt->gimple_asm.no = streamer_read_uhwi (ib);
-	stmt->gimple_asm.nc = streamer_read_uhwi (ib);
-	stmt->gimple_asm.nl = streamer_read_uhwi (ib);
+	asm_stmt->ni = streamer_read_uhwi (ib);
+	asm_stmt->no = streamer_read_uhwi (ib);
+	asm_stmt->nc = streamer_read_uhwi (ib);
+	asm_stmt->nl = streamer_read_uhwi (ib);
 	str = streamer_read_string_cst (data_in, ib);
-	stmt->gimple_asm.string = TREE_STRING_POINTER (str);
+	asm_stmt->string = TREE_STRING_POINTER (str);
       }
       /* Fallthru  */
 
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 9b1337a..e9ef8e0 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -641,21 +641,22 @@ static inline gimple
 gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
                     unsigned nclobbers, unsigned nlabels)
 {
-  gimple p;
+  gimple_statement_asm *p;
   int size = strlen (string);
 
   /* ASMs with labels cannot have outputs.  This should have been
      enforced by the front end.  */
   gcc_assert (nlabels == 0 || noutputs == 0);
 
-  p = gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
-			     ninputs + noutputs + nclobbers + nlabels);
+  p = as_a <gimple_statement_asm> (
+        gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
+			       ninputs + noutputs + nclobbers + nlabels));
 
-  p->gimple_asm.ni = ninputs;
-  p->gimple_asm.no = noutputs;
-  p->gimple_asm.nc = nclobbers;
-  p->gimple_asm.nl = nlabels;
-  p->gimple_asm.string = ggc_alloc_string (string, size);
+  p->ni = ninputs;
+  p->no = noutputs;
+  p->nc = nclobbers;
+  p->nl = nlabels;
+  p->string = ggc_alloc_string (string, size);
 
   if (GATHER_STATISTICS)
     gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size;
@@ -767,14 +768,14 @@ gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
    KIND is either GIMPLE_TRY_CATCH or GIMPLE_TRY_FINALLY depending on
    whether this is a try/catch or a try/finally respectively.  */
 
-gimple
+gimple_statement_try *
 gimple_build_try (gimple_seq eval, gimple_seq cleanup,
     		  enum gimple_try_flags kind)
 {
-  gimple p;
+  gimple_statement_try *p;
 
   gcc_assert (kind == GIMPLE_TRY_CATCH || kind == GIMPLE_TRY_FINALLY);
-  p = gimple_alloc (GIMPLE_TRY, 0);
+  p = as_a <gimple_statement_try> (gimple_alloc (GIMPLE_TRY, 0));
   gimple_set_subcode (p, kind);
   if (eval)
     gimple_try_set_eval (p, eval);
@@ -804,8 +805,10 @@ gimple_build_wce (gimple_seq cleanup)
 gimple
 gimple_build_resx (int region)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0);
-  p->gimple_eh_ctrl.region = region;
+  gimple_statement_eh_ctrl *p =
+    as_a <gimple_statement_eh_ctrl> (
+      gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
+  p->region = region;
   return p;
 }
 
@@ -852,8 +855,10 @@ gimple_build_switch (tree index, tree default_label, vec<tree> args)
 gimple
 gimple_build_eh_dispatch (int region)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0);
-  p->gimple_eh_ctrl.region = region;
+  gimple_statement_eh_ctrl *p =
+    as_a <gimple_statement_eh_ctrl> (
+      gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
+  p->region = region;
   return p;
 }
 
@@ -927,14 +932,17 @@ gimple
 gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
 		      gimple_seq pre_body)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_FOR, 0);
+  gimple_statement_omp_for *p =
+    as_a <gimple_statement_omp_for> (gimple_alloc (GIMPLE_OMP_FOR, 0));
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_for_set_clauses (p, clauses);
   gimple_omp_for_set_kind (p, kind);
-  p->gimple_omp_for.collapse = collapse;
-  p->gimple_omp_for.iter
-      = ggc_alloc_cleared_vec_gimple_omp_for_iter (collapse);
+  p->collapse = collapse;
+  p->iter =  static_cast <struct gimple_omp_for_iter *> (
+   ggc_internal_cleared_vec_alloc_stat (sizeof (*p->iter),
+					collapse MEM_STAT_INFO));
+
   if (pre_body)
     gimple_omp_for_set_pre_body (p, pre_body);
 
@@ -2311,9 +2319,15 @@ gimple_copy (gimple stmt)
 	  gimple_omp_for_set_pre_body (copy, new_seq);
 	  t = unshare_expr (gimple_omp_for_clauses (stmt));
 	  gimple_omp_for_set_clauses (copy, t);
-	  copy->gimple_omp_for.iter
-	    = ggc_alloc_vec_gimple_omp_for_iter
-	    (gimple_omp_for_collapse (stmt));
+	  {
+	    gimple_statement_omp_for *omp_for_copy =
+	      as_a <gimple_statement_omp_for> (copy);
+	    omp_for_copy->iter =
+	      static_cast <struct gimple_omp_for_iter *> (
+		  ggc_internal_vec_alloc_stat (sizeof (struct gimple_omp_for_iter),
+					       gimple_omp_for_collapse (stmt)
+					       MEM_STAT_INFO));
+          }
 	  for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
 	    {
 	      gimple_omp_for_set_cond (copy, i,
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 710ce04..35bfa06 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1074,7 +1074,8 @@ gimple gimple_build_catch (tree, gimple_seq);
 gimple gimple_build_eh_filter (tree, gimple_seq);
 gimple gimple_build_eh_must_not_throw (tree);
 gimple gimple_build_eh_else (gimple_seq, gimple_seq);
-gimple gimple_build_try (gimple_seq, gimple_seq, enum gimple_try_flags);
+gimple_statement_try *gimple_build_try (gimple_seq, gimple_seq,
+					enum gimple_try_flags);
 gimple gimple_build_wce (gimple_seq);
 gimple gimple_build_resx (int);
 gimple gimple_build_eh_dispatch (int);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 1f18466..5869441 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -5456,7 +5456,7 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
 	    }
 	  else
 	    {
-	      gimple gtry;
+	      gimple_statement_try *gtry;
 	      gimple_seq seq;
 	      enum gimple_try_flags kind;
 
@@ -5470,7 +5470,7 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
               /* Do not use gsi_replace here, as it may scan operands.
                  We want to do a simple structural modification only.  */
 	      gsi_set_stmt (&iter, gtry);
-	      iter = gsi_start (gtry->gimple_try.eval);
+	      iter = gsi_start (gtry->eval);
 	    }
 	}
       else
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index 65c636c..6e425fe 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -92,10 +92,10 @@ phinodes_print_statistics (void)
    happens to contain a PHI node with LEN arguments or more, return
    that one.  */
 
-static inline gimple
+static inline gimple_statement_phi *
 allocate_phi_node (size_t len)
 {
-  gimple phi;
+  gimple_statement_phi *phi;
   size_t bucket = NUM_BUCKETS - 2;
   size_t size = sizeof (struct gimple_statement_phi)
 	        + (len - 1) * sizeof (struct phi_arg_d);
@@ -110,7 +110,7 @@ allocate_phi_node (size_t len)
       && gimple_phi_capacity ((*free_phinodes[bucket])[0]) >= len)
     {
       free_phinode_count--;
-      phi = free_phinodes[bucket]->pop ();
+      phi = as_a <gimple_statement_phi> (free_phinodes[bucket]->pop ());
       if (free_phinodes[bucket]->is_empty ())
 	vec_free (free_phinodes[bucket]);
       if (GATHER_STATISTICS)
@@ -118,7 +118,8 @@ allocate_phi_node (size_t len)
     }
   else
     {
-      phi = ggc_alloc_gimple_statement_d (size);
+      phi = static_cast <gimple_statement_phi *> (
+	ggc_internal_alloc_stat (size MEM_STAT_INFO));
       if (GATHER_STATISTICS)
 	{
 	  enum gimple_alloc_kind kind = gimple_alloc_kind (GIMPLE_PHI);
@@ -170,7 +171,7 @@ ideal_phi_node_len (int len)
 static gimple
 make_phi_node (tree var, int len)
 {
-  gimple phi;
+  gimple_statement_phi *phi;
   int capacity, i;
 
   capacity = ideal_phi_node_len (len);
@@ -185,8 +186,8 @@ make_phi_node (tree var, int len)
 		   + sizeof (struct phi_arg_d) * len));
   phi->code = GIMPLE_PHI;
   gimple_init_singleton (phi);
-  phi->gimple_phi.nargs = len;
-  phi->gimple_phi.capacity = capacity;
+  phi->nargs = len;
+  phi->capacity = capacity;
   if (!var)
     ;
   else if (TREE_CODE (var) == SSA_NAME)
@@ -235,11 +236,11 @@ release_phi_node (gimple phi)
 /* Resize an existing PHI node.  The only way is up.  Return the
    possibly relocated phi.  */
 
-static gimple
-resize_phi_node (gimple phi, size_t len)
+static gimple_statement_phi *
+resize_phi_node (gimple_statement_phi *phi, size_t len)
 {
   size_t old_size, i;
-  gimple new_phi;
+  gimple_statement_phi *new_phi;
 
   gcc_assert (len > gimple_phi_capacity (phi));
 
@@ -262,7 +263,7 @@ resize_phi_node (gimple phi, size_t len)
       relink_imm_use_stmt (imm, old_imm, new_phi);
     }
 
-  new_phi->gimple_phi.capacity = len;
+  new_phi->capacity = len;
 
   for (i = gimple_phi_num_args (new_phi); i < len; i++)
     {
@@ -290,11 +291,12 @@ reserve_phi_args_for_new_edge (basic_block bb)
 
   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      gimple stmt = gsi_stmt (gsi);
+      gimple_statement_phi *stmt =
+	as_a <gimple_statement_phi> (gsi_stmt (gsi));
 
       if (len > gimple_phi_capacity (stmt))
 	{
-	  gimple new_phi = resize_phi_node (stmt, cap);
+	  gimple_statement_phi *new_phi = resize_phi_node (stmt, cap);
 
 	  /* The result of the PHI is defined by this PHI node.  */
 	  SSA_NAME_DEF_STMT (gimple_phi_result (new_phi)) = new_phi;
@@ -314,7 +316,7 @@ reserve_phi_args_for_new_edge (basic_block bb)
       SET_PHI_ARG_DEF (stmt, len - 1, NULL_TREE);
       gimple_phi_arg_set_location (stmt, len - 1, UNKNOWN_LOCATION);
 
-      stmt->gimple_phi.nargs++;
+      stmt->nargs++;
     }
 }
 
@@ -390,7 +392,7 @@ add_phi_arg (gimple phi, tree def, edge e, source_location locus)
    is consistent with how we remove an edge from the edge vector.  */
 
 static void
-remove_phi_arg_num (gimple phi, int i)
+remove_phi_arg_num (gimple_statement_phi *phi, int i)
 {
   int num_elem = gimple_phi_num_args (phi);
 
@@ -417,7 +419,7 @@ remove_phi_arg_num (gimple phi, int i)
   /* Shrink the vector and return.  Note that we do not have to clear
      PHI_ARG_DEF because the garbage collector will not look at those
      elements beyond the first PHI_NUM_ARGS elements of the array.  */
-  phi->gimple_phi.nargs--;
+  phi->nargs--;
 }
 
 
@@ -429,7 +431,8 @@ remove_phi_args (edge e)
   gimple_stmt_iterator gsi;
 
   for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
-    remove_phi_arg_num (gsi_stmt (gsi), e->dest_idx);
+    remove_phi_arg_num (as_a <gimple_statement_phi> (gsi_stmt (gsi)),
+			e->dest_idx);
 }
 
 
-- 
1.7.11.7

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
                     ` (5 preceding siblings ...)
  2013-10-31 16:49   ` [PATCH 5/6] Port various places from union access to subclass access David Malcolm
@ 2013-10-31 18:43   ` Basile Starynkevitch
  2013-11-01 21:36   ` Andrew MacLeod
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 116+ messages in thread
From: Basile Starynkevitch @ 2013-10-31 18:43 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Andrew MacLeod

On 10/31/2013 05:26 PM, David Malcolm wrote:
> [Shamelessly hijacking Andrew's thread about gimple.h refactoring,
> since this seems on-topic for that, and I'm keen to hear from Andrew on
> how the following would interact with his work - I *think* our two
> cleanups are orthogonal.
>
> [This is a revised version of the patches sent as:
>    http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01788.html
> and
>    http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01954.html
> which got bogged down in discussion of hand-written GTY hooks.  This
> patch series updates things to make use of the new support in gengtype
> for simple inheritance schemes]
>
> The gimple statement types are currently implemented using a hand-coded
> C inheritance scheme, with a "union gimple_statement_d" holding the
> various possible structs for a statement.
>
> The following series of patches convert it to a C++ hierarchy, using the
> existing structs, eliminating the union. The "gimple" typedef changes
> from being a
>    (union gimple_statement_d *)
> to being a:
>    (struct gimple_statement_base *)


Very good idea. But please, document that in some texinfo file, probably 
gcc/doc/gimple.texi

Gimple-s are so damn important, even for plugin writers, that a small 
but up to date documentation is absolutely essential. You don"t need to 
write a lot of doc, just the minimal stuff (which at least tells which 
file should the plugin writer look into and list all the relevant classes).

I hope your patches (or similar ones) will be accepted in 4.9

Regards.



-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
                     ` (6 preceding siblings ...)
  2013-10-31 18:43   ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) Basile Starynkevitch
@ 2013-11-01 21:36   ` Andrew MacLeod
  2013-11-01 21:41     ` Jakub Jelinek
                       ` (3 more replies)
  2013-11-05 21:33   ` Jeff Law
  2013-11-14  8:40   ` Jeff Law
  9 siblings, 4 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-01 21:36 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

On 10/31/2013 12:26 PM, David Malcolm wrote:
> [Shamelessly hijacking Andrew's thread about gimple.h refactoring,
> since this seems on-topic for that, and I'm keen to hear from Andrew on
> how the following would interact with his work - I *think* our two
> cleanups are orthogonal.

Mostly orthogonal anyway... just stomping on the same bits :-).

Since you hijacked a planning thread, do you plan to take this any 
further, or make this change and move on to something else?

It is a start, but it doesnt do the rest of the work that needs doing to 
really take advantage of it... which will be extensive.
for instance, we should change:

   static inline void
! gimple_call_set_lhs (gimple gs, tree lhs)
   {
-   GIMPLE_CHECK (gs, GIMPLE_CALL);
     gimple_set_op (gs, 0, lhs);
to
     static inline void
! gimple_call_set_lhs (gimple_statement_call *gs, tree lhs)
   {
     gimple_set_op (gs, 0, lhs);


but then every location that calls it needs an appropriate change:

!       gimple call;
!       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
alias), vargs);
         gimple_call_set_lhs (call, atree);

--- 1518,1524 ----

!       gimple_statement_call *call;
!       call = as_a<gimple_statement_call> (gimple_build_call_vec 
(build_fold_addr_expr_loc (0, alias), vargs));
         gimple_call_set_lhs (call, atree);

And in fact there is a ripple effect to then change 
gimple_build_call_vec to simply return a gimple_statement_call *... Then 
this doesn't look as ugly either...

!       gimple_statement_call *call;
!       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
alias), vargs);
         gimple_call_set_lhs (call, atree);

that is looking much better :-)


Leaving the names as they are should be ok, but the I'd also add a 
typedef for the pointer without the 'statement' in the name.. ie
     typedef gimple_statement_call *gimple_call;
That seems in line with what we do with 'gimple' right now and the short 
form is the type we'd normally use.

That adds a touch of difficulty with "as_a", since that requires the 
type name, not the shorthand pointer.... so you have something like
gimple_call call = as_a <gimple_statement_call> blah().
I think as the changes to use the gimple_call type are pushed through 
all the callers and callee's, the requirement of as_a and the long name 
being ugly begins to rapidly disappear...  it'll only exist in the core 
creation routines and no one will usually see it.   So I don't *think* 
this is an issue...  but it is an ugly transition if its only partially 
done.

And eventually we can pull the accessor routines and others into the 
class itself:
        gimple_call call;
        call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
alias), vargs);
        call->set_lhs (atree);

Which results in a similar feel to the new gimple_type, gimple_decl, 
etc. classes with my upcoming tree wrappers.  Changing gimple statements 
to behave something like this is actually mentioned in the plan, but out 
in the future once trees have been taken care of.

I would also plan to create instances for each of the gimple statements 
that don't have them now, like gimple_statement_assign. Its lumped in as 
a general GSS_WITH_MEM_OPS, so there is no gimple_statement_assign 
class/struct to use.

It would really be nice to use the DEFGSCODE macro and gimple.def to 
make this happen automagically somehow... Its tantalizingly close now I 
think, especially combined with the info in gsstruct.def... Although if 
we are moving to proper classes eventually its probably better to 
explicitly write the required class for a statement kind.

That all said, this change enables that work to proceed if someone wants 
to do it.

My question is: Is anyone going to do it, and if so,  who and when? :-)


>
> Again, as noted in the earlier patch series, the names of the structs
> are rather verbose.  I would prefer to also rename them all to eliminate
> the "_statement" component:
>    "gimple_statement_base" -> "gimple_base"
>    "gimple_statement_phi"  -> "gimple_phi"
>    "gimple_statement_omp"  -> "gimple_omp"
> etc, but I didn't do this to mimimize the patch size.  But if the core
> maintainers are up for that, I can redo the patch series with that
> change also, or do that as a followup.

As mentioned, I'd rather see the short names be typedefs for pointers to 
the long names since we're typically using the pointers.

Other than stomping on the same bits at the moment (less so once 
gimple-stmt.[ch] is split out), these changes are completely orthogonal, 
but in line with with my direction.  I think It should be done sooner or 
later....  My preference is to also see the follow up work carried out 
as well.  Or at least a plan for it.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:36   ` Andrew MacLeod
@ 2013-11-01 21:41     ` Jakub Jelinek
  2013-11-01 21:47       ` Andrew MacLeod
  2013-11-04 18:23       ` Jeff Law
  2013-11-01 22:43     ` David Malcolm
                       ` (2 subsequent siblings)
  3 siblings, 2 replies; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-01 21:41 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: David Malcolm, gcc-patches

On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>   static inline void
> ! gimple_call_set_lhs (gimple gs, tree lhs)
>   {
> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>     gimple_set_op (gs, 0, lhs);
> to
>     static inline void
> ! gimple_call_set_lhs (gimple_statement_call *gs, tree lhs)
>   {
>     gimple_set_op (gs, 0, lhs);
> 
> 
> but then every location that calls it needs an appropriate change:
> 
> !       gimple call;
> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
> alias), vargs);
>         gimple_call_set_lhs (call, atree);
> 
> --- 1518,1524 ----
> 
> !       gimple_statement_call *call;
> !       call = as_a<gimple_statement_call> (gimple_build_call_vec
> (build_fold_addr_expr_loc (0, alias), vargs));
>         gimple_call_set_lhs (call, atree);
> 
> And in fact there is a ripple effect to then change
> gimple_build_call_vec to simply return a gimple_statement_call *...
> Then this doesn't look as ugly either...
> 
> !       gimple_statement_call *call;
> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
> alias), vargs);
>         gimple_call_set_lhs (call, atree);
> 
> that is looking much better :-)

Do you seriously think this is an improvement?  The cost of changing
the --enable-checking=yes cost to compile time checking in either
cases sounds way too high to me.  Please don't.

	Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:41     ` Jakub Jelinek
@ 2013-11-01 21:47       ` Andrew MacLeod
  2013-11-01 21:57         ` Jakub Jelinek
  2013-11-04 18:23       ` Jeff Law
  1 sibling, 1 reply; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-01 21:47 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: David Malcolm, gcc-patches

On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>>    static inline void
>> ! gimple_call_set_lhs (gimple gs, tree lhs)
>>    {
>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>>      gimple_set_op (gs, 0, lhs);
>> to
>>      static inline void
>> ! gimple_call_set_lhs (gimple_statement_call *gs, tree lhs)
>>    {
>>      gimple_set_op (gs, 0, lhs);
>>
>>
>> but then every location that calls it needs an appropriate change:
>>
>> !       gimple call;
>> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
>> alias), vargs);
>>          gimple_call_set_lhs (call, atree);
>>
>> --- 1518,1524 ----
>>
>> !       gimple_statement_call *call;
>> !       call = as_a<gimple_statement_call> (gimple_build_call_vec
>> (build_fold_addr_expr_loc (0, alias), vargs));
>>          gimple_call_set_lhs (call, atree);
>>
>> And in fact there is a ripple effect to then change
>> gimple_build_call_vec to simply return a gimple_statement_call *...
>> Then this doesn't look as ugly either...
>>
>> !       gimple_statement_call *call;
>> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
>> alias), vargs);
>>          gimple_call_set_lhs (call, atree);
>>
>> that is looking much better :-)
> Do you seriously think this is an improvement?  The cost of changing
> the --enable-checking=yes cost to compile time checking in either
> cases sounds way too high to me.  Please don't.

What checking?  There ought to be no checking at all in this example...  
gimple_build_call_vec returns a gimple_call, and gimple_call_set_lhs()  
doesn't have to check anything because it only accepts gimple_call's.. 
so there is no checking other than the usual "does my parameter match" 
that the compiler has to do...

What extra are you expecting?

Andrew



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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:47       ` Andrew MacLeod
@ 2013-11-01 21:57         ` Jakub Jelinek
  2013-11-01 22:58           ` David Malcolm
  2013-11-04 14:00           ` Andrew MacLeod
  0 siblings, 2 replies; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-01 21:57 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: David Malcolm, gcc-patches

On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
> >On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
> >>   static inline void
> >>! gimple_call_set_lhs (gimple gs, tree lhs)
> >>   {
> >>-   GIMPLE_CHECK (gs, GIMPLE_CALL);

The checking you are removing here.

> What checking?  There ought to be no checking at all in this
> example...  gimple_build_call_vec returns a gimple_call, and
> gimple_call_set_lhs()  doesn't have to check anything because it
> only accepts gimple_call's.. so there is no checking other than the
> usual "does my parameter match" that the compiler has to do...

and want to replace it by checking of the types at compile time.
The problem is that it uglifies the source too much, and, when you
actually don't have a gimple_call but supposedly a base class of it,
I expect you'd do as_a which is not only further uglification, but has
runtime cost also for --enable-checking=release.

	Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:36   ` Andrew MacLeod
  2013-11-01 21:41     ` Jakub Jelinek
@ 2013-11-01 22:43     ` David Malcolm
  2013-11-01 23:43       ` Trevor Saunders
  2013-11-04 13:15       ` Andrew MacLeod
  2013-11-05 17:23     ` [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)) David Malcolm
  2013-11-05 18:22     ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) Andrew MacLeod
  3 siblings, 2 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-01 22:43 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

On Fri, 2013-11-01 at 17:36 -0400, Andrew MacLeod wrote:
> On 10/31/2013 12:26 PM, David Malcolm wrote:
> > [Shamelessly hijacking Andrew's thread about gimple.h refactoring,
> > since this seems on-topic for that, and I'm keen to hear from Andrew on
> > how the following would interact with his work - I *think* our two
> > cleanups are orthogonal.
> 
> Mostly orthogonal anyway... just stomping on the same bits :-).
> 
> Since you hijacked a planning thread, do you plan to take this any 
> further, or make this change and move on to something else?

I have various changes that are mostly done that I'm trying to get
finished and into trunk for stage1.  These can be seen at:
https://github.com/davidmalcolm/gcc-refactoring-scripts/blob/master/README.rst

If you want me to do more follow cleanups to gimple, I can do those.

> It is a start, but it doesnt do the rest of the work that needs doing to 
> really take advantage of it... which will be extensive.
> for instance, we should change:
> 
>    static inline void
> ! gimple_call_set_lhs (gimple gs, tree lhs)
>    {
> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>      gimple_set_op (gs, 0, lhs);
> to
>      static inline void
> ! gimple_call_set_lhs (gimple_statement_call *gs, tree lhs)
>    {
>      gimple_set_op (gs, 0, lhs);
> 
> 
> but then every location that calls it needs an appropriate change:
> 
> !       gimple call;
> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> alias), vargs);
>          gimple_call_set_lhs (call, atree);
> 
> --- 1518,1524 ----
> 
> !       gimple_statement_call *call;
> !       call = as_a<gimple_statement_call> (gimple_build_call_vec 
> (build_fold_addr_expr_loc (0, alias), vargs));
>          gimple_call_set_lhs (call, atree);
> 
> And in fact there is a ripple effect to then change 
> gimple_build_call_vec to simply return a gimple_statement_call *... Then 
> this doesn't look as ugly either...
> 
> !       gimple_statement_call *call;
> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> alias), vargs);
>          gimple_call_set_lhs (call, atree);
> 
> that is looking much better :-)

I'd love to make use of compile-time type-safety like this, but does
this have to gate this initial step?

The transition to strongly-typed getters/setters could be done one
at-a-time, I guess.


> Leaving the names as they are should be ok, but the I'd also add a 
> typedef for the pointer without the 'statement' in the name.. ie
>      typedef gimple_statement_call *gimple_call;
> That seems in line with what we do with 'gimple' right now and the short 
> form is the type we'd normally use.
> 
> That adds a touch of difficulty with "as_a", since that requires the 
> type name, not the shorthand pointer.... so you have something like
> gimple_call call = as_a <gimple_statement_call> blah().
> I think as the changes to use the gimple_call type are pushed through 
> all the callers and callee's, the requirement of as_a and the long name 
> being ugly begins to rapidly disappear...  it'll only exist in the core 
> creation routines and no one will usually see it.   So I don't *think* 
> this is an issue...  but it is an ugly transition if its only partially 
> done.

(nods)

> And eventually we can pull the accessor routines and others into the 
> class itself:
>         gimple_call call;
>         call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> alias), vargs);
>         call->set_lhs (atree);

Nice.  It's readable (IMHO), and the type-checking (that it's a call) is
enforced at compile-time, rather than at run-time (and only in
ENABLE_CHECKING builds).

Sadly, this may need some further gengtype work: the simple inheritance
support I'm using in this patch series will barf if it sees methods
within a class.  So I can have a look at supporting methods in gengtype,
I guess.   Though the change above of gimple_call_set_lhs to accepting a
subclass ptr gives a middle-ground.

> Which results in a similar feel to the new gimple_type, gimple_decl, 
> etc. classes with my upcoming tree wrappers.  Changing gimple statements 
> to behave something like this is actually mentioned in the plan, but out 
> in the future once trees have been taken care of.
> 
> I would also plan to create instances for each of the gimple statements 
By "instances" presumably you meant "subclasses"?

> that don't have them now, like gimple_statement_assign. Its lumped in as 
> a general GSS_WITH_MEM_OPS, so there is no gimple_statement_assign 
> class/struct to use.

> It would really be nice to use the DEFGSCODE macro and gimple.def to 
> make this happen automagically somehow... Its tantalizingly close now I 
> think, especially combined with the info in gsstruct.def... Although if 
> we are moving to proper classes eventually its probably better to 
> explicitly write the required class for a statement kind.

I think writing them out explicitly is better than doing them with
preprocessor magic: if we go down the route described above of wanting
to add methods, the various subclasses will eventually gain their own
methods, so we'll want code rather than building it all from .def files.

> That all said, this change enables that work to proceed if someone wants 
> to do it.
> 
> My question is: Is anyone going to do it, and if so,  who and when? :-)

I'd be up for working on a followup patch that adds such subclasses, and
I'd be up for changing the accessors to give up compile-time
type-safety.  I'd do it one accessor at a time.

> > Again, as noted in the earlier patch series, the names of the structs
> > are rather verbose.  I would prefer to also rename them all to eliminate
> > the "_statement" component:
> >    "gimple_statement_base" -> "gimple_base"
> >    "gimple_statement_phi"  -> "gimple_phi"
> >    "gimple_statement_omp"  -> "gimple_omp"
> > etc, but I didn't do this to mimimize the patch size.  But if the core
> > maintainers are up for that, I can redo the patch series with that
> > change also, or do that as a followup.
> 
> As mentioned, I'd rather see the short names be typedefs for pointers to 
> the long names since we're typically using the pointers.

[FWIW, I'm not a fan of such typedefs, but I'll defer to you in this]

Presumably we'd want typedefs for the extra subclasses as well?

Also, I take it we'd use the "printable_name" from gimple.def - though
would we use it for the subclass name, or for the ptr typedef?

> Other than stomping on the same bits at the moment (less so once 
> gimple-stmt.[ch] is split out), these changes are completely orthogonal, 
> but in line with with my direction.  I think It should be done sooner or 
> later....  My preference is to also see the follow up work carried out 
> as well.  Or at least a plan for it.

So you like the approach, provided I commit to the followup work? [1]

OK, I'll try to create some followup patches next week.  I'd prefer to
get the conversion to inheritance into trunk sooner rather than later,
though.

Thanks for looking at this (and for your cleanup work!)

Dave
[1] and the patches still need formal review.

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:57         ` Jakub Jelinek
@ 2013-11-01 22:58           ` David Malcolm
  2013-11-04 13:23             ` Andrew MacLeod
  2013-11-04 14:00           ` Andrew MacLeod
  1 sibling, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-11-01 22:58 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Andrew MacLeod, gcc-patches

On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
> > On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
> > >On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
> > >>   static inline void
> > >>! gimple_call_set_lhs (gimple gs, tree lhs)
> > >>   {
> > >>-   GIMPLE_CHECK (gs, GIMPLE_CALL);
> 
> The checking you are removing here.
> 
> > What checking?  There ought to be no checking at all in this
> > example...  gimple_build_call_vec returns a gimple_call, and
> > gimple_call_set_lhs()  doesn't have to check anything because it
> > only accepts gimple_call's.. so there is no checking other than the
> > usual "does my parameter match" that the compiler has to do...
> 
> and want to replace it by checking of the types at compile time.
> The problem is that it uglifies the source too much, and, when you
> actually don't have a gimple_call but supposedly a base class of it,
> I expect you'd do as_a which is not only further uglification, but has
> runtime cost also for --enable-checking=release.

I can have a look next week at every call to gimple_call_set_lhs in the
tree, and see to what extent we know at compile-time that the initial
arg is indeed a call (of the ones I quickly grepped just now, most are
from gimple_build_call and friends, but one was from a gimple_copy).

FWIW I did some performance testing of the is_a/as_a code in the earlier
version of the patch, and it didn't have a noticable runtime cost
compared to the GIMPLE_CHECK in the existing code:
Size of compiler executable:
http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
Compile times:
http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html

Dave

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 22:43     ` David Malcolm
@ 2013-11-01 23:43       ` Trevor Saunders
  2013-11-04 13:15       ` Andrew MacLeod
  1 sibling, 0 replies; 116+ messages in thread
From: Trevor Saunders @ 2013-11-01 23:43 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrew MacLeod, gcc-patches

> > It is a start, but it doesnt do the rest of the work that needs doing to 
> > really take advantage of it... which will be extensive.
> > for instance, we should change:
> > 
> >    static inline void
> > ! gimple_call_set_lhs (gimple gs, tree lhs)
> >    {
> > -   GIMPLE_CHECK (gs, GIMPLE_CALL);
> >      gimple_set_op (gs, 0, lhs);
> > to
> >      static inline void
> > ! gimple_call_set_lhs (gimple_statement_call *gs, tree lhs)
> >    {
> >      gimple_set_op (gs, 0, lhs);
> > 
> > 
> > but then every location that calls it needs an appropriate change:
> > 
> > !       gimple call;
> > !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> > alias), vargs);
> >          gimple_call_set_lhs (call, atree);
> > 
> > --- 1518,1524 ----
> > 
> > !       gimple_statement_call *call;
> > !       call = as_a<gimple_statement_call> (gimple_build_call_vec 
> > (build_fold_addr_expr_loc (0, alias), vargs));
> >          gimple_call_set_lhs (call, atree);
> > 
> > And in fact there is a ripple effect to then change 
> > gimple_build_call_vec to simply return a gimple_statement_call *... Then 
> > this doesn't look as ugly either...
> > 
> > !       gimple_statement_call *call;
> > !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> > alias), vargs);
> >          gimple_call_set_lhs (call, atree);
> > 
> > that is looking much better :-)
> 
> I'd love to make use of compile-time type-safety like this, but does
> this have to gate this initial step?

 I don't think Andrew was suggesting it should, but fwiw I agree with
 you one step at a time.

> The transition to strongly-typed getters/setters could be done one
> at-a-time, I guess.

I actually have a slightly different suggestion, see below.

> > Leaving the names as they are should be ok, but the I'd also add a 
> > typedef for the pointer without the 'statement' in the name.. ie
> >      typedef gimple_statement_call *gimple_call;
> > That seems in line with what we do with 'gimple' right now and the short 
> > form is the type we'd normally use.
> > 
> > That adds a touch of difficulty with "as_a", since that requires the 
> > type name, not the shorthand pointer.... so you have something like
> > gimple_call call = as_a <gimple_statement_call> blah().
> > I think as the changes to use the gimple_call type are pushed through 
> > all the callers and callee's, the requirement of as_a and the long name 
> > being ugly begins to rapidly disappear...  it'll only exist in the core 
> > creation routines and no one will usually see it.   So I don't *think* 
> > this is an issue...  but it is an ugly transition if its only partially 
> > done.
> 
> (nods)
> 
> > And eventually we can pull the accessor routines and others into the 
> > class itself:
> >         gimple_call call;
> >         call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> > alias), vargs);
> >         call->set_lhs (atree);
> 
> Nice.  It's readable (IMHO), and the type-checking (that it's a call) is
> enforced at compile-time, rather than at run-time (and only in
> ENABLE_CHECKING builds).

Well, if you never need to downcast its always enforced by the type
system.

> Sadly, this may need some further gengtype work: the simple inheritance
> support I'm using in this patch series will barf if it sees methods
> within a class.  So I can have a look at supporting methods in gengtype,
> I guess.   Though the change above of gimple_call_set_lhs to accepting a
> subclass ptr gives a middle-ground.

hm, I have a patch around that adds member functions to symtab_node and
gentype doesn't fall over on it, is it just sub classes maybe?

 Anyway to avoid churn multiple times / ugly intermediates what I think
 we should do is:

 1. add methods to the sub classes as appropriate (fixing gentype first
 if needed).
 2. change creator functions to return dirived types.
 3. when we already have the sub type replace the function with the
 method.
 4. when all uses of the function are gone remove it.

> > that don't have them now, like gimple_statement_assign. Its lumped in as 
> > a general GSS_WITH_MEM_OPS, so there is no gimple_statement_assign 
> > class/struct to use.
> 
> > It would really be nice to use the DEFGSCODE macro and gimple.def to 
> > make this happen automagically somehow... Its tantalizingly close now I 
> > think, especially combined with the info in gsstruct.def... Although if 
> > we are moving to proper classes eventually its probably better to 
> > explicitly write the required class for a statement kind.
> 
> I think writing them out explicitly is better than doing them with
> preprocessor magic: if we go down the route described above of wanting
> to add methods, the various subclasses will eventually gain their own
> methods, so we'll want code rather than building it all from .def files.

agreed.

> > That all said, this change enables that work to proceed if someone wants 
> > to do it.
> > 
> > My question is: Is anyone going to do it, and if so,  who and when? :-)
> 
> I'd be up for working on a followup patch that adds such subclasses, and
> I'd be up for changing the accessors to give up compile-time
> type-safety.  I'd do it one accessor at a time.

I'd be happy to work on this too.

> > > Again, as noted in the earlier patch series, the names of the structs
> > > are rather verbose.  I would prefer to also rename them all to eliminate
> > > the "_statement" component:
> > >    "gimple_statement_base" -> "gimple_base"
> > >    "gimple_statement_phi"  -> "gimple_phi"
> > >    "gimple_statement_omp"  -> "gimple_omp"
> > > etc, but I didn't do this to mimimize the patch size.  But if the core
> > > maintainers are up for that, I can redo the patch series with that
> > > change also, or do that as a followup.
> > 
> > As mentioned, I'd rather see the short names be typedefs for pointers to 
> > the long names since we're typically using the pointers.
> 
> [FWIW, I'm not a fan of such typedefs, but I'll defer to you in this]

agreed, especially since C++ lets us omit the struct / class part
anyway.

Trev

> Also, I take it we'd use the "printable_name" from gimple.def - though
> would we use it for the subclass name, or for the ptr typedef?
> 
> > Other than stomping on the same bits at the moment (less so once 
> > gimple-stmt.[ch] is split out), these changes are completely orthogonal, 
> > but in line with with my direction.  I think It should be done sooner or 
> > later....  My preference is to also see the follow up work carried out 
> > as well.  Or at least a plan for it.
> 
> So you like the approach, provided I commit to the followup work? [1]
> 
> OK, I'll try to create some followup patches next week.  I'd prefer to
> get the conversion to inheritance into trunk sooner rather than later,
> though.
> 
> Thanks for looking at this (and for your cleanup work!)
> 
> Dave
> [1] and the patches still need formal review.
> 

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 22:43     ` David Malcolm
  2013-11-01 23:43       ` Trevor Saunders
@ 2013-11-04 13:15       ` Andrew MacLeod
  1 sibling, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-04 13:15 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

On 11/01/2013 06:42 PM, David Malcolm wrote:
>
>> !       gimple_statement_call *call;
>> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
>> alias), vargs);
>>           gimple_call_set_lhs (call, atree);
>>
>> that is looking much better :-)
> I'd love to make use of compile-time type-safety like this, but does
> this have to gate this initial step?
no, I wasn't implying it did... just mapping out what I think we can go 
on to do with it.

>
>> And eventually we can pull the accessor routines and others into the
>> class itself:
>>          gimple_call call;
>>          call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
>> alias), vargs);
>>          call->set_lhs (atree);
> Nice.  It's readable (IMHO), and the type-checking (that it's a call) is
> enforced at compile-time, rather than at run-time (and only in
> ENABLE_CHECKING builds).
>
> Sadly, this may need some further gengtype work: the simple inheritance
> support I'm using in this patch series will barf if it sees methods
> within a class.  So I can have a look at supporting methods in gengtype,
> I guess.   Though the change above of gimple_call_set_lhs to accepting a
> subclass ptr gives a middle-ground.
Eventually this is going to be an issue elsewhere as well.  Whats the 
problem with methods in gengtype?  it just doesn't parse them? or 
something deeper and more insidious?
>> Which results in a similar feel to the new gimple_type, gimple_decl,
>> etc. classes with my upcoming tree wrappers.  Changing gimple statements
>> to behave something like this is actually mentioned in the plan, but out
>> in the future once trees have been taken care of.
>>
>> I would also plan to create instances for each of the gimple statements
> By "instances" presumably you meant "subclasses"?
yeah.
>> That all said, this change enables that work to proceed if someone wants
>> to do it.
>>
>> My question is: Is anyone going to do it, and if so,  who and when? :-)
> I'd be up for working on a followup patch that adds such subclasses, and
> I'd be up for changing the accessors to give up compile-time
> type-safety.  I'd do it one accessor at a time.
Its probably pushing it for 4.9...  and doesn't really serve much 
purpose to try do do any of this followup work now.  Probably a better 
task  for the next stage 1 anyway when there is time to fully flush it 
out and prove the various improvements to have full support from 
everyone :-)
>>> Again, as noted in the earlier patch series, the names of the structs
>>> are rather verbose.  I would prefer to also rename them all to eliminate
>>> the "_statement" component:
>>>     "gimple_statement_base" -> "gimple_base"
>>>     "gimple_statement_phi"  -> "gimple_phi"
>>>     "gimple_statement_omp"  -> "gimple_omp"
>>> etc, but I didn't do this to mimimize the patch size.  But if the core
>>> maintainers are up for that, I can redo the patch series with that
>>> change also, or do that as a followup.
>> As mentioned, I'd rather see the short names be typedefs for pointers to
>> the long names since we're typically using the pointers.
> [FWIW, I'm not a fan of such typedefs, but I'll defer to you in this]

Just expressing my opinion :-)
>
> Presumably we'd want typedefs for the extra subclasses as well?
>
> Also, I take it we'd use the "printable_name" from gimple.def - though
> would we use it for the subclass name, or for the ptr typedef?

I would think a typedef for any type that we would directly refer to in 
the code, like a gimple_omp_clause, gimple_assign, or whatever.
>
>> Other than stomping on the same bits at the moment (less so once
>> gimple-stmt.[ch] is split out), these changes are completely orthogonal,
>> but in line with with my direction.  I think It should be done sooner or
>> later....  My preference is to also see the follow up work carried out
>> as well.  Or at least a plan for it.
> So you like the approach, provided I commit to the followup work? [1]
>
> OK, I'll try to create some followup patches next week.  I'd prefer to
> get the conversion to inheritance into trunk sooner rather than later,
> though.
>
> Thanks for looking at this (and for your cleanup work!)
>
> Dave
> [1] and the patches still need formal review.

Im not the one that has to be sold on this, I'm actually ambivalent to 
the change this close to the end of stage1...  I'm pointing out what we 
can eventually do with it in case it sways opinion..

I would have considered something similar in a "while" when the other 
refactoring work reached that point.  In some ways it might be better 
for next stage 1, but perhaps you have outlined enough benefits for it 
to be attractive to someone today.  It seems to be pretty neutral in 
most other respects.


Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 22:58           ` David Malcolm
@ 2013-11-04 13:23             ` Andrew MacLeod
  2013-11-04 21:52               ` David Malcolm
  0 siblings, 1 reply; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-04 13:23 UTC (permalink / raw)
  To: David Malcolm; +Cc: Jakub Jelinek, gcc-patches

On 11/01/2013 06:58 PM, David Malcolm wrote:
> On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
>> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
>>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
>>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>>>>>    static inline void
>>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
>>>>>    {
>>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>> The checking you are removing here.
>>
>>> What checking?  There ought to be no checking at all in this
>>> example...  gimple_build_call_vec returns a gimple_call, and
>>> gimple_call_set_lhs()  doesn't have to check anything because it
>>> only accepts gimple_call's.. so there is no checking other than the
>>> usual "does my parameter match" that the compiler has to do...
>> and want to replace it by checking of the types at compile time.
>> The problem is that it uglifies the source too much, and, when you
>> actually don't have a gimple_call but supposedly a base class of it,
>> I expect you'd do as_a which is not only further uglification, but has
>> runtime cost also for --enable-checking=release.
> I can have a look next week at every call to gimple_call_set_lhs in the
> tree, and see to what extent we know at compile-time that the initial
> arg is indeed a call (of the ones I quickly grepped just now, most are
> from gimple_build_call and friends, but one was from a gimple_copy).
>
> FWIW I did some performance testing of the is_a/as_a code in the earlier
> version of the patch, and it didn't have a noticable runtime cost
> compared to the GIMPLE_CHECK in the existing code:
> Size of compiler executable:
> http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
> Compile times:
> http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html
I actually really dislike as_a<> and is_a<>, and  think code needs to be 
restructured rather than use them, other than possibly at the very 
bottom level when we're allocating memory or something like that, or 
some kind of emergency :-)...   If we require frequent uses of those, 
I'd be against it, I find them quite ugly.

Like I said in the other reply, no rush, I don't think any of this 
follow up is appropriate this late in stage 1.  It would be more of an 
"interest" examination right now.. at least in my opinion...  I suspect 
thinks like gimple_assign are more complex cases, but without looking 
its hard to tell for sure.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:57         ` Jakub Jelinek
  2013-11-01 22:58           ` David Malcolm
@ 2013-11-04 14:00           ` Andrew MacLeod
  2013-11-04 14:01             ` Jakub Jelinek
  1 sibling, 1 reply; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-04 14:00 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: David Malcolm, gcc-patches

On 11/01/2013 05:57 PM, Jakub Jelinek wrote:
> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>>>>    static inline void
>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
>>>>    {
>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
> The checking you are removing here.
>
>> What checking?  There ought to be no checking at all in this
>> example...  gimple_build_call_vec returns a gimple_call, and
>> gimple_call_set_lhs()  doesn't have to check anything because it
>> only accepts gimple_call's.. so there is no checking other than the
>> usual "does my parameter match" that the compiler has to do...
> and want to replace it by checking of the types at compile time.
> The problem is that it uglifies the source too much, and, when you
> actually don't have a gimple_call but supposedly a base class of it,

But when you convert all the source base for gimple calls, then you have 
context pretty much everywhere.. you wont be doing it from a base 
class...  at least pretty infrequently.
> I expect you'd do as_a which is not only further uglification, but has
> runtime cost also for --enable-checking=release.
>
> 	
Im not a fan of as_a<> or is_a<> at all.  I really dislike them. They 
should be kept to the barest minimum, or even non existent if 
possible.....   If you need it, you probably need restructured source.  
ie, functions which work with switches on gimple_code() need to be 
restructured... And the end result should look cleaner.

Of course, thats what makes it a big project too :-)

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 14:00           ` Andrew MacLeod
@ 2013-11-04 14:01             ` Jakub Jelinek
  2013-11-04 14:15               ` Andrew MacLeod
  0 siblings, 1 reply; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-04 14:01 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: David Malcolm, gcc-patches

On Mon, Nov 04, 2013 at 08:54:40AM -0500, Andrew MacLeod wrote:
> >>What checking?  There ought to be no checking at all in this
> >>example...  gimple_build_call_vec returns a gimple_call, and
> >>gimple_call_set_lhs()  doesn't have to check anything because it
> >>only accepts gimple_call's.. so there is no checking other than the
> >>usual "does my parameter match" that the compiler has to do...
> >and want to replace it by checking of the types at compile time.
> >The problem is that it uglifies the source too much, and, when you
> >actually don't have a gimple_call but supposedly a base class of it,
> 
> But when you convert all the source base for gimple calls, then you
> have context pretty much everywhere.. you wont be doing it from a
> base class...  at least pretty infrequently.

Usually you just have IL which contains various kinds of statements,
it can be a call, assign, dozens of other gimple stmt forms.
If you need to modify something in these, you'd need to uglify with
as_a/is_a if you require everybody using these setters/getters to use
gimple_call * rather than gimple, pointer to any kind of stmt.

	Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 14:01             ` Jakub Jelinek
@ 2013-11-04 14:15               ` Andrew MacLeod
  0 siblings, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-04 14:15 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: David Malcolm, gcc-patches

On 11/04/2013 09:00 AM, Jakub Jelinek wrote:
> On Mon, Nov 04, 2013 at 08:54:40AM -0500, Andrew MacLeod wrote:
>>>> What checking?  There ought to be no checking at all in this
>>>> example...  gimple_build_call_vec returns a gimple_call, and
>>>> gimple_call_set_lhs()  doesn't have to check anything because it
>>>> only accepts gimple_call's.. so there is no checking other than the
>>>> usual "does my parameter match" that the compiler has to do...
>>> and want to replace it by checking of the types at compile time.
>>> The problem is that it uglifies the source too much, and, when you
>>> actually don't have a gimple_call but supposedly a base class of it,
>> But when you convert all the source base for gimple calls, then you
>> have context pretty much everywhere.. you wont be doing it from a
>> base class...  at least pretty infrequently.
> Usually you just have IL which contains various kinds of statements,
> it can be a call, assign, dozens of other gimple stmt forms.
> If you need to modify something in these, you'd need to uglify with
> as_a/is_a if you require everybody using these setters/getters to use
> gimple_call * rather than gimple, pointer to any kind of stmt.
>
> 	Jakub
In many cases splitting out the case body and typing functions will 
surprisingly cover many of the the uses required.
Proper subclassing will cover a lot too if the get/set methods are in 
the right classes.  In cases where none of this works...  well, there is 
an appropriate time for a virtual function...  Thats really all those 
kinds off switches are implementing....  but I won't get into that meta 
discussion right now :-).   We can save that for someday when there is 
actually a real proposal on the table.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:41     ` Jakub Jelinek
  2013-11-01 21:47       ` Andrew MacLeod
@ 2013-11-04 18:23       ` Jeff Law
  1 sibling, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-04 18:23 UTC (permalink / raw)
  To: Jakub Jelinek, Andrew MacLeod; +Cc: David Malcolm, gcc-patches

On 11/01/13 15:41, Jakub Jelinek wrote:
> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>>    static inline void
>> ! gimple_call_set_lhs (gimple gs, tree lhs)
>>    {
>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>>      gimple_set_op (gs, 0, lhs);
>> to
>>      static inline void
>> ! gimple_call_set_lhs (gimple_statement_call *gs, tree lhs)
>>    {
>>      gimple_set_op (gs, 0, lhs);
>>
>>
>> but then every location that calls it needs an appropriate change:
>>
>> !       gimple call;
>> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
>> alias), vargs);
>>          gimple_call_set_lhs (call, atree);
>>
>> --- 1518,1524 ----
>>
>> !       gimple_statement_call *call;
>> !       call = as_a<gimple_statement_call> (gimple_build_call_vec
>> (build_fold_addr_expr_loc (0, alias), vargs));
>>          gimple_call_set_lhs (call, atree);
>>
>> And in fact there is a ripple effect to then change
>> gimple_build_call_vec to simply return a gimple_statement_call *...
>> Then this doesn't look as ugly either...
>>
>> !       gimple_statement_call *call;
>> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0,
>> alias), vargs);
>>          gimple_call_set_lhs (call, atree);
>>
>> that is looking much better :-)
>
> Do you seriously think this is an improvement?  The cost of changing
> the --enable-checking=yes cost to compile time checking in either
> cases sounds way too high to me.  Please don't.
?!?  One of the things we're reallying trying to do here is be type safe 
and use the type system to check for things at compile-time rather than 
runtime checks.

jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 13:23             ` Andrew MacLeod
@ 2013-11-04 21:52               ` David Malcolm
  2013-11-04 22:09                 ` David Malcolm
                                   ` (2 more replies)
  0 siblings, 3 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-04 21:52 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Jakub Jelinek, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3139 bytes --]

On Mon, 2013-11-04 at 08:19 -0500, Andrew MacLeod wrote:
> On 11/01/2013 06:58 PM, David Malcolm wrote:
> > On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
> >> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
> >>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
> >>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
> >>>>>    static inline void
> >>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
> >>>>>    {
> >>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
> >> The checking you are removing here.
> >>
> >>> What checking?  There ought to be no checking at all in this
> >>> example...  gimple_build_call_vec returns a gimple_call, and
> >>> gimple_call_set_lhs()  doesn't have to check anything because it
> >>> only accepts gimple_call's.. so there is no checking other than the
> >>> usual "does my parameter match" that the compiler has to do...
> >> and want to replace it by checking of the types at compile time.
> >> The problem is that it uglifies the source too much, and, when you
> >> actually don't have a gimple_call but supposedly a base class of it,
> >> I expect you'd do as_a which is not only further uglification, but has
> >> runtime cost also for --enable-checking=release.
> > I can have a look next week at every call to gimple_call_set_lhs in the
> > tree, and see to what extent we know at compile-time that the initial
> > arg is indeed a call (of the ones I quickly grepped just now, most are
> > from gimple_build_call and friends, but one was from a gimple_copy).
> >
> > FWIW I did some performance testing of the is_a/as_a code in the earlier
> > version of the patch, and it didn't have a noticable runtime cost
> > compared to the GIMPLE_CHECK in the existing code:
> > Size of compiler executable:
> > http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
> > Compile times:
> > http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html
> I actually really dislike as_a<> and is_a<>, and  think code needs to be 
> restructured rather than use them, other than possibly at the very 
> bottom level when we're allocating memory or something like that, or 
> some kind of emergency :-)...   If we require frequent uses of those, 
> I'd be against it, I find them quite ugly.
> 
> Like I said in the other reply, no rush, I don't think any of this 
> follow up is appropriate this late in stage 1.  It would be more of an 
> "interest" examination right now.. at least in my opinion...  I suspect 
> thinks like gimple_assign are more complex cases, but without looking 
> its hard to tell for sure.

I tried converting gimple_call_set_lhs to accept a gimple_call, rather
than a gimple, and excitingly, it was easiest to also convert
cgraph_edge's call_stmt to also be a gimple_call, rather than just a
gimple.

Am attaching a patch (on top of the patch series being discussed) which
adds this compile-time typesafety; bootstrap is in-progress.   IMHO very
little use of is-a.h was needed (5 instances of as_a, and 3 of dyn_cast;
no use of is_a).

I'm also attaching a followup patch which eliminates gimple_call_set_lhs
in favor of a method of gimple_statement_call.


[-- Attachment #2: use-gimple_call-subclass.patch --]
[-- Type: text/x-patch, Size: 65895 bytes --]

commit ea57d6c7d3920cf27b23b7e978194a69be5f0071
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Mon Nov 4 15:22:45 2013 -0500

    FIXME: gimple_call_set_lhs (without methods)

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 4a4e9ac..6156993 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -764,7 +764,7 @@ cgraph_edge (struct cgraph_node *node, gimple call_stmt)
    edge, then update all components.  */
 
 void
-cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt,
+cgraph_set_call_stmt (struct cgraph_edge *e, gimple_call new_stmt,
 		      bool update_speculative)
 {
   tree decl;
@@ -817,7 +817,7 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt,
 
 static struct cgraph_edge *
 cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
-		       gimple call_stmt, gcov_type count, int freq,
+		       gimple_call call_stmt, gcov_type count, int freq,
 		       bool indir_unknown_callee)
 {
   struct cgraph_edge *edge;
@@ -889,7 +889,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
 
 struct cgraph_edge *
 cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
-		    gimple call_stmt, gcov_type count, int freq)
+		    gimple_call call_stmt, gcov_type count, int freq)
 {
   struct cgraph_edge *edge = cgraph_create_edge_1 (caller, callee, call_stmt,
 						   count, freq, false);
@@ -925,7 +925,7 @@ cgraph_allocate_init_indirect_info (void)
    PARAM_INDEX. */
 
 struct cgraph_edge *
-cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
+cgraph_create_indirect_edge (struct cgraph_node *caller, gimple_call call_stmt,
 			     int ecf_flags,
 			     gcov_type count, int freq)
 {
@@ -1298,7 +1298,7 @@ gimple
 cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
 {
   tree decl = gimple_call_fndecl (e->call_stmt);
-  gimple new_stmt;
+  gimple_call new_stmt;
   gimple_stmt_iterator gsi;
 #ifdef ENABLE_CHECKING
   struct cgraph_node *node;
@@ -1307,7 +1307,6 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
   if (e->speculative)
     {
       struct cgraph_edge *e2;
-      gimple new_stmt;
       struct ipa_ref *ref;
 
       cgraph_speculative_call_info (e, e, e2, ref);
@@ -1459,7 +1458,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
 static void
 cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
 					gimple old_stmt, tree old_call,
-					gimple new_stmt)
+					gimple_call new_stmt)
 {
   tree new_call = (new_stmt && is_gimple_call (new_stmt))
 		  ? gimple_call_fndecl (new_stmt) : 0;
@@ -1526,7 +1525,8 @@ cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
    of OLD_STMT before it was updated (updating can happen inplace).  */
 
 void
-cgraph_update_edges_for_call_stmt (gimple old_stmt, tree old_decl, gimple new_stmt)
+cgraph_update_edges_for_call_stmt (gimple old_stmt, tree old_decl,
+				   gimple_call new_stmt)
 {
   struct cgraph_node *orig = cgraph_get_node (cfun->decl);
   struct cgraph_node *node;
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 9171a79..9fab47b 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -458,7 +458,7 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgrap
   struct cgraph_edge *next_caller;
   struct cgraph_edge *prev_callee;
   struct cgraph_edge *next_callee;
-  gimple call_stmt;
+  gimple_call call_stmt;
   /* Additional information about an indirect call.  Not cleared when an edge
      becomes direct.  */
   struct cgraph_indirect_call_info *indirect_info;
@@ -626,8 +626,9 @@ void release_function_body (tree);
 void cgraph_node_remove_callees (struct cgraph_node *node);
 struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
 					struct cgraph_node *,
-					gimple, gcov_type, int);
-struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple,
+					gimple_call, gcov_type, int);
+struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *,
+						 gimple_call,
 						 int, gcov_type, int);
 struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
 struct cgraph_node * cgraph_create_node (tree);
@@ -639,8 +640,8 @@ struct cgraph_node * cgraph_add_thunk (struct cgraph_node *, tree, tree, bool, H
 				       HOST_WIDE_INT, tree, tree);
 struct cgraph_node *cgraph_node_for_asm (tree);
 struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
-void cgraph_set_call_stmt (struct cgraph_edge *, gimple, bool update_speculative = true);
-void cgraph_update_edges_for_call_stmt (gimple, tree, gimple);
+void cgraph_set_call_stmt (struct cgraph_edge *, gimple_call, bool update_speculative = true);
+void cgraph_update_edges_for_call_stmt (gimple, tree, gimple_call);
 struct cgraph_local_info *cgraph_local_info (tree);
 struct cgraph_global_info *cgraph_global_info (tree);
 struct cgraph_rtl_info *cgraph_rtl_info (tree);
@@ -748,7 +749,7 @@ bool expand_thunk (struct cgraph_node *, bool);
 /* In cgraphclones.c  */
 
 struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
-					struct cgraph_node *, gimple,
+					struct cgraph_node *, gimple_call,
 					unsigned, gcov_type, int, bool);
 struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type,
 					int, bool, vec<cgraph_edge_p>,
@@ -761,11 +762,11 @@ struct cgraph_node * cgraph_create_virtual_clone (struct cgraph_node *old_node,
 						  const char *clone_name);
 struct cgraph_node *cgraph_find_replacement_node (struct cgraph_node *);
 bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *);
-void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple,
+void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple_call,
 					    bool update_speculative = true);
 void cgraph_create_edge_including_clones (struct cgraph_node *,
 					  struct cgraph_node *,
-					  gimple, gimple, gcov_type, int,
+					  gimple, gimple_call, gcov_type, int,
 					  cgraph_inline_failed_t);
 void cgraph_materialize_all_clones (void);
 struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *,
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 1490cb7..b5f459d 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -319,16 +319,16 @@ build_cgraph_edges (void)
 	  if (is_gimple_debug (stmt))
 	    continue;
 
-	  if (is_gimple_call (stmt))
+	  if (gimple_call call_stmt = dyn_cast<gimple_statement_call> (stmt))
 	    {
 	      int freq = compute_call_stmt_bb_frequency (current_function_decl,
 							 bb);
 	      decl = gimple_call_fndecl (stmt);
 	      if (decl)
 		cgraph_create_edge (node, cgraph_get_create_node (decl),
-				    stmt, bb->count, freq);
+				    call_stmt, bb->count, freq);
 	      else
-		cgraph_create_indirect_edge (node, stmt,
+		cgraph_create_indirect_edge (node, call_stmt,
 					     gimple_call_flags (stmt),
 					     bb->count, freq);
 	    }
@@ -448,16 +448,16 @@ rebuild_cgraph_edges (void)
 	  gimple stmt = gsi_stmt (gsi);
 	  tree decl;
 
-	  if (is_gimple_call (stmt))
+	  if (gimple_call call_stmt = dyn_cast<gimple_statement_call> (stmt))
 	    {
 	      int freq = compute_call_stmt_bb_frequency (current_function_decl,
 							 bb);
 	      decl = gimple_call_fndecl (stmt);
 	      if (decl)
-		cgraph_create_edge (node, cgraph_get_create_node (decl), stmt,
+		cgraph_create_edge (node, cgraph_get_create_node (decl), call_stmt,
 				    bb->count, freq);
 	      else
-		cgraph_create_indirect_edge (node, stmt,
+		cgraph_create_indirect_edge (node, call_stmt,
 					     gimple_call_flags (stmt),
 					     bb->count, freq);
 	    }
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 373f501..e607e27 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -98,8 +98,8 @@ along with GCC; see the file COPYING3.  If not see
 /* Create clone of E in the node N represented by CALL_EXPR the callgraph.  */
 struct cgraph_edge *
 cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
-		   gimple call_stmt, unsigned stmt_uid, gcov_type count_scale,
-		   int freq_scale, bool update_original)
+		   gimple_call call_stmt, unsigned stmt_uid,
+		   gcov_type count_scale, int freq_scale, bool update_original)
 {
   struct cgraph_edge *new_edge;
   gcov_type count = apply_probability (e->count, count_scale);
@@ -488,7 +488,7 @@ cgraph_find_replacement_node (struct cgraph_node *node)
 
 void
 cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
-				       gimple old_stmt, gimple new_stmt,
+				       gimple old_stmt, gimple_call new_stmt,
 				       bool update_speculative)
 {
   struct cgraph_node *node;
@@ -545,7 +545,7 @@ void
 cgraph_create_edge_including_clones (struct cgraph_node *orig,
 				     struct cgraph_node *callee,
 				     gimple old_stmt,
-				     gimple stmt, gcov_type count,
+				     gimple_call stmt, gcov_type count,
 				     int freq,
 				     cgraph_inline_failed_t reason)
 {
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 39fb142..a9ab226 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1519,7 +1519,7 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks)
       tree restmp = NULL;
       vec<tree> vargs;
 
-      gimple call;
+      gimple_call call;
       gimple ret;
 
       if (in_lto_p)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3131efd..b76479c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -29419,7 +29419,7 @@ add_condition_to_bb (tree function_decl, tree version_decl,
   gimple return_stmt;
   tree convert_expr, result_var;
   gimple convert_stmt;
-  gimple call_cond_stmt;
+  gimple_call call_cond_stmt;
   gimple if_else_stmt;
 
   basic_block bb1, bb2, bb3;
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 5d60240..5a5cfbb 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -66,6 +66,9 @@ typedef const struct gimple_statement_base *const_gimple;
 typedef gimple gimple_seq;
 struct gimple_stmt_iterator_d;
 typedef struct gimple_stmt_iterator_d gimple_stmt_iterator;
+/* FWIW I'd rather simply have the class be called "gimple_call", and
+   make the pointerness be explicit rather than implicit.  */
+typedef struct gimple_statement_call *gimple_call;
 union section;
 typedef union section section;
 struct gcc_options;
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index d527d86..b24961b 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -142,6 +142,7 @@ lower_function_body (void)
   if (data.calls_builtin_setjmp)
     {
       tree disp_label, disp_var, arg;
+      gimple_call call;
 
       /* Build 'DISP_LABEL:' and insert.  */
       disp_label = create_artificial_label (cfun->function_end_locus);
@@ -156,11 +157,11 @@ lower_function_body (void)
       disp_var = create_tmp_var (ptr_type_node, "setjmpvar");
       arg = build_addr (disp_label, current_function_decl);
       t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER);
-      x = gimple_build_call (t, 1, arg);
-      gimple_call_set_lhs (x, disp_var);
+      call = gimple_build_call (t, 1, arg);
+      gimple_call_set_lhs (call, disp_var);
+      gsi_insert_after (&i, call, GSI_CONTINUE_LINKING);
 
       /* Build 'goto DISP_VAR;' and insert.  */
-      gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
       x = gimple_build_goto (disp_var);
       gsi_insert_after (&i, x, GSI_CONTINUE_LINKING);
     }
diff --git a/gcc/gimple.c b/gcc/gimple.c
index e9ef8e0..f31c935 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -200,10 +200,12 @@ gimple_call_reset_alias_info (gimple s)
    components of a GIMPLE_CALL statement to function FN with NARGS
    arguments.  */
 
-static inline gimple
+static inline gimple_call
 gimple_build_call_1 (tree fn, unsigned nargs)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
+  gimple_call s =
+    static_cast<gimple_call> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
+						     nargs + 3));
   if (TREE_CODE (fn) == FUNCTION_DECL)
     fn = build_fold_addr_expr (fn);
   gimple_set_op (s, 1, fn);
@@ -216,12 +218,12 @@ gimple_build_call_1 (tree fn, unsigned nargs)
 /* Build a GIMPLE_CALL statement to function FN with the arguments
    specified in vector ARGS.  */
 
-gimple
+gimple_call
 gimple_build_call_vec (tree fn, vec<tree> args)
 {
   unsigned i;
   unsigned nargs = args.length ();
-  gimple call = gimple_build_call_1 (fn, nargs);
+  gimple_call call = gimple_build_call_1 (fn, nargs);
 
   for (i = 0; i < nargs; i++)
     gimple_call_set_arg (call, i, args[i]);
@@ -233,11 +235,11 @@ gimple_build_call_vec (tree fn, vec<tree> args)
 /* Build a GIMPLE_CALL statement to function FN.  NARGS is the number of
    arguments.  The ... are the arguments.  */
 
-gimple
+gimple_call
 gimple_build_call (tree fn, unsigned nargs, ...)
 {
   va_list ap;
-  gimple call;
+  gimple_call call;
   unsigned i;
 
   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
@@ -256,10 +258,10 @@ gimple_build_call (tree fn, unsigned nargs, ...)
 /* Build a GIMPLE_CALL statement to function FN.  NARGS is the number of
    arguments.  AP contains the arguments.  */
 
-gimple
+gimple_call
 gimple_build_call_valist (tree fn, unsigned nargs, va_list ap)
 {
-  gimple call;
+  gimple_call call;
   unsigned i;
 
   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
@@ -277,10 +279,12 @@ gimple_build_call_valist (tree fn, unsigned nargs, va_list ap)
    Build the basic components of a GIMPLE_CALL statement to internal
    function FN with NARGS arguments.  */
 
-static inline gimple
+static inline gimple_call
 gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
+  gimple_call s =
+    static_cast<gimple_call> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
+						     nargs + 3));
   s->subcode |= GF_CALL_INTERNAL;
   gimple_call_set_internal_fn (s, fn);
   gimple_call_reset_alias_info (s);
@@ -291,11 +295,11 @@ gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
 /* Build a GIMPLE_CALL statement to internal function FN.  NARGS is
    the number of arguments.  The ... are the arguments.  */
 
-gimple
+gimple_call
 gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
 {
   va_list ap;
-  gimple call;
+  gimple_call call;
   unsigned i;
 
   call = gimple_build_call_internal_1 (fn, nargs);
@@ -311,11 +315,11 @@ gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
 /* Build a GIMPLE_CALL statement to internal function FN with the arguments
    specified in vector ARGS.  */
 
-gimple
+gimple_call
 gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
 {
   unsigned i, nargs;
-  gimple call;
+  gimple_call call;
 
   nargs = args.length ();
   call = gimple_build_call_internal_1 (fn, nargs);
@@ -330,11 +334,11 @@ gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
    assumed to be in GIMPLE form already.  Minimal checking is done of
    this fact.  */
 
-gimple
+gimple_call
 gimple_build_call_from_tree (tree t)
 {
   unsigned i, nargs;
-  gimple call;
+  gimple_call call;
   tree fndecl = get_callee_fndecl (t);
 
   gcc_assert (TREE_CODE (t) == CALL_EXPR);
@@ -2248,7 +2252,7 @@ gimple_set_lhs (gimple stmt, tree lhs)
   if (code == GIMPLE_ASSIGN)
     gimple_assign_set_lhs (stmt, lhs);
   else if (code == GIMPLE_CALL)
-    gimple_call_set_lhs (stmt, lhs);
+    gimple_call_set_lhs (static_cast<gimple_call> (stmt), lhs);
   else
     gcc_unreachable ();
 }
@@ -3059,14 +3063,14 @@ canonicalize_cond_expr_cond (tree t)
 /* Build a GIMPLE_CALL identical to STMT but skipping the arguments in
    the positions marked by the set ARGS_TO_SKIP.  */
 
-gimple
+gimple_call
 gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
 {
   int i;
   int nargs = gimple_call_num_args (stmt);
   vec<tree> vargs;
   vargs.create (nargs);
-  gimple new_stmt;
+  gimple_call new_stmt;
 
   for (i = 0; i < nargs; i++)
     if (!bitmap_bit_p (args_to_skip, i))
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 35bfa06..1180d3e 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1055,12 +1055,12 @@ gimple gimple_build_debug_source_bind_stat (tree, tree, gimple MEM_STAT_DECL);
 #define gimple_build_debug_source_bind(var,val,stmt)			\
   gimple_build_debug_source_bind_stat ((var), (val), (stmt) MEM_STAT_INFO)
 
-gimple gimple_build_call_vec (tree, vec<tree> );
-gimple gimple_build_call (tree, unsigned, ...);
-gimple gimple_build_call_valist (tree, unsigned, va_list);
-gimple gimple_build_call_internal (enum internal_fn, unsigned, ...);
-gimple gimple_build_call_internal_vec (enum internal_fn, vec<tree> );
-gimple gimple_build_call_from_tree (tree);
+gimple_call gimple_build_call_vec (tree, vec<tree> );
+gimple_call gimple_build_call (tree, unsigned, ...);
+gimple_call gimple_build_call_valist (tree, unsigned, va_list);
+gimple_call gimple_build_call_internal (enum internal_fn, unsigned, ...);
+gimple_call gimple_build_call_internal_vec (enum internal_fn, vec<tree> );
+gimple_call gimple_build_call_from_tree (tree);
 gimple gimplify_assign (tree, tree, gimple_seq *);
 gimple gimple_build_cond (enum tree_code, tree, tree, tree, tree);
 gimple gimple_build_label (tree label);
@@ -2551,9 +2551,8 @@ gimple_call_lhs_ptr (const_gimple gs)
 /* Set LHS to be the LHS operand of call statement GS.  */
 
 static inline void
-gimple_call_set_lhs (gimple gs, tree lhs)
+gimple_call_set_lhs (gimple_call gs, tree lhs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CALL);
   gimple_set_op (gs, 0, lhs);
   if (lhs && TREE_CODE (lhs) == SSA_NAME)
     SSA_NAME_DEF_STMT (lhs) = gs;
@@ -6134,7 +6133,7 @@ basic_block gsi_insert_on_edge_immediate (edge, gimple);
 basic_block gsi_insert_seq_on_edge_immediate (edge, gimple_seq);
 void gsi_commit_one_edge_insert (edge, basic_block *);
 void gsi_commit_edge_inserts (void);
-gimple gimple_call_copy_skip_args (gimple, bitmap);
+gimple_call gimple_call_copy_skip_args (gimple, bitmap);
 
 /* In gimplify.c.  */
 tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 5869441..e2c81b9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1160,7 +1160,7 @@ voidify_wrapper_expr (tree wrapper, tree temp)
    a temporary through which they communicate.  */
 
 static void
-build_stack_save_restore (gimple *save, gimple *restore)
+build_stack_save_restore (gimple_call *save, gimple_call *restore)
 {
   tree tmp_var;
 
@@ -1183,7 +1183,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
   tree t;
   gimple gimple_bind;
   gimple_seq body, cleanup;
-  gimple stack_save;
+  gimple_call stack_save;
 
   tree temp = voidify_wrapper_expr (bind_expr, NULL);
 
@@ -1233,7 +1233,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
   stack_save = NULL;
   if (gimplify_ctxp->save_stack)
     {
-      gimple stack_restore;
+      gimple_call stack_restore;
 
       /* Save stack on entry and restore it on exit.  Add a try_finally
 	 block to achieve this.  */
@@ -3438,7 +3438,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
     				gimple_seq *seq_p)
 {
   tree t, to, to_ptr, from, from_ptr;
-  gimple gs;
+  gimple_call gs;
   location_t loc = EXPR_LOCATION (*expr_p);
 
   to = TREE_OPERAND (*expr_p, 0);
@@ -3485,7 +3485,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
     				gimple_seq *seq_p)
 {
   tree t, from, to, to_ptr;
-  gimple gs;
+  gimple_call gs;
   location_t loc = EXPR_LOCATION (*expr_p);
 
   /* Assert our assumptions, to abort instead of producing wrong code
@@ -4876,11 +4876,12 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
       CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
       STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
-      assign = gimple_build_call_from_tree (*from_p);
+      gimple_call call = gimple_build_call_from_tree (*from_p);
+      assign = call;
       gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
       notice_special_calls (assign);
       if (!gimple_call_noreturn_p (assign))
-	gimple_call_set_lhs (assign, *to_p);
+	gimple_call_set_lhs (call, *to_p);
     }
   else
     {
@@ -7789,8 +7790,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	    tree id = TREE_OPERAND (*expr_p, 1);
 	    tree tmp = create_tmp_var_raw (TREE_TYPE(cond), NULL);
 	    gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
-	    gimple call = gimple_build_call_internal (IFN_ANNOTATE, 2,
-						      cond, id);
+	    gimple_call call = gimple_build_call_internal (IFN_ANNOTATE, 2,
+							   cond, id);
 	    gimple_call_set_lhs (call, tmp);
 	    gimplify_seq_add_stmt (pre_p, call);
 	    *expr_p = tmp;
@@ -8989,7 +8990,7 @@ gimplify_function_tree (tree fndecl)
       gimple tf;
       gimple_seq cleanup = NULL, body = NULL;
       tree tmp_var;
-      gimple call;
+      gimple_call call;
 
       x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 1ceabfa..642153d 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -3523,7 +3523,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
   struct cgraph_node *current_node = cgraph_get_node (current_function_decl);
   vec<tree> vargs;
   vec<tree, va_gc> **debug_args = NULL;
-  gimple new_stmt;
+  gimple_call new_stmt;
   gimple_stmt_iterator gsi, prev_gsi;
   tree callee_decl;
   int i, len;
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index 849868c..915533c 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1075,7 +1075,7 @@ split_function (struct split_point *split_point)
   basic_block return_bb = find_return_bb ();
   basic_block call_bb;
   gimple_stmt_iterator gsi;
-  gimple call;
+  gimple_call call;
   edge e;
   edge_iterator ei;
   tree retval = NULL, real_retval = NULL;
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index d4a52a7..e9e245a 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -771,7 +771,10 @@ fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts,
     {
       if (gimple_stmt_max_uid (fn) < cedge->lto_stmt_uid)
         fatal_error ("Cgraph edge statement index out of range");
-      cedge->call_stmt = stmts[cedge->lto_stmt_uid - 1];
+      gimple stmt = stmts[cedge->lto_stmt_uid - 1];
+      if (stmt)
+	gcc_assert (stmt->code == GIMPLE_CALL);
+      cedge->call_stmt = static_cast<gimple_call> (stmt);
       if (!cedge->call_stmt)
         fatal_error ("Cgraph edge statement index not found");
     }
@@ -779,7 +782,10 @@ fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts,
     {
       if (gimple_stmt_max_uid (fn) < cedge->lto_stmt_uid)
         fatal_error ("Cgraph edge statement index out of range");
-      cedge->call_stmt = stmts[cedge->lto_stmt_uid - 1];
+      gimple stmt = stmts[cedge->lto_stmt_uid - 1];
+      if (stmt)
+	gcc_assert (stmt->code == GIMPLE_CALL);
+      cedge->call_stmt = static_cast<gimple_call> (stmt);
       if (!cedge->call_stmt)
         fatal_error ("Cgraph edge statement index not found");
     }
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index a5b9210..dcececc 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2670,7 +2670,7 @@ build_omp_barrier (tree lhs)
 {
   tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
 					   : BUILT_IN_GOMP_BARRIER);
-  gimple g = gimple_build_call (fndecl, 0);
+  gimple_call g = gimple_build_call (fndecl, 0);
   if (lhs)
     gimple_call_set_lhs (g, lhs);
   return g;
@@ -3099,7 +3099,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 
 	      if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
 		{
-		  gimple stmt;
+		  gimple_call stmt;
 		  tree tmp, atmp;
 
 		  ptr = DECL_VALUE_EXPR (new_var);
@@ -3519,27 +3519,28 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
       /* Don't want uninit warnings on simduid, it is always uninitialized,
 	 but we use it not for the value, but for the DECL_UID only.  */
       TREE_NO_WARNING (uid) = 1;
-      gimple g
+      gimple_call call
 	= gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
-      gimple_call_set_lhs (g, lane);
+      gimple_call_set_lhs (call, lane);
       gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
-      gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
+      gsi_insert_before_without_update (&gsi, call, GSI_SAME_STMT);
       c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
       OMP_CLAUSE__SIMDUID__DECL (c) = uid;
       OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
       gimple_omp_for_set_clauses (ctx->stmt, c);
-      g = gimple_build_assign_with_ops (INTEGER_CST, lane,
-					build_int_cst (unsigned_type_node, 0),
-					NULL_TREE);
+      gimple g =
+	gimple_build_assign_with_ops (INTEGER_CST, lane,
+				      build_int_cst (unsigned_type_node, 0),
+				      NULL_TREE);
       gimple_seq_add_stmt (ilist, g);
       for (int i = 0; i < 2; i++)
 	if (llist[i])
 	  {
 	    tree vf = create_tmp_var (unsigned_type_node, NULL);
-	    g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
-	    gimple_call_set_lhs (g, vf);
+	    call = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
+	    gimple_call_set_lhs (call, vf);
 	    gimple_seq *seq = i == 0 ? ilist : dlist;
-	    gimple_seq_add_stmt (seq, g);
+	    gimple_seq_add_stmt (seq, call);
 	    tree t = build_int_cst (unsigned_type_node, 0);
 	    g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
 	    gimple_seq_add_stmt (seq, g);
@@ -3693,7 +3694,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
 		  if (lastlane == NULL)
 		    {
 		      lastlane = create_tmp_var (unsigned_type_node, NULL);
-		      gimple g
+		      gimple_call g
 			= gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
 						      2, simduid,
 						      TREE_OPERAND (val, 1));
@@ -5544,10 +5545,10 @@ expand_omp_for_generic (struct omp_region *region,
     t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
   else
     t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
-  stmt = gimple_build_call (t, 0);
+  gimple_call call = gimple_build_call (t, 0);
   if (gimple_omp_return_lhs (gsi_stmt (gsi)))
-    gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
-  gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
+    gimple_call_set_lhs (call, gimple_omp_return_lhs (gsi_stmt (gsi)));
+  gsi_insert_after (&gsi, call, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
 
   /* Connect the new blocks.  */
@@ -6867,6 +6868,7 @@ expand_omp_sections (struct omp_region *region)
   basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
   gimple_stmt_iterator si, switch_si;
   gimple sections_stmt, stmt, cont;
+  gimple_call call;
   edge_iterator ei;
   edge e;
   struct omp_region *inner;
@@ -6929,16 +6931,16 @@ expand_omp_sections (struct omp_region *region)
 	 call GOMP_sections_start.  */
       t = build_int_cst (unsigned_type_node, len - 1);
       u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
-      stmt = gimple_build_call (u, 1, t);
+      call = gimple_build_call (u, 1, t);
     }
   else
     {
       /* Otherwise, call GOMP_sections_next.  */
       u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
-      stmt = gimple_build_call (u, 0);
+      call = gimple_build_call (u, 0);
     }
-  gimple_call_set_lhs (stmt, vin);
-  gsi_insert_after (&si, stmt, GSI_SAME_STMT);
+  gimple_call_set_lhs (call, vin);
+  gsi_insert_after (&si, call, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
   /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
@@ -7026,9 +7028,9 @@ expand_omp_sections (struct omp_region *region)
       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
 
       bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
-      stmt = gimple_build_call (bfn_decl, 0);
-      gimple_call_set_lhs (stmt, vnext);
-      gsi_insert_after (&si, stmt, GSI_SAME_STMT);
+      call = gimple_build_call (bfn_decl, 0);
+      gimple_call_set_lhs (call, vnext);
+      gsi_insert_after (&si, call, GSI_SAME_STMT);
       gsi_remove (&si, true);
 
       single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
@@ -7042,10 +7044,10 @@ expand_omp_sections (struct omp_region *region)
     t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
   else
     t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
-  stmt = gimple_build_call (t, 0);
+  call = gimple_build_call (t, 0);
   if (gimple_omp_return_lhs (gsi_stmt (si)))
-    gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
-  gsi_insert_after (&si, stmt, GSI_SAME_STMT);
+    gimple_call_set_lhs (call, gimple_omp_return_lhs (gsi_stmt (si)));
+  gsi_insert_after (&si, call, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
   set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
@@ -8413,7 +8415,8 @@ lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
   location_t loc = gimple_location (single_stmt);
   tree tlabel = create_artificial_label (loc);
   tree flabel = create_artificial_label (loc);
-  gimple call, cond;
+  gimple_call call;
+  gimple cond;
   tree lhs, decl;
 
   decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
@@ -9863,6 +9866,7 @@ static void
 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 {
   gimple stmt = gsi_stmt (*gsi_p);
+  gimple_call call;
   struct walk_stmt_info wi;
 
   if (gimple_has_location (stmt))
@@ -9971,6 +9975,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
       break;
     case GIMPLE_CALL:
       tree fndecl;
+      call = static_cast<gimple_call> (stmt);
       fndecl = gimple_call_fndecl (stmt);
       if (fndecl
 	  && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
@@ -10005,7 +10010,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		gimple_call_set_fndecl (stmt, fndecl);
 		gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
 	      }
-	    gimple_call_set_lhs (stmt, lhs);
+	    gimple_call_set_lhs (call, lhs);
 	    tree fallthru_label;
 	    fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
 	    gimple g;
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index d74455d2..0358b26 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -1614,11 +1614,12 @@ lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi)
       n_seq = gimple_seq_alloc_with_stmt (g);
       e_seq = NULL;
 
-      g = gimple_build_call (builtin_decl_explicit (BUILT_IN_EH_POINTER),
-			     1, integer_zero_node);
+      gimple_call call =
+	gimple_build_call (builtin_decl_explicit (BUILT_IN_EH_POINTER),
+			   1, integer_zero_node);
       ptr = create_tmp_var (ptr_type_node, NULL);
-      gimple_call_set_lhs (g, ptr);
-      gimple_seq_add_stmt (&e_seq, g);
+      gimple_call_set_lhs (call, ptr);
+      gimple_seq_add_stmt (&e_seq, call);
 
       g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_COMMIT_EH),
 			     1, ptr);
@@ -2065,12 +2066,12 @@ transaction_subcode_ior (struct tm_region *region, unsigned flags)
 
    LOC is the location to use for the new statement(s).  */
 
-static gimple
+static gimple_call
 build_tm_load (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
 {
   enum built_in_function code = END_BUILTINS;
   tree t, type = TREE_TYPE (rhs), decl;
-  gimple gcall;
+  gimple_call gcall;
 
   if (type == float_type_node)
     code = BUILT_IN_TM_LOAD_FLOAT;
@@ -2310,6 +2311,7 @@ expand_call_tm (struct tm_region *region,
 		gimple_stmt_iterator *gsi)
 {
   gimple stmt = gsi_stmt (*gsi);
+  gimple_call call_stmt = as_a<gimple_statement_call> (stmt);
   tree lhs = gimple_call_lhs (stmt);
   tree fn_decl;
   struct cgraph_node *node;
@@ -2412,7 +2414,7 @@ expand_call_tm (struct tm_region *region,
 	      }
 	}
 
-      gimple_call_set_lhs (stmt, tmp);
+      gimple_call_set_lhs (call_stmt, tmp);
       update_stmt (stmt);
       stmt = gimple_build_assign (lhs, tmp);
       gimple_set_location (stmt, loc);
@@ -2698,7 +2700,7 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
     if (subcode & GTMA_IS_OUTER)
       region->original_transaction_was_outer = true;
     tree t = build_int_cst (tm_state_type, flags);
-    gimple call = gimple_build_call (tm_start, 1, t);
+    gimple_call call = gimple_build_call (tm_start, 1, t);
     gimple_call_set_lhs (call, tm_state);
     gimple_set_location (call, gimple_location (region->transaction_stmt));
 
@@ -4930,7 +4932,7 @@ ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region,
 			basic_block bb)
 {
   gimple_stmt_iterator gsi;
-  gimple g;
+  gimple_call g;
 
   transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE);
 
@@ -4954,10 +4956,11 @@ ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region,
 static bool
 ipa_tm_insert_gettmclone_call (struct cgraph_node *node,
 			       struct tm_region *region,
-			       gimple_stmt_iterator *gsi, gimple stmt)
+			       gimple_stmt_iterator *gsi, gimple_call stmt)
 {
   tree gettm_fn, ret, old_fn, callfn;
-  gimple g, g2;
+  gimple_call g;
+  gimple g2;
   bool safe;
 
   old_fn = gimple_call_fn (stmt);
@@ -5050,7 +5053,7 @@ ipa_tm_transform_calls_redirect (struct cgraph_node *node,
 				 gimple_stmt_iterator *gsi,
 				 bool *need_ssa_rename_p)
 {
-  gimple stmt = gsi_stmt (*gsi);
+  gimple_call stmt = as_a<gimple_statement_call> (gsi_stmt (*gsi));
   struct cgraph_node *new_node;
   struct cgraph_edge *e = cgraph_edge (node, stmt);
   tree fndecl = gimple_call_fndecl (stmt);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index d705657..8d82342 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -8262,6 +8262,7 @@ execute_fixup_cfg (void)
 		      : NULL;
 	  if (decl)
 	    {
+	      gimple_call call = static_cast<gimple_call> (stmt);
 	      int flags = gimple_call_flags (stmt);
 	      if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
 		{
@@ -8276,7 +8277,7 @@ execute_fixup_cfg (void)
 		}
 
 	      if (flags & ECF_NORETURN
-		  && fixup_noreturn_call (stmt))
+		  && fixup_noreturn_call (call))
 		todo |= TODO_cleanup_cfg;
 	     }
 
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index c627d2c..3cd625c 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -499,7 +499,7 @@ remove_forwarder_block (basic_block bb)
    and remove LHS.  Return true if something changed.  */
 
 bool
-fixup_noreturn_call (gimple stmt)
+fixup_noreturn_call (gimple_call stmt)
 {
   basic_block bb = gimple_bb (stmt);
   bool changed = false;
@@ -582,7 +582,7 @@ split_bbs_on_noreturn_calls (void)
 	    || !gimple_call_noreturn_p (stmt))
 	  continue;
 
-	changed |= fixup_noreturn_call (stmt);
+	changed |= fixup_noreturn_call (static_cast<gimple_call> (stmt));
       }
 
   return changed;
diff --git a/gcc/tree-cfgcleanup.h b/gcc/tree-cfgcleanup.h
index 6bd3c39..b7e0dde 100644
--- a/gcc/tree-cfgcleanup.h
+++ b/gcc/tree-cfgcleanup.h
@@ -23,6 +23,6 @@ along with GCC; see the file COPYING3.  If not see
 /* In tree-cfgcleanup.c  */
 extern bitmap cfgcleanup_altered_bbs;
 extern bool cleanup_tree_cfg (void);
-extern bool fixup_noreturn_call (gimple stmt);
+extern bool fixup_noreturn_call (gimple_call stmt);
 
 #endif /* GCC_TREE_CFGCLEANUP_H */
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 6439402..aee1e26 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -936,7 +936,8 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai,
   enum machine_mode mode;
   enum built_in_function bcode;
   tree fn, type, lhs;
-  gimple old_stmt, stmt;
+  gimple old_stmt;
+  gimple_call stmt;
 
   old_stmt = gsi_stmt (*gsi);
   lhs = gimple_assign_lhs (old_stmt);
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index a91542d..3347b7b 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -3204,11 +3204,11 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
 	{
 	  fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
 	  src_nr = build_int_cst (integer_type_node, src_r->index);
-	  x = gimple_build_call (fn, 1, src_nr);
+	  gimple_call call = gimple_build_call (fn, 1, src_nr);
 	  var = create_tmp_var (ptr_type_node, NULL);
-	  var = make_ssa_name (var, x);
-	  gimple_call_set_lhs (x, var);
-	  gsi_insert_before (&gsi, x, GSI_SAME_STMT);
+	  var = make_ssa_name (var, call);
+	  gimple_call_set_lhs (call, var);
+	  gsi_insert_before (&gsi, call, GSI_SAME_STMT);
 
 	  fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME);
 	  x = gimple_build_call (fn, 1, var);
@@ -3578,12 +3578,13 @@ lower_eh_dispatch (basic_block src, gimple stmt)
 	else
 	  {
 	    fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
-	    x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
-							 region_nr));
+	    gimple_call call =
+	      gimple_build_call (fn, 1, build_int_cst (integer_type_node,
+						       region_nr));
 	    filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
-	    filter = make_ssa_name (filter, x);
-	    gimple_call_set_lhs (x, filter);
-	    gsi_insert_before (&gsi, x, GSI_SAME_STMT);
+	    filter = make_ssa_name (filter, call);
+	    gimple_call_set_lhs (call, filter);
+	    gsi_insert_before (&gsi, call, GSI_SAME_STMT);
 
 	    /* Turn the default label into a default case.  */
 	    default_label = build_case_label (NULL, NULL, default_label);
@@ -3604,12 +3605,13 @@ lower_eh_dispatch (basic_block src, gimple stmt)
 	edge f_e = FALLTHRU_EDGE (src);
 
 	fn = builtin_decl_implicit (BUILT_IN_EH_FILTER);
-	x = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
+	gimple_call call
+	  = gimple_build_call (fn, 1, build_int_cst (integer_type_node,
 						     region_nr));
 	filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
-	filter = make_ssa_name (filter, x);
-	gimple_call_set_lhs (x, filter);
-	gsi_insert_before (&gsi, x, GSI_SAME_STMT);
+	filter = make_ssa_name (filter, call);
+	gimple_call_set_lhs (call, filter);
+	gsi_insert_before (&gsi, call, GSI_SAME_STMT);
 
 	r->u.allowed.label = NULL;
 	x = gimple_build_cond (EQ_EXPR, filter,
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index b5ca407..7b17a68 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -427,7 +427,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d)
     {
       struct varpool_node *cvar;
       tree cdecl;
-      gimple x;
+      gimple_call x;
 
       cvar = control_vars[index];
       cdecl = cvar->decl;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index a600d3c..83a3e27 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1648,7 +1648,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 	      /* __builtin_va_arg_pack () should be replaced by
 		 all arguments corresponding to ... in the caller.  */
 	      tree p;
-	      gimple new_call;
+	      gimple_call new_call;
 	      vec<tree> argarray;
 	      size_t nargs = gimple_call_num_args (id->gimple_call);
 	      size_t n;
@@ -1725,7 +1725,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 
 	  /* We're duplicating a CALL_EXPR.  Find any corresponding
 	     callgraph edges and update or duplicate them.  */
-	  if (is_gimple_call (stmt))
+	  if (gimple_call call_stmt = dyn_cast<gimple_statement_call> (stmt))
 	    {
 	      struct cgraph_edge *edge;
 	      int flags;
@@ -1739,7 +1739,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 		      int edge_freq = edge->frequency;
 		      int new_freq;
 		      struct cgraph_edge *old_edge = edge;
-		      edge = cgraph_clone_edge (edge, id->dst_node, stmt,
+		      edge = cgraph_clone_edge (edge, id->dst_node, call_stmt,
 					        gimple_uid (stmt),
 					        REG_BR_PROB_BASE, CGRAPH_FREQ_BASE,
 					        true);
@@ -1758,7 +1758,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 
 			  gcc_assert (!edge->indirect_unknown_callee);
 			  cgraph_speculative_call_info (old_edge, direct, indirect, ref);
-			  indirect = cgraph_clone_edge (indirect, id->dst_node, stmt,
+			  indirect = cgraph_clone_edge (indirect, id->dst_node, call_stmt,
 							gimple_uid (stmt),
 							REG_BR_PROB_BASE, CGRAPH_FREQ_BASE,
 							true);
@@ -1797,14 +1797,14 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 
 		case CB_CGE_MOVE_CLONES:
 		  cgraph_set_call_stmt_including_clones (id->dst_node,
-							 orig_stmt, stmt);
+							 orig_stmt, call_stmt);
 		  edge = cgraph_edge (id->dst_node, stmt);
 		  break;
 
 		case CB_CGE_MOVE:
 		  edge = cgraph_edge (id->dst_node, orig_stmt);
 		  if (edge)
-		    cgraph_set_call_stmt (edge, stmt);
+		    cgraph_set_call_stmt (edge, call_stmt);
 		  break;
 
 		default:
@@ -1833,12 +1833,12 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 			      || !id->dst_node->definition);
 		  if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
 		    cgraph_create_edge_including_clones
-		      (id->dst_node, dest, orig_stmt, stmt, bb->count,
+		      (id->dst_node, dest, orig_stmt, call_stmt, bb->count,
 		       compute_call_stmt_bb_frequency (id->dst_node->decl,
 		       				       copy_basic_block),
 		       CIF_ORIGINALLY_INDIRECT_CALL);
 		  else
-		    cgraph_create_edge (id->dst_node, dest, stmt,
+		    cgraph_create_edge (id->dst_node, dest, call_stmt,
 					bb->count,
 					compute_call_stmt_bb_frequency
 					  (id->dst_node->decl,
@@ -4401,7 +4401,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
 		  gsi_prev (&i2);
 		  if (fold_stmt (&gsi))
 		    {
-		      gimple new_stmt;
+		      gimple_call new_stmt;
 		      /* If a builtin at the end of a bb folded into nothing,
 			 the following loop won't work.  */
 		      if (gsi_end_p (gsi))
@@ -4416,7 +4416,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
 			gsi_next (&i2);
 		      while (1)
 			{
-			  new_stmt = gsi_stmt (i2);
+			  new_stmt = as_a<gimple_statement_call> (gsi_stmt (i2));
 			  update_stmt (new_stmt);
 			  cgraph_update_edges_for_call_stmt (old_stmt, old_decl,
 							     new_stmt);
@@ -4451,8 +4451,14 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
 
 		  if (is_gimple_call (old_stmt)
 		      || is_gimple_call (new_stmt))
-		    cgraph_update_edges_for_call_stmt (old_stmt, old_decl,
-						       new_stmt);
+		    {
+		      if (new_stmt)
+			gcc_assert (new_stmt->code == GIMPLE_CALL);
+		      gimple_call new_call_stmt =
+			static_cast<gimple_call> (new_stmt);
+		      cgraph_update_edges_for_call_stmt (old_stmt, old_decl,
+							 new_call_stmt);
+		    }
 
 		  if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
 		    gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index dc63ef6..5f5dcef 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -401,7 +401,7 @@ get_chain_field (struct nesting_info *info)
 
 static tree
 init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
-		        gimple call)
+		        gimple_call call)
 {
   tree t;
 
@@ -1919,7 +1919,7 @@ convert_tramp_reference_op (tree *tp, int *walk_subtrees, void *data)
   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *const info = (struct nesting_info *) wi->info, *i;
   tree t = *tp, decl, target_context, x, builtin;
-  gimple call;
+  gimple_call call;
 
   *walk_subtrees = 0;
   switch (TREE_CODE (t))
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 38da577..35c97b6 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -4476,7 +4476,7 @@ replace_removed_params_ssa_names (gimple stmt,
   if (is_gimple_assign (stmt))
     gimple_assign_set_lhs (stmt, name);
   else if (is_gimple_call (stmt))
-    gimple_call_set_lhs (stmt, name);
+    gimple_call_set_lhs (static_cast<gimple_call> (stmt), name);
   else
     gimple_phi_set_result (stmt, name);
 
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 72e2fb8..3527848 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1212,6 +1212,7 @@ eliminate_unnecessary_stmts (void)
 	    }
 	  else if (is_gimple_call (stmt))
 	    {
+	      gimple_call call_stmt = static_cast <gimple_call> (stmt);
 	      tree name = gimple_call_lhs (stmt);
 
 	      notice_special_calls (stmt);
@@ -1240,7 +1241,7 @@ eliminate_unnecessary_stmts (void)
 		      fprintf (dump_file, "\n");
 		    }
 
-		  gimple_call_set_lhs (stmt, NULL_TREE);
+		  gimple_call_set_lhs (call_stmt, NULL_TREE);
 		  maybe_clean_or_replace_eh_stmt (stmt, stmt);
 		  update_stmt (stmt);
 		  release_ssa_name (name);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 93b8970..c0415d4 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1651,8 +1651,9 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
 	    {
 	      /* If STMT1 is a mem{,p}cpy call, adjust it and remove
 		 memset call.  */
+	      gimple_call call_stmt1 = static_cast <gimple_call> (stmt1);
 	      if (lhs1 && DECL_FUNCTION_CODE (callee1) == BUILT_IN_MEMPCPY)
-		gimple_call_set_lhs (stmt1, NULL_TREE);
+		gimple_call_set_lhs (call_stmt1, NULL_TREE);
 	      gimple_call_set_arg (stmt1, 1, new_str_cst);
 	      gimple_call_set_arg (stmt1, 2,
 				   build_int_cst (TREE_TYPE (len1), src_len));
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 9a29411..6253c3d 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -724,6 +724,7 @@ execute_cse_sincos_1 (tree name)
   imm_use_iterator use_iter;
   tree fndecl, res, type;
   gimple def_stmt, use_stmt, stmt;
+  gimple_call call_stmt;
   int seen_cos = 0, seen_sin = 0, seen_cexpi = 0;
   vec<gimple> stmts = vNULL;
   basic_block top_bb = NULL;
@@ -768,9 +769,9 @@ execute_cse_sincos_1 (tree name)
   fndecl = mathfn_built_in (type, BUILT_IN_CEXPI);
   if (!fndecl)
     return false;
-  stmt = gimple_build_call (fndecl, 1, name);
-  res = make_temp_ssa_name (TREE_TYPE (TREE_TYPE (fndecl)), stmt, "sincostmp");
-  gimple_call_set_lhs (stmt, res);
+  call_stmt = gimple_build_call (fndecl, 1, name);
+  res = make_temp_ssa_name (TREE_TYPE (TREE_TYPE (fndecl)), call_stmt, "sincostmp");
+  gimple_call_set_lhs (call_stmt, res);
 
   def_stmt = SSA_NAME_DEF_STMT (name);
   if (!SSA_NAME_IS_DEFAULT_DEF (name)
@@ -778,12 +779,12 @@ execute_cse_sincos_1 (tree name)
       && gimple_bb (def_stmt) == top_bb)
     {
       gsi = gsi_for_stmt (def_stmt);
-      gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
+      gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
     }
   else
     {
       gsi = gsi_after_labels (top_bb);
-      gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+      gsi_insert_before (&gsi, call_stmt, GSI_SAME_STMT);
     }
   sincos_stats.inserted++;
 
@@ -1944,7 +1945,7 @@ execute_optimize_bswap (void)
 	  tree bswap_tmp;
 	  tree fndecl = NULL_TREE;
 	  int type_size;
-	  gimple call;
+	  gimple_call call;
 
 	  if (!is_gimple_assign (stmt)
 	      || gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR)
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index d5bcc9c..4565de0 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -697,7 +697,7 @@ move_ssa_defining_stmt_for_defs (gimple new_stmt, gimple old_stmt)
    A GIMPLE_CALL STMT is being replaced with GIMPLE_CALL NEW_STMT.  */
 
 static void
-finish_update_gimple_call (gimple_stmt_iterator *si_p, gimple new_stmt,
+finish_update_gimple_call (gimple_stmt_iterator *si_p, gimple_call new_stmt,
 			   gimple stmt)
 {
   gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
@@ -718,7 +718,8 @@ bool
 update_gimple_call (gimple_stmt_iterator *si_p, tree fn, int nargs, ...)
 {
   va_list ap;
-  gimple new_stmt, stmt = gsi_stmt (*si_p);
+  gimple_call new_stmt;
+  gimple stmt = gsi_stmt (*si_p);
 
   gcc_assert (is_gimple_call (stmt));
   va_start (ap, nargs);
@@ -752,7 +753,7 @@ update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
       unsigned i;
       unsigned nargs = call_expr_nargs (expr);
       vec<tree> args = vNULL;
-      gimple new_stmt;
+      gimple_call new_stmt;
 
       if (nargs > 0)
         {
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 39982f1..982c6d2 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -3979,7 +3979,8 @@ attempt_builtin_powi (gimple stmt, vec<operand_entry_t> *ops)
   tree type = TREE_TYPE (gimple_get_lhs (stmt));
   tree powi_fndecl = mathfn_built_in (type, BUILT_IN_POWI);
   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
-  gimple mul_stmt, pow_stmt;
+  gimple mul_stmt;
+  gimple_call pow_stmt;
 
   /* Nothing to do if BUILT_IN_POWI doesn't exist for this type and
      target.  */
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index ea73179..ad18fc1 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -412,12 +412,15 @@ get_string_length (strinfo si)
 
   if (si->stmt)
     {
-      gimple stmt = si->stmt, lenstmt;
+      gimple stmt = si->stmt;
+      gimple_call lenstmt_call;
+      gimple lenstmt_assign;
       tree callee, lhs, fn, tem;
       location_t loc;
       gimple_stmt_iterator gsi;
 
       gcc_assert (is_gimple_call (stmt));
+      gimple_call call_stmt = static_cast<gimple_call> (stmt);
       callee = gimple_call_fndecl (stmt);
       gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
       lhs = gimple_call_lhs (stmt);
@@ -436,11 +439,11 @@ get_string_length (strinfo si)
 	  fn = builtin_decl_implicit (BUILT_IN_STRLEN);
 	  gcc_assert (lhs == NULL_TREE);
 	  tem = unshare_expr (gimple_call_arg (stmt, 0));
-	  lenstmt = gimple_build_call (fn, 1, tem);
-	  lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt);
-	  gimple_call_set_lhs (lenstmt, lhs);
-	  gimple_set_vuse (lenstmt, gimple_vuse (stmt));
-	  gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
+	  lenstmt_call = gimple_build_call (fn, 1, tem);
+	  lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt_call);
+	  gimple_call_set_lhs (lenstmt_call, lhs);
+	  gimple_set_vuse (lenstmt_call, gimple_vuse (stmt));
+	  gsi_insert_before (&gsi, lenstmt_call, GSI_SAME_STMT);
 	  tem = gimple_call_arg (stmt, 0);
           if (!ptrofftype_p (TREE_TYPE (lhs)))
             {
@@ -448,13 +451,13 @@ get_string_length (strinfo si)
               lhs = force_gimple_operand_gsi (&gsi, lhs, true, NULL_TREE,
                                               true, GSI_SAME_STMT);
             }
-	  lenstmt
+	  lenstmt_assign
 	    = gimple_build_assign_with_ops
 	        (POINTER_PLUS_EXPR,
 		 make_ssa_name (TREE_TYPE (gimple_call_arg (stmt, 0)), NULL),
 		 tem, lhs);
-	  gsi_insert_before (&gsi, lenstmt, GSI_SAME_STMT);
-	  gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt));
+	  gsi_insert_before (&gsi, lenstmt_assign, GSI_SAME_STMT);
+	  gimple_call_set_arg (stmt, 0, gimple_assign_lhs (lenstmt_assign));
 	  lhs = NULL_TREE;
 	  /* FALLTHRU */
 	case BUILT_IN_STRCPY:
@@ -471,7 +474,7 @@ get_string_length (strinfo si)
 	    }
 	  gimple_call_set_fndecl (stmt, fn);
 	  lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
-	  gimple_call_set_lhs (stmt, lhs);
+	  gimple_call_set_lhs (call_stmt, lhs);
 	  update_stmt (stmt);
 	  if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	    {
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index fb3fe94..2ddaebe 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -4463,24 +4463,24 @@ vect_setup_realignment (gimple stmt, gimple_stmt_iterator *gsi,
 	}
 
       builtin_decl = targetm.vectorize.builtin_mask_for_load ();
-      new_stmt = gimple_build_call (builtin_decl, 1, init_addr);
+      gimple_call call_stmt = gimple_build_call (builtin_decl, 1, init_addr);
       vec_dest =
 	vect_create_destination_var (scalar_dest,
-				     gimple_call_return_type (new_stmt));
-      new_temp = make_ssa_name (vec_dest, new_stmt);
-      gimple_call_set_lhs (new_stmt, new_temp);
+				     gimple_call_return_type (call_stmt));
+      new_temp = make_ssa_name (vec_dest, call_stmt);
+      gimple_call_set_lhs (call_stmt, new_temp);
 
       if (compute_in_loop)
-	gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
+	gsi_insert_before (gsi, call_stmt, GSI_SAME_STMT);
       else
 	{
 	  /* Generate the misalignment computation outside LOOP.  */
 	  pe = loop_preheader_edge (loop);
-	  new_bb = gsi_insert_on_edge_immediate (pe, new_stmt);
+	  new_bb = gsi_insert_on_edge_immediate (pe, call_stmt);
 	  gcc_assert (!new_bb);
 	}
 
-      *realignment_token = gimple_call_lhs (new_stmt);
+      *realignment_token = gimple_call_lhs (call_stmt);
 
       /* The result of the CALL_EXPR to this builtin is determined from
          the value of the parameter and no global variables are touched
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 8d9aaa2..2dc918f 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -801,7 +801,7 @@ vect_recog_pow_pattern (vec<gimple> *stmts, tree *type_in,
       *type_in = get_vectype_for_scalar_type (TREE_TYPE (base));
       if (*type_in)
 	{
-	  gimple stmt = gimple_build_call (newfn, 1, base);
+	  gimple_call stmt = gimple_build_call (newfn, 1, base);
 	  if (vectorizable_function (stmt, *type_in, *type_in)
 	      != NULL_TREE)
 	    {
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 9516e76..906a44d 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1940,9 +1940,10 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 		      vec<tree> vec_oprndsk = vec_defs[k];
 		      vargs[k] = vec_oprndsk[i];
 		    }
-		  new_stmt = gimple_build_call_vec (fndecl, vargs);
+		  gimple_call call = gimple_build_call_vec (fndecl, vargs);
+		  new_stmt = call;
 		  new_temp = make_ssa_name (vec_dest, new_stmt);
-		  gimple_call_set_lhs (new_stmt, new_temp);
+		  gimple_call_set_lhs (call, new_temp);
 		  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 		  SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
 		}
@@ -1992,9 +1993,10 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	    }
 	  else
 	    {
-	      new_stmt = gimple_build_call_vec (fndecl, vargs);
+	      gimple_call call = gimple_build_call_vec (fndecl, vargs);
+	      new_stmt = call;
 	      new_temp = make_ssa_name (vec_dest, new_stmt);
-	      gimple_call_set_lhs (new_stmt, new_temp);
+	      gimple_call_set_lhs (call, new_temp);
 	    }
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
@@ -2039,9 +2041,10 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 		      vargs.quick_push (vec_oprndsk[i]);
 		      vargs.quick_push (vec_oprndsk[i + 1]);
 		    }
-		  new_stmt = gimple_build_call_vec (fndecl, vargs);
+		  gimple_call call = gimple_build_call_vec (fndecl, vargs);
+		  new_stmt = call;
 		  new_temp = make_ssa_name (vec_dest, new_stmt);
-		  gimple_call_set_lhs (new_stmt, new_temp);
+		  gimple_call_set_lhs (call, new_temp);
 		  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 		  SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
 		}
@@ -2078,9 +2081,10 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	      vargs.quick_push (vec_oprnd1);
 	    }
 
-	  new_stmt = gimple_build_call_vec (fndecl, vargs);
+	  gimple_call call = gimple_build_call_vec (fndecl, vargs);
+	  new_stmt = call;
 	  new_temp = make_ssa_name (vec_dest, new_stmt);
-	  gimple_call_set_lhs (new_stmt, new_temp);
+	  gimple_call_set_lhs (call, new_temp);
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
 	  if (j == 0)
@@ -2152,13 +2156,15 @@ vect_gen_widened_results_half (enum tree_code code,
   /* Generate half of the widened result:  */
   if (code == CALL_EXPR)
     {
+      gimple_call call;
       /* Target specific support  */
       if (op_type == binary_op)
-	new_stmt = gimple_build_call (decl, 2, vec_oprnd0, vec_oprnd1);
+	call = gimple_build_call (decl, 2, vec_oprnd0, vec_oprnd1);
       else
-	new_stmt = gimple_build_call (decl, 1, vec_oprnd0);
+	call = gimple_build_call (decl, 1, vec_oprnd0);
+      new_stmt = call;
       new_temp = make_ssa_name (vec_dest, new_stmt);
-      gimple_call_set_lhs (new_stmt, new_temp);
+      gimple_call_set_lhs (call, new_temp);
     }
   else
     {
@@ -2710,9 +2716,10 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
 	      /* Arguments are ready, create the new vector stmt.  */
 	      if (code1 == CALL_EXPR)
 		{
-		  new_stmt = gimple_build_call (decl1, 1, vop0);
+		  gimple_call call = gimple_build_call (decl1, 1, vop0);
+		  new_stmt = call;
 		  new_temp = make_ssa_name (vec_dest, new_stmt);
-		  gimple_call_set_lhs (new_stmt, new_temp);
+		  gimple_call_set_lhs (call, new_temp);
 		}
 	      else
 		{
@@ -2821,9 +2828,10 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
 		{
 		  if (codecvt1 == CALL_EXPR)
 		    {
-		      new_stmt = gimple_build_call (decl1, 1, vop0);
+		      gimple_call call = gimple_build_call (decl1, 1, vop0);
+		      new_stmt = call;
 		      new_temp = make_ssa_name (vec_dest, new_stmt);
-		      gimple_call_set_lhs (new_stmt, new_temp);
+		      gimple_call_set_lhs (call, new_temp);
 		    }
 		  else
 		    {
@@ -2879,9 +2887,10 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
 	      {
 		if (codecvt1 == CALL_EXPR)
 		  {
-		    new_stmt = gimple_build_call (decl1, 1, vop0);
+		    gimple_call call = gimple_build_call (decl1, 1, vop0);
+		    new_stmt = call;
 		    new_temp = make_ssa_name (vec_dest, new_stmt);
-		    gimple_call_set_lhs (new_stmt, new_temp);
+		    gimple_call_set_lhs (call, new_temp);
 		  }
 		else
 		  {
@@ -4240,8 +4249,9 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  /* Emit:
 	       MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY).  */
 	  data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
-	  new_stmt = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array);
-	  gimple_call_set_lhs (new_stmt, data_ref);
+	  gimple_call call = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array);
+	  new_stmt = call;
+	  gimple_call_set_lhs (call, data_ref);
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 	}
       else
@@ -4732,8 +4742,9 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	      op = var;
 	    }
 
-	  new_stmt
+	  gimple_call call
 	    = gimple_build_call (gather_decl, 5, mask, ptr, op, mask, scale);
+	  new_stmt = call;
 
 	  if (!useless_type_conversion_p (vectype, rettype))
 	    {
@@ -4741,7 +4752,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 			  == TYPE_VECTOR_SUBPARTS (rettype));
 	      var = vect_get_new_vect_var (rettype, vect_simple_var, NULL);
 	      op = make_ssa_name (var, new_stmt);
-	      gimple_call_set_lhs (new_stmt, op);
+	      gimple_call_set_lhs (call, op);
 	      vect_finish_stmt_generation (stmt, new_stmt, gsi);
 	      var = make_ssa_name (vec_dest, NULL);
 	      op = build1 (VIEW_CONVERT_EXPR, vectype, op);
@@ -4752,7 +4763,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  else
 	    {
 	      var = make_ssa_name (vec_dest, new_stmt);
-	      gimple_call_set_lhs (new_stmt, var);
+	      gimple_call_set_lhs (call, var);
 	    }
 
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
@@ -5111,8 +5122,9 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  /* Emit:
 	       VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]).  */
 	  data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
-	  new_stmt = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref);
-	  gimple_call_set_lhs (new_stmt, vec_array);
+	  gimple_call call = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref);
+	  new_stmt = call;
+	  gimple_call_set_lhs (call, vec_array);
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
 	  /* Extract each vector into an SSA_NAME.  */
diff --git a/gcc/tsan.c b/gcc/tsan.c
index bceb597..de95625 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -426,7 +426,8 @@ static const struct tsan_map_atomic
 static void
 instrument_builtin_call (gimple_stmt_iterator *gsi)
 {
-  gimple stmt = gsi_stmt (*gsi), g;
+  gimple stmt = gsi_stmt (*gsi);
+  gimple g;
   tree callee = gimple_call_fndecl (stmt), last_arg, args[6], t, lhs;
   enum built_in_function fcode = DECL_FUNCTION_CODE (callee);
   unsigned int i, num = gimple_call_num_args (stmt), j;
@@ -487,7 +488,8 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
 		    gsi_insert_after (gsi, g, GSI_NEW_STMT);
 		    args[1] = var;
 		  }
-		gimple_call_set_lhs (stmt,
+		gimple_call call_stmt = as_a<gimple_statement_call> (stmt);
+		gimple_call_set_lhs (call_stmt,
 				     make_ssa_name (TREE_TYPE (lhs), NULL));
 		/* BIT_NOT_EXPR stands for NAND.  */
 		if (tsan_atomic_table[i].code == BIT_NOT_EXPR)
@@ -569,7 +571,8 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
 		g = gimple_build_assign_with_ops (COND_EXPR, lhs, cond,
 						  args[1],
 						  gimple_assign_lhs (g));
-		gimple_call_set_lhs (stmt, t);
+		gimple_call call_stmt = as_a<gimple_statement_call> (stmt);
+		gimple_call_set_lhs (call_stmt, t);
 		update_stmt (stmt);
 		gsi_insert_after (gsi, g, GSI_NEW_STMT);
 	      }
@@ -649,7 +652,7 @@ instrument_func_entry (void)
   basic_block succ_bb;
   gimple_stmt_iterator gsi;
   tree ret_addr, builtin_decl;
-  gimple g;
+  gimple_call g;
 
   succ_bb = single_succ (ENTRY_BLOCK_PTR);
   gsi = gsi_after_labels (succ_bb);
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 7be54ce..7ca9f4d 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -1292,11 +1292,12 @@ check_ic_target (gimple call_stmt, struct cgraph_node *target)
     old call
  */
 
-gimple
-gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
+gimple_call
+gimple_ic (gimple_call icall_stmt, struct cgraph_node *direct_call,
 	   int prob, gcov_type count, gcov_type all)
 {
-  gimple dcall_stmt, load_stmt, cond_stmt;
+  gimple_call dcall_stmt;
+  gimple load_stmt, cond_stmt;
   tree tmp0, tmp1, tmp;
   basic_block cond_bb, dcall_bb, icall_bb, join_bb = NULL;
   tree optype = build_pointer_type (void_type_node);
@@ -1327,7 +1328,7 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
   gimple_set_vdef (icall_stmt, NULL_TREE);
   gimple_set_vuse (icall_stmt, NULL_TREE);
   update_stmt (icall_stmt);
-  dcall_stmt = gimple_copy (icall_stmt);
+  dcall_stmt = static_cast<gimple_call> (gimple_copy (icall_stmt));
   gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
   dflags = flags_from_decl_or_type (direct_call->decl);
   if ((dflags & ECF_NORETURN) != 0)
@@ -1559,10 +1560,11 @@ interesting_stringop_to_profile_p (tree fndecl, gimple call, int *size_arg)
    assuming we'll propagate a true constant into ICALL_SIZE later.  */
 
 static void
-gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob,
+gimple_stringop_fixed_value (gimple_call vcall_stmt, tree icall_size, int prob,
 			     gcov_type count, gcov_type all)
 {
-  gimple tmp_stmt, cond_stmt, icall_stmt;
+  gimple tmp_stmt, cond_stmt;
+  gimple_call icall_stmt;
   tree tmp0, tmp1, vcall_size, optype;
   basic_block cond_bb, icall_bb, vcall_bb, join_bb;
   edge e_ci, e_cv, e_iv, e_ij, e_vj;
@@ -1594,7 +1596,7 @@ gimple_stringop_fixed_value (gimple vcall_stmt, tree icall_size, int prob,
   gimple_set_vdef (vcall_stmt, NULL);
   gimple_set_vuse (vcall_stmt, NULL);
   update_stmt (vcall_stmt);
-  icall_stmt = gimple_copy (vcall_stmt);
+  icall_stmt = static_cast<gimple_call> (gimple_copy (vcall_stmt));
   gimple_call_set_arg (icall_stmt, size_arg, icall_size);
   gsi_insert_before (&gsi, icall_stmt, GSI_SAME_STMT);
 
@@ -1654,6 +1656,7 @@ static bool
 gimple_stringops_transform (gimple_stmt_iterator *gsi)
 {
   gimple stmt = gsi_stmt (*gsi);
+  gimple_call call_stmt;
   tree fndecl;
   tree blck_size;
   enum built_in_function fcode;
@@ -1667,6 +1670,7 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi)
 
   if (gimple_code (stmt) != GIMPLE_CALL)
     return false;
+  call_stmt = static_cast<gimple_call> (stmt);
   fndecl = gimple_call_fndecl (stmt);
   if (!fndecl)
     return false;
@@ -1731,7 +1735,7 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi)
 	       (int)val);
       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
     }
-  gimple_stringop_fixed_value (stmt, tree_val, prob, count, all);
+  gimple_stringop_fixed_value (call_stmt, tree_val, prob, count, all);
 
   return true;
 }
diff --git a/gcc/value-prof.h b/gcc/value-prof.h
index 57f249d..0dd9033 100644
--- a/gcc/value-prof.h
+++ b/gcc/value-prof.h
@@ -86,7 +86,8 @@ void gimple_move_stmt_histograms (struct function *, gimple, gimple);
 void verify_histograms (void);
 void free_histograms (void);
 void stringop_block_profile (gimple, unsigned int *, HOST_WIDE_INT *);
-gimple gimple_ic (gimple, struct cgraph_node *, int, gcov_type, gcov_type);
+gimple_call
+gimple_ic (gimple_call, struct cgraph_node *, int, gcov_type, gcov_type);
 
 
 /* In tree-profile.c.  */
diff --git a/gcc/vtable-verify.c b/gcc/vtable-verify.c
index fb26978..a276a8d 100644
--- a/gcc/vtable-verify.c
+++ b/gcc/vtable-verify.c
@@ -593,7 +593,7 @@ verify_bb_vtables (basic_block bb)
           tree vtbl_var_decl = NULL_TREE;
           struct vtbl_map_node *vtable_map_node;
           tree vtbl_decl = NULL_TREE;
-          gimple call_stmt;
+          gimple_call call_stmt;
           const char *vtable_name = "<unknown>";
           tree tmp0;
           bool found;

[-- Attachment #3: convert-gimple_call_set_lhs-to-method.patch --]
[-- Type: text/x-patch, Size: 32871 bytes --]

commit 9a89f418eceb2d11d6eff60cb8c76c11f7cdf77c
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Mon Nov 4 16:01:42 2013 -0500

    FIXME: conversion of gimple_call_set_lhs to a method

diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index a9ab226..a12e581 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1587,7 +1587,7 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks)
       gimple_call_set_from_thunk (call, true);
       if (restmp)
 	{
-          gimple_call_set_lhs (call, restmp);
+          call->set_lhs (restmp);
 	  gcc_assert (useless_type_conversion_p (TREE_TYPE (restmp),
 						 TREE_TYPE (TREE_TYPE (alias))));
 	}
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b76479c..cd44f3d 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -29459,7 +29459,7 @@ add_condition_to_bb (tree function_decl, tree version_decl,
       predicate_decl = TREE_PURPOSE (predicate_chain);
       predicate_arg = TREE_VALUE (predicate_chain);
       call_cond_stmt = gimple_build_call (predicate_decl, 1, predicate_arg);
-      gimple_call_set_lhs (call_cond_stmt, cond_var);
+      call_cond_stmt->set_lhs (cond_var);
 
       gimple_set_block (call_cond_stmt, DECL_INITIAL (function_decl));
       gimple_set_bb (call_cond_stmt, new_bb);
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index b24961b..f7c399e 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -158,7 +158,7 @@ lower_function_body (void)
       arg = build_addr (disp_label, current_function_decl);
       t = builtin_decl_implicit (BUILT_IN_SETJMP_DISPATCHER);
       call = gimple_build_call (t, 1, arg);
-      gimple_call_set_lhs (call, disp_var);
+      call->set_lhs (disp_var);
       gsi_insert_after (&i, call, GSI_CONTINUE_LINKING);
 
       /* Build 'goto DISP_VAR;' and insert.  */
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f31c935..a128582 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2252,7 +2252,7 @@ gimple_set_lhs (gimple stmt, tree lhs)
   if (code == GIMPLE_ASSIGN)
     gimple_assign_set_lhs (stmt, lhs);
   else if (code == GIMPLE_CALL)
-    gimple_call_set_lhs (static_cast<gimple_call> (stmt), lhs);
+    ((gimple_call)stmt)->set_lhs (lhs);
   else
     gcc_unreachable ();
 }
@@ -3083,7 +3083,7 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
     new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
   vargs.release ();
   if (gimple_call_lhs (stmt))
-    gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
+    new_stmt->set_lhs (gimple_call_lhs (stmt));
 
   gimple_set_vuse (new_stmt, gimple_vuse (stmt));
   gimple_set_vdef (new_stmt, gimple_vdef (stmt));
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 1180d3e..c9df1d9 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -292,6 +292,13 @@ struct GTY((tag("GSS_WITH_MEM_OPS")))
 struct GTY((tag("GSS_CALL")))
   gimple_statement_call : public gimple_statement_with_memory_ops_base
 {
+public:
+
+  /* Set LHS to be the LHS operand of this call statement.  */
+  inline void set_lhs (tree lhs);
+
+public:
+
   /* [ WORD 1-9 ] : base class */
 
   /* [ WORD 10-13 ]  */
@@ -2550,12 +2557,12 @@ gimple_call_lhs_ptr (const_gimple gs)
 
 /* Set LHS to be the LHS operand of call statement GS.  */
 
-static inline void
-gimple_call_set_lhs (gimple_call gs, tree lhs)
+inline void
+gimple_statement_call::set_lhs (tree lhs)
 {
-  gimple_set_op (gs, 0, lhs);
+  gimple_set_op (this, 0, lhs);
   if (lhs && TREE_CODE (lhs) == SSA_NAME)
-    SSA_NAME_DEF_STMT (lhs) = gs;
+    SSA_NAME_DEF_STMT (lhs) = this;
 }
 
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index e2c81b9..4cfc2e9 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1166,7 +1166,7 @@ build_stack_save_restore (gimple_call *save, gimple_call *restore)
 
   *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
   tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
-  gimple_call_set_lhs (*save, tmp_var);
+  (*save)->set_lhs (tmp_var);
 
   *restore
     = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
@@ -3464,7 +3464,7 @@ gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
     {
       /* tmp = memcpy() */
       t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
-      gimple_call_set_lhs (gs, t);
+      gs->set_lhs (t);
       gimplify_seq_add_stmt (seq_p, gs);
 
       *expr_p = build_simple_mem_ref (t);
@@ -3511,7 +3511,7 @@ gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
     {
       /* tmp = memset() */
       t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
-      gimple_call_set_lhs (gs, t);
+      gs->set_lhs (t);
       gimplify_seq_add_stmt (seq_p, gs);
 
       *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
@@ -4881,7 +4881,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
       notice_special_calls (assign);
       if (!gimple_call_noreturn_p (assign))
-	gimple_call_set_lhs (call, *to_p);
+	call->set_lhs (*to_p);
     }
   else
     {
@@ -7792,7 +7792,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	    gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
 	    gimple_call call = gimple_build_call_internal (IFN_ANNOTATE, 2,
 							   cond, id);
-	    gimple_call_set_lhs (call, tmp);
+	    call->set_lhs (tmp);
 	    gimplify_seq_add_stmt (pre_p, call);
 	    *expr_p = tmp;
 	    ret = GS_ALL_DONE;
@@ -8995,7 +8995,7 @@ gimplify_function_tree (tree fndecl)
       x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
-      gimple_call_set_lhs (call, tmp_var);
+      call->set_lhs (tmp_var);
       gimplify_seq_add_stmt (&cleanup, call);
       x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_EXIT);
       call = gimple_build_call (x, 2,
@@ -9007,7 +9007,7 @@ gimplify_function_tree (tree fndecl)
       x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
       call = gimple_build_call (x, 1, integer_zero_node);
       tmp_var = create_tmp_var (ptr_type_node, "return_addr");
-      gimple_call_set_lhs (call, tmp_var);
+      call->set_lhs (tmp_var);
       gimplify_seq_add_stmt (&body, call);
       x = builtin_decl_implicit (BUILT_IN_PROFILE_FUNC_ENTER);
       call = gimple_build_call (x, 2,
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 642153d..5e8b068 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -3713,7 +3713,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
   new_stmt = gimple_build_call_vec (callee_decl, vargs);
   vargs.release ();
   if (gimple_call_lhs (stmt))
-    gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
+    new_stmt->set_lhs (gimple_call_lhs (stmt));
 
   gimple_set_block (new_stmt, gimple_block (stmt));
   if (gimple_has_location (stmt))
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index 915533c..b7f8381 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1414,7 +1414,7 @@ split_function (struct split_point *split_point)
 		}
 	      if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
 		{
-		  gimple_call_set_lhs (call, build_simple_mem_ref (retval));
+		  call->set_lhs (build_simple_mem_ref (retval));
 		  gsi_insert_after (&gsi, call, GSI_NEW_STMT);
 		}
 	      else
@@ -1432,7 +1432,7 @@ split_function (struct split_point *split_point)
 		      gsi_insert_after (&gsi, cpy, GSI_NEW_STMT);
 		      retval = tem;
 		    }
-		  gimple_call_set_lhs (call, retval);
+		  call->set_lhs (retval);
 		  update_stmt (call);
 		}
 	    }
@@ -1468,9 +1468,9 @@ split_function (struct split_point *split_point)
 		    retval = make_ssa_name (retval, call);
 		}
 	      if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
-	        gimple_call_set_lhs (call, build_simple_mem_ref (retval));
+	        call->set_lhs (build_simple_mem_ref (retval));
 	      else
-	        gimple_call_set_lhs (call, retval);
+	        call->set_lhs (retval);
 	    }
           gsi_insert_after (&gsi, call, GSI_NEW_STMT);
 	  ret = gimple_build_return (retval);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index dcececc..3b7882d 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2672,7 +2672,7 @@ build_omp_barrier (tree lhs)
 					   : BUILT_IN_GOMP_BARRIER);
   gimple_call g = gimple_build_call (fndecl, 0);
   if (lhs)
-    gimple_call_set_lhs (g, lhs);
+    g->set_lhs (lhs);
   return g;
 }
 
@@ -3113,7 +3113,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 		  stmt = gimple_build_call (atmp, 1, x);
 		  tmp = create_tmp_var_raw (ptr_type_node, NULL);
 		  gimple_add_tmp_var (tmp);
-		  gimple_call_set_lhs (stmt, tmp);
+		  stmt->set_lhs (tmp);
 
 		  gimple_seq_add_stmt (ilist, stmt);
 
@@ -3521,7 +3521,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
       TREE_NO_WARNING (uid) = 1;
       gimple_call call
 	= gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
-      gimple_call_set_lhs (call, lane);
+      call->set_lhs (lane);
       gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
       gsi_insert_before_without_update (&gsi, call, GSI_SAME_STMT);
       c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
@@ -3538,7 +3538,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 	  {
 	    tree vf = create_tmp_var (unsigned_type_node, NULL);
 	    call = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
-	    gimple_call_set_lhs (call, vf);
+	    call->set_lhs (vf);
 	    gimple_seq *seq = i == 0 ? ilist : dlist;
 	    gimple_seq_add_stmt (seq, call);
 	    tree t = build_int_cst (unsigned_type_node, 0);
@@ -3698,7 +3698,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
 			= gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
 						      2, simduid,
 						      TREE_OPERAND (val, 1));
-		      gimple_call_set_lhs (g, lastlane);
+		      g->set_lhs (lastlane);
 		      gimple_seq_add_stmt (stmt_list, g);
 		    }
 		  new_var = build4 (ARRAY_REF, TREE_TYPE (val),
@@ -5547,7 +5547,7 @@ expand_omp_for_generic (struct omp_region *region,
     t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
   gimple_call call = gimple_build_call (t, 0);
   if (gimple_omp_return_lhs (gsi_stmt (gsi)))
-    gimple_call_set_lhs (call, gimple_omp_return_lhs (gsi_stmt (gsi)));
+    call->set_lhs (gimple_omp_return_lhs (gsi_stmt (gsi)));
   gsi_insert_after (&gsi, call, GSI_SAME_STMT);
   gsi_remove (&gsi, true);
 
@@ -6939,7 +6939,7 @@ expand_omp_sections (struct omp_region *region)
       u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
       call = gimple_build_call (u, 0);
     }
-  gimple_call_set_lhs (call, vin);
+  call->set_lhs (vin);
   gsi_insert_after (&si, call, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
@@ -7029,7 +7029,7 @@ expand_omp_sections (struct omp_region *region)
 
       bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
       call = gimple_build_call (bfn_decl, 0);
-      gimple_call_set_lhs (call, vnext);
+      call->set_lhs (vnext);
       gsi_insert_after (&si, call, GSI_SAME_STMT);
       gsi_remove (&si, true);
 
@@ -7046,7 +7046,7 @@ expand_omp_sections (struct omp_region *region)
     t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
   call = gimple_build_call (t, 0);
   if (gimple_omp_return_lhs (gsi_stmt (si)))
-    gimple_call_set_lhs (call, gimple_omp_return_lhs (gsi_stmt (si)));
+    call->set_lhs (gimple_omp_return_lhs (gsi_stmt (si)));
   gsi_insert_after (&si, call, GSI_SAME_STMT);
   gsi_remove (&si, true);
 
@@ -8422,7 +8422,7 @@ lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
   decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
   lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
   call = gimple_build_call (decl, 0);
-  gimple_call_set_lhs (call, lhs);
+  call->set_lhs (lhs);
   gimple_seq_add_stmt (pre_p, call);
 
   cond = gimple_build_cond (EQ_EXPR, lhs,
@@ -10010,7 +10010,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		gimple_call_set_fndecl (stmt, fndecl);
 		gimple_call_set_fntype (stmt, TREE_TYPE (fndecl));
 	      }
-	    gimple_call_set_lhs (call, lhs);
+	    call->set_lhs (lhs);
 	    tree fallthru_label;
 	    fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
 	    gimple g;
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 0358b26..b9e1be6 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -1618,7 +1618,7 @@ lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi)
 	gimple_build_call (builtin_decl_explicit (BUILT_IN_EH_POINTER),
 			   1, integer_zero_node);
       ptr = create_tmp_var (ptr_type_node, NULL);
-      gimple_call_set_lhs (call, ptr);
+      call->set_lhs (ptr);
       gimple_seq_add_stmt (&e_seq, call);
 
       g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_COMMIT_EH),
@@ -2115,7 +2115,7 @@ build_tm_load (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
   t = TREE_TYPE (TREE_TYPE (decl));
   if (useless_type_conversion_p (type, t))
     {
-      gimple_call_set_lhs (gcall, lhs);
+      gcall->set_lhs (lhs);
       gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
     }
   else
@@ -2124,7 +2124,7 @@ build_tm_load (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
       tree temp;
 
       temp = create_tmp_reg (t, NULL);
-      gimple_call_set_lhs (gcall, temp);
+      gcall->set_lhs (temp);
       gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
 
       t = fold_build1 (VIEW_CONVERT_EXPR, type, temp);
@@ -2414,7 +2414,7 @@ expand_call_tm (struct tm_region *region,
 	      }
 	}
 
-      gimple_call_set_lhs (call_stmt, tmp);
+      call_stmt->set_lhs (tmp);
       update_stmt (stmt);
       stmt = gimple_build_assign (lhs, tmp);
       gimple_set_location (stmt, loc);
@@ -2701,7 +2701,7 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
       region->original_transaction_was_outer = true;
     tree t = build_int_cst (tm_state_type, flags);
     gimple_call call = gimple_build_call (tm_start, 1, t);
-    gimple_call_set_lhs (call, tm_state);
+    call->set_lhs (tm_state);
     gimple_set_location (call, gimple_location (region->transaction_stmt));
 
     // Replace the GIMPLE_TRANSACTION with the call to BUILT_IN_TM_START.
@@ -4993,7 +4993,7 @@ ipa_tm_insert_gettmclone_call (struct cgraph_node *node,
 
   g = gimple_build_call (gettm_fn, 1, old_fn);
   ret = make_ssa_name (ret, g);
-  gimple_call_set_lhs (g, ret);
+  g->set_lhs (ret);
 
   gsi_insert_before (gsi, g, GSI_SAME_STMT);
 
@@ -5029,7 +5029,7 @@ ipa_tm_insert_gettmclone_call (struct cgraph_node *node,
       tree temp;
 
       temp = create_tmp_reg (rettype, 0);
-      gimple_call_set_lhs (stmt, temp);
+      stmt->set_lhs (temp);
 
       g2 = gimple_build_assign (lhs,
 				fold_build1 (VIEW_CONVERT_EXPR,
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index 3cd625c..db43ea8 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -517,7 +517,7 @@ fixup_noreturn_call (gimple_call stmt)
   if (gimple_call_lhs (stmt))
     {
       tree op = gimple_call_lhs (stmt);
-      gimple_call_set_lhs (stmt, NULL_TREE);
+      stmt->set_lhs (NULL_TREE);
 
       /* We need to remove SSA name to avoid checking errors.
 	 All uses are dominated by the noreturn and thus will
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index aee1e26..325554f 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -957,7 +957,7 @@ expand_complex_libcall (gimple_stmt_iterator *gsi, tree ar, tree ai,
   fn = builtin_decl_explicit (bcode);
 
   stmt = gimple_build_call (fn, 4, ar, ai, br, bi);
-  gimple_call_set_lhs (stmt, lhs);
+  stmt->set_lhs (lhs);
   update_stmt (stmt);
   gsi_replace (gsi, stmt, false);
 
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 3347b7b..c83229f 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -3207,7 +3207,7 @@ lower_resx (basic_block bb, gimple stmt, struct pointer_map_t *mnt_map)
 	  gimple_call call = gimple_build_call (fn, 1, src_nr);
 	  var = create_tmp_var (ptr_type_node, NULL);
 	  var = make_ssa_name (var, call);
-	  gimple_call_set_lhs (call, var);
+	  call->set_lhs (var);
 	  gsi_insert_before (&gsi, call, GSI_SAME_STMT);
 
 	  fn = builtin_decl_implicit (BUILT_IN_UNWIND_RESUME);
@@ -3583,7 +3583,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
 						       region_nr));
 	    filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
 	    filter = make_ssa_name (filter, call);
-	    gimple_call_set_lhs (call, filter);
+	    call->set_lhs (filter);
 	    gsi_insert_before (&gsi, call, GSI_SAME_STMT);
 
 	    /* Turn the default label into a default case.  */
@@ -3610,7 +3610,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
 						     region_nr));
 	filter = create_tmp_var (TREE_TYPE (TREE_TYPE (fn)), NULL);
 	filter = make_ssa_name (filter, call);
-	gimple_call_set_lhs (call, filter);
+	call->set_lhs (filter);
 	gsi_insert_before (&gsi, call, GSI_SAME_STMT);
 
 	r->u.allowed.label = NULL;
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index 7b17a68..177d0e9 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -438,7 +438,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d)
       gimple_set_location (x, d->loc);
 
       addr = make_ssa_name (addr, x);
-      gimple_call_set_lhs (x, addr);
+      x->set_lhs (addr);
 
       gimple_seq_add_stmt (&d->seq, x);
 
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 83a3e27..e4c80a7 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1683,7 +1683,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
 	      gimple_call_set_va_arg_pack (new_call, false);
 	      gimple_set_location (new_call, gimple_location (stmt));
 	      gimple_set_block (new_call, gimple_block (stmt));
-	      gimple_call_set_lhs (new_call, gimple_call_lhs (stmt));
+	      new_call->set_lhs (gimple_call_lhs (stmt));
 
 	      gsi_replace (&copy_gsi, new_call, false);
 	      stmt = new_call;
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 5f5dcef..0258553 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -406,7 +406,7 @@ init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
   tree t;
 
   t = create_tmp_var_for (info, gimple_call_return_type (call), NULL);
-  gimple_call_set_lhs (call, t);
+  call->set_lhs (t);
   if (! gsi_end_p (*gsi))
     gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
   gsi_insert_before (gsi, call, GSI_SAME_STMT);
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 35c97b6..3acb721 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -4476,7 +4476,7 @@ replace_removed_params_ssa_names (gimple stmt,
   if (is_gimple_assign (stmt))
     gimple_assign_set_lhs (stmt, name);
   else if (is_gimple_call (stmt))
-    gimple_call_set_lhs (static_cast<gimple_call> (stmt), name);
+    static_cast<gimple_call> (stmt)->set_lhs (name);
   else
     gimple_phi_set_result (stmt, name);
 
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 3527848..4451585 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1241,7 +1241,7 @@ eliminate_unnecessary_stmts (void)
 		      fprintf (dump_file, "\n");
 		    }
 
-		  gimple_call_set_lhs (call_stmt, NULL_TREE);
+		  call_stmt->set_lhs (NULL_TREE);
 		  maybe_clean_or_replace_eh_stmt (stmt, stmt);
 		  update_stmt (stmt);
 		  release_ssa_name (name);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index c0415d4..6ad45c9 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1653,7 +1653,7 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
 		 memset call.  */
 	      gimple_call call_stmt1 = static_cast <gimple_call> (stmt1);
 	      if (lhs1 && DECL_FUNCTION_CODE (callee1) == BUILT_IN_MEMPCPY)
-		gimple_call_set_lhs (call_stmt1, NULL_TREE);
+		call_stmt1->set_lhs (NULL_TREE);
 	      gimple_call_set_arg (stmt1, 1, new_str_cst);
 	      gimple_call_set_arg (stmt1, 2,
 				   build_int_cst (TREE_TYPE (len1), src_len));
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 6253c3d..2ffa38a 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -771,7 +771,7 @@ execute_cse_sincos_1 (tree name)
     return false;
   call_stmt = gimple_build_call (fndecl, 1, name);
   res = make_temp_ssa_name (TREE_TYPE (TREE_TYPE (fndecl)), call_stmt, "sincostmp");
-  gimple_call_set_lhs (call_stmt, res);
+  call_stmt->set_lhs (res);
 
   def_stmt = SSA_NAME_DEF_STMT (name);
   if (!SSA_NAME_IS_DEFAULT_DEF (name)
@@ -2022,7 +2022,7 @@ execute_optimize_bswap (void)
 	      gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT);
 	    }
 
-	  gimple_call_set_lhs (call, bswap_tmp);
+	  call->set_lhs (bswap_tmp);
 
 	  if (dump_file)
 	    {
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 4565de0..0c84581 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -700,7 +700,7 @@ static void
 finish_update_gimple_call (gimple_stmt_iterator *si_p, gimple_call new_stmt,
 			   gimple stmt)
 {
-  gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
+  new_stmt->set_lhs (gimple_call_lhs (stmt));
   move_ssa_defining_stmt_for_defs (new_stmt, stmt);
   gimple_set_vuse (new_stmt, gimple_vuse (stmt));
   gimple_set_vdef (new_stmt, gimple_vdef (stmt));
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 982c6d2..0e66f7c 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -4097,7 +4097,7 @@ attempt_builtin_powi (gimple stmt, vec<operand_entry_t> *ops)
 	      pow_stmt = gimple_build_call (powi_fndecl, 2, rf1->repr, 
 					    build_int_cst (integer_type_node,
 							   power));
-	      gimple_call_set_lhs (pow_stmt, iter_result);
+	      pow_stmt->set_lhs (iter_result);
 	      gimple_set_location (pow_stmt, gimple_location (stmt));
 	      gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT);
 
@@ -4198,7 +4198,7 @@ attempt_builtin_powi (gimple stmt, vec<operand_entry_t> *ops)
 	  pow_stmt = gimple_build_call (powi_fndecl, 2, rf1->repr, 
 					build_int_cst (integer_type_node,
 						       power));
-	  gimple_call_set_lhs (pow_stmt, iter_result);
+	  pow_stmt->set_lhs (iter_result);
 	  gimple_set_location (pow_stmt, gimple_location (stmt));
 	  gsi_insert_before (&gsi, pow_stmt, GSI_SAME_STMT);
 	}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index ad18fc1..f47b20f 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -441,7 +441,7 @@ get_string_length (strinfo si)
 	  tem = unshare_expr (gimple_call_arg (stmt, 0));
 	  lenstmt_call = gimple_build_call (fn, 1, tem);
 	  lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), lenstmt_call);
-	  gimple_call_set_lhs (lenstmt_call, lhs);
+	  lenstmt_call->set_lhs (lhs);
 	  gimple_set_vuse (lenstmt_call, gimple_vuse (stmt));
 	  gsi_insert_before (&gsi, lenstmt_call, GSI_SAME_STMT);
 	  tem = gimple_call_arg (stmt, 0);
@@ -474,7 +474,7 @@ get_string_length (strinfo si)
 	    }
 	  gimple_call_set_fndecl (stmt, fn);
 	  lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (fn)), stmt);
-	  gimple_call_set_lhs (call_stmt, lhs);
+	  call_stmt->set_lhs (lhs);
 	  update_stmt (stmt);
 	  if (dump_file && (dump_flags & TDF_DETAILS) != 0)
 	    {
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 2ddaebe..7b8d20d 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -4468,7 +4468,7 @@ vect_setup_realignment (gimple stmt, gimple_stmt_iterator *gsi,
 	vect_create_destination_var (scalar_dest,
 				     gimple_call_return_type (call_stmt));
       new_temp = make_ssa_name (vec_dest, call_stmt);
-      gimple_call_set_lhs (call_stmt, new_temp);
+      call_stmt->set_lhs (new_temp);
 
       if (compute_in_loop)
 	gsi_insert_before (gsi, call_stmt, GSI_SAME_STMT);
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 2dc918f..b1a1e5f 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -806,7 +806,7 @@ vect_recog_pow_pattern (vec<gimple> *stmts, tree *type_in,
 	      != NULL_TREE)
 	    {
 	      var = vect_recog_temp_ssa_var (TREE_TYPE (base), stmt);
-	      gimple_call_set_lhs (stmt, var);
+	      stmt->set_lhs (var);
 	      return stmt;
 	    }
 	}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 906a44d..b982046 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1943,7 +1943,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 		  gimple_call call = gimple_build_call_vec (fndecl, vargs);
 		  new_stmt = call;
 		  new_temp = make_ssa_name (vec_dest, new_stmt);
-		  gimple_call_set_lhs (call, new_temp);
+		  call->set_lhs (new_temp);
 		  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 		  SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
 		}
@@ -1996,7 +1996,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	      gimple_call call = gimple_build_call_vec (fndecl, vargs);
 	      new_stmt = call;
 	      new_temp = make_ssa_name (vec_dest, new_stmt);
-	      gimple_call_set_lhs (call, new_temp);
+	      call->set_lhs (new_temp);
 	    }
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
@@ -2044,7 +2044,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 		  gimple_call call = gimple_build_call_vec (fndecl, vargs);
 		  new_stmt = call;
 		  new_temp = make_ssa_name (vec_dest, new_stmt);
-		  gimple_call_set_lhs (call, new_temp);
+		  call->set_lhs (new_temp);
 		  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 		  SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
 		}
@@ -2084,7 +2084,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  gimple_call call = gimple_build_call_vec (fndecl, vargs);
 	  new_stmt = call;
 	  new_temp = make_ssa_name (vec_dest, new_stmt);
-	  gimple_call_set_lhs (call, new_temp);
+	  call->set_lhs (new_temp);
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
 	  if (j == 0)
@@ -2164,7 +2164,7 @@ vect_gen_widened_results_half (enum tree_code code,
 	call = gimple_build_call (decl, 1, vec_oprnd0);
       new_stmt = call;
       new_temp = make_ssa_name (vec_dest, new_stmt);
-      gimple_call_set_lhs (call, new_temp);
+      call->set_lhs (new_temp);
     }
   else
     {
@@ -2719,7 +2719,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
 		  gimple_call call = gimple_build_call (decl1, 1, vop0);
 		  new_stmt = call;
 		  new_temp = make_ssa_name (vec_dest, new_stmt);
-		  gimple_call_set_lhs (call, new_temp);
+		  call->set_lhs (new_temp);
 		}
 	      else
 		{
@@ -2831,7 +2831,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
 		      gimple_call call = gimple_build_call (decl1, 1, vop0);
 		      new_stmt = call;
 		      new_temp = make_ssa_name (vec_dest, new_stmt);
-		      gimple_call_set_lhs (call, new_temp);
+		      call->set_lhs (new_temp);
 		    }
 		  else
 		    {
@@ -2890,7 +2890,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
 		    gimple_call call = gimple_build_call (decl1, 1, vop0);
 		    new_stmt = call;
 		    new_temp = make_ssa_name (vec_dest, new_stmt);
-		    gimple_call_set_lhs (call, new_temp);
+		    call->set_lhs (new_temp);
 		  }
 		else
 		  {
@@ -4251,7 +4251,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
 	  gimple_call call = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array);
 	  new_stmt = call;
-	  gimple_call_set_lhs (call, data_ref);
+	  call->set_lhs (data_ref);
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 	}
       else
@@ -4752,7 +4752,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 			  == TYPE_VECTOR_SUBPARTS (rettype));
 	      var = vect_get_new_vect_var (rettype, vect_simple_var, NULL);
 	      op = make_ssa_name (var, new_stmt);
-	      gimple_call_set_lhs (call, op);
+	      call->set_lhs (op);
 	      vect_finish_stmt_generation (stmt, new_stmt, gsi);
 	      var = make_ssa_name (vec_dest, NULL);
 	      op = build1 (VIEW_CONVERT_EXPR, vectype, op);
@@ -4763,7 +4763,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  else
 	    {
 	      var = make_ssa_name (vec_dest, new_stmt);
-	      gimple_call_set_lhs (call, var);
+	      call->set_lhs (var);
 	    }
 
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
@@ -5124,7 +5124,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
 	  data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
 	  gimple_call call = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref);
 	  new_stmt = call;
-	  gimple_call_set_lhs (call, vec_array);
+	  call->set_lhs (vec_array);
 	  vect_finish_stmt_generation (stmt, new_stmt, gsi);
 
 	  /* Extract each vector into an SSA_NAME.  */
diff --git a/gcc/tsan.c b/gcc/tsan.c
index de95625..8a8dccf 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -489,8 +489,7 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
 		    args[1] = var;
 		  }
 		gimple_call call_stmt = as_a<gimple_statement_call> (stmt);
-		gimple_call_set_lhs (call_stmt,
-				     make_ssa_name (TREE_TYPE (lhs), NULL));
+		call_stmt->set_lhs (make_ssa_name (TREE_TYPE (lhs), NULL));
 		/* BIT_NOT_EXPR stands for NAND.  */
 		if (tsan_atomic_table[i].code == BIT_NOT_EXPR)
 		  {
@@ -572,7 +571,7 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
 						  args[1],
 						  gimple_assign_lhs (g));
 		gimple_call call_stmt = as_a<gimple_statement_call> (stmt);
-		gimple_call_set_lhs (call_stmt, t);
+		call_stmt->set_lhs (t);
 		update_stmt (stmt);
 		gsi_insert_after (gsi, g, GSI_NEW_STMT);
 	      }
@@ -660,7 +659,7 @@ instrument_func_entry (void)
   builtin_decl = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
   g = gimple_build_call (builtin_decl, 1, integer_zero_node);
   ret_addr = make_ssa_name (ptr_type_node, NULL);
-  gimple_call_set_lhs (g, ret_addr);
+  g->set_lhs (ret_addr);
   gimple_set_location (g, cfun->function_start_locus);
   gsi_insert_before (&gsi, g, GSI_SAME_STMT);
 
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 7ca9f4d..29d40a1 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -1332,7 +1332,7 @@ gimple_ic (gimple_call icall_stmt, struct cgraph_node *direct_call,
   gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
   dflags = flags_from_decl_or_type (direct_call->decl);
   if ((dflags & ECF_NORETURN) != 0)
-    gimple_call_set_lhs (dcall_stmt, NULL_TREE);
+    dcall_stmt->set_lhs (NULL_TREE);
   gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
 
   /* Fix CFG. */
@@ -1397,11 +1397,9 @@ gimple_ic (gimple_call icall_stmt, struct cgraph_node *direct_call,
     {
       tree result = gimple_call_lhs (icall_stmt);
       gimple phi = create_phi_node (result, join_bb);
-      gimple_call_set_lhs (icall_stmt,
-			   duplicate_ssa_name (result, icall_stmt));
+      icall_stmt->set_lhs (duplicate_ssa_name (result, icall_stmt));
       add_phi_arg (phi, gimple_call_lhs (icall_stmt), e_ij, UNKNOWN_LOCATION);
-      gimple_call_set_lhs (dcall_stmt,
-			   duplicate_ssa_name (result, dcall_stmt));
+      dcall_stmt->set_lhs (duplicate_ssa_name (result, dcall_stmt));
       add_phi_arg (phi, gimple_call_lhs (dcall_stmt), e_dj, UNKNOWN_LOCATION);
     }
 
@@ -1637,11 +1635,9 @@ gimple_stringop_fixed_value (gimple_call vcall_stmt, tree icall_size, int prob,
     {
       tree result = gimple_call_lhs (vcall_stmt);
       gimple phi = create_phi_node (result, join_bb);
-      gimple_call_set_lhs (vcall_stmt,
-			   duplicate_ssa_name (result, vcall_stmt));
+      vcall_stmt->set_lhs (duplicate_ssa_name (result, vcall_stmt));
       add_phi_arg (phi, gimple_call_lhs (vcall_stmt), e_vj, UNKNOWN_LOCATION);
-      gimple_call_set_lhs (icall_stmt,
-			   duplicate_ssa_name (result, icall_stmt));
+      icall_stmt->set_lhs (duplicate_ssa_name (result, icall_stmt));
       add_phi_arg (phi, gimple_call_lhs (icall_stmt), e_ij, UNKNOWN_LOCATION);
     }
 
diff --git a/gcc/vtable-verify.c b/gcc/vtable-verify.c
index a276a8d..d743c3e 100644
--- a/gcc/vtable-verify.c
+++ b/gcc/vtable-verify.c
@@ -686,7 +686,7 @@ verify_bb_vtables (basic_block bb)
                      return value, and make the call_stmt use the
                      variable for that purpose.  */
                   tmp0 = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "VTV");
-                  gimple_call_set_lhs (call_stmt, tmp0);
+                  call_stmt->set_lhs (tmp0);
                   update_stmt (call_stmt);
 
                   /* Find the next stmt, after the vptr assignment

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 21:52               ` David Malcolm
@ 2013-11-04 22:09                 ` David Malcolm
  2013-11-04 22:31                   ` Andrew MacLeod
  2013-11-04 22:43                   ` Andrew MacLeod
  2013-11-04 22:28                 ` Jakub Jelinek
  2013-11-05 11:53                 ` Richard Biener
  2 siblings, 2 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-04 22:09 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Jakub Jelinek, gcc-patches

On Mon, 2013-11-04 at 16:43 -0500, David Malcolm wrote:
> On Mon, 2013-11-04 at 08:19 -0500, Andrew MacLeod wrote:
> > On 11/01/2013 06:58 PM, David Malcolm wrote:
> > > On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
> > >> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
> > >>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
> > >>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
> > >>>>>    static inline void
> > >>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
> > >>>>>    {
> > >>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
> > >> The checking you are removing here.
> > >>
> > >>> What checking?  There ought to be no checking at all in this
> > >>> example...  gimple_build_call_vec returns a gimple_call, and
> > >>> gimple_call_set_lhs()  doesn't have to check anything because it
> > >>> only accepts gimple_call's.. so there is no checking other than the
> > >>> usual "does my parameter match" that the compiler has to do...
> > >> and want to replace it by checking of the types at compile time.
> > >> The problem is that it uglifies the source too much, and, when you
> > >> actually don't have a gimple_call but supposedly a base class of it,
> > >> I expect you'd do as_a which is not only further uglification, but has
> > >> runtime cost also for --enable-checking=release.
> > > I can have a look next week at every call to gimple_call_set_lhs in the
> > > tree, and see to what extent we know at compile-time that the initial
> > > arg is indeed a call (of the ones I quickly grepped just now, most are
> > > from gimple_build_call and friends, but one was from a gimple_copy).
> > >
> > > FWIW I did some performance testing of the is_a/as_a code in the earlier
> > > version of the patch, and it didn't have a noticable runtime cost
> > > compared to the GIMPLE_CHECK in the existing code:
> > > Size of compiler executable:
> > > http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
> > > Compile times:
> > > http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html
> > I actually really dislike as_a<> and is_a<>, and  think code needs to be 
> > restructured rather than use them, other than possibly at the very 
> > bottom level when we're allocating memory or something like that, or 
> > some kind of emergency :-)...   If we require frequent uses of those, 
> > I'd be against it, I find them quite ugly.
> > 
> > Like I said in the other reply, no rush, I don't think any of this 
> > follow up is appropriate this late in stage 1.  

I wasn't aware that there was a ramp in conservatism within stage1 - I
thought that we had a "large (tested) changes are OK" attitude
throughout all of stage1, and that the switch to conservatism only began
at the transition to stage3.  (and have been frantically attempting to
get my big changes in before November 21st - should I be rethinking
this?)

> It would be more of an 
> > "interest" examination right now.. at least in my opinion...  I suspect 
> > thinks like gimple_assign are more complex cases, but without looking 
> > its hard to tell for sure.
> 
> I tried converting gimple_call_set_lhs to accept a gimple_call, rather
> than a gimple, and excitingly, it was easiest to also convert
> cgraph_edge's call_stmt to also be a gimple_call, rather than just a
> gimple.
> 
> Am attaching a patch (on top of the patch series being discussed) which
> adds this compile-time typesafety; bootstrap is in-progress.   IMHO very
> little use of is-a.h was needed (5 instances of as_a, and 3 of dyn_cast;
> no use of is_a).
> 
> I'm also attaching a followup patch which eliminates gimple_call_set_lhs
> in favor of a method of gimple_statement_call.

(I posted the two patches in my prioer email more as a talking point
than for detailed review, sorry if that wasn't clear).

FWIW, my preferred strategy for 4.9 is a compromise: to do the 1st patch
but not the 2nd: i.e. to make the existing gimple_foo_bar accessor
functions be typesafe at compile-time, but without converting them to
C++ methods - I think this gives us compile-time type-safety, whilst
minimizing code-churn and minimizing the more "C++ish" aspects that may
alarm those less happy with C++ in the codebase.

I believe it would be easiest to do them one subclass at-a-time e.g.
convert all gimple_call_* functions to accepting a gimple_call, then
another subclass etc - assuming that this approach is blessed by the
core reviewers.

Dave

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 21:52               ` David Malcolm
  2013-11-04 22:09                 ` David Malcolm
@ 2013-11-04 22:28                 ` Jakub Jelinek
  2013-11-04 22:49                   ` Andrew MacLeod
  2013-11-05 21:09                   ` Jeff Law
  2013-11-05 11:53                 ` Richard Biener
  2 siblings, 2 replies; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-04 22:28 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrew MacLeod, gcc-patches

On Mon, Nov 04, 2013 at 04:43:33PM -0500, David Malcolm wrote:
> I tried converting gimple_call_set_lhs to accept a gimple_call, rather
> than a gimple, and excitingly, it was easiest to also convert
> cgraph_edge's call_stmt to also be a gimple_call, rather than just a
> gimple.
> 
> Am attaching a patch (on top of the patch series being discussed) which
> adds this compile-time typesafety; bootstrap is in-progress.   IMHO very
> little use of is-a.h was needed (5 instances of as_a, and 3 of dyn_cast;
> no use of is_a).

But that was just for gimple_call_set_lhs, which indeed usually is done just
for newly created calls, not for inspecting preexisting IL.  If you do it
for say gimple_call_arg, gimple_call_fndecl and/or even gimple_call_lhs, I'm
afraid suddenly it would be hundreds of ugly dyn_casts/as_a and similar mess
everywhere.  And, calls are still far less common gimple statements than
gimple assign.

	Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 22:09                 ` David Malcolm
@ 2013-11-04 22:31                   ` Andrew MacLeod
  2013-11-05 21:27                     ` Jeff Law
  2013-11-04 22:43                   ` Andrew MacLeod
  1 sibling, 1 reply; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-04 22:31 UTC (permalink / raw)
  To: David Malcolm; +Cc: Jakub Jelinek, gcc-patches

On 11/04/2013 05:03 PM, David Malcolm wrote:
> On Mon, 2013-11-04 at 16:43 -0500, David Malcolm wrote:
>> On Mon, 2013-11-04 at 08:19 -0500, Andrew MacLeod wrote:
>>> On 11/01/2013 06:58 PM, David Malcolm wrote:
>>>> On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
>>>>> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
>>>>>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
>>>>>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>>>>>>>>     static inline void
>>>>>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
>>>>>>>>     {
>>>>>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>>>>> The checking you are removing here.
>>>>>
>>>>>> What checking?  There ought to be no checking at all in this
>>>>>> example...  gimple_build_call_vec returns a gimple_call, and
>>>>>> gimple_call_set_lhs()  doesn't have to check anything because it
>>>>>> only accepts gimple_call's.. so there is no checking other than the
>>>>>> usual "does my parameter match" that the compiler has to do...
>>>>> and want to replace it by checking of the types at compile time.
>>>>> The problem is that it uglifies the source too much, and, when you
>>>>> actually don't have a gimple_call but supposedly a base class of it,
>>>>> I expect you'd do as_a which is not only further uglification, but has
>>>>> runtime cost also for --enable-checking=release.
>>>> I can have a look next week at every call to gimple_call_set_lhs in the
>>>> tree, and see to what extent we know at compile-time that the initial
>>>> arg is indeed a call (of the ones I quickly grepped just now, most are
>>>> from gimple_build_call and friends, but one was from a gimple_copy).
>>>>
>>>> FWIW I did some performance testing of the is_a/as_a code in the earlier
>>>> version of the patch, and it didn't have a noticable runtime cost
>>>> compared to the GIMPLE_CHECK in the existing code:
>>>> Size of compiler executable:
>>>> http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
>>>> Compile times:
>>>> http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html
>>> I actually really dislike as_a<> and is_a<>, and  think code needs to be
>>> restructured rather than use them, other than possibly at the very
>>> bottom level when we're allocating memory or something like that, or
>>> some kind of emergency :-)...   If we require frequent uses of those,
>>> I'd be against it, I find them quite ugly.
>>>
>>> Like I said in the other reply, no rush, I don't think any of this
>>> follow up is appropriate this late in stage 1.
> I wasn't aware that there was a ramp in conservatism within stage1 - I
> thought that we had a "large (tested) changes are OK" attitude
> throughout all of stage1, and that the switch to conservatism only began
> at the transition to stage3.  (and have been frantically attempting to
> get my big changes in before November 21st - should I be rethinking
> this?)
You read a lot into things :-)

No, what I mean its too late to get a full change in, and partial 
changes don't seem worthwhile to me.. ie, I don't think there is much 
point in partially converting one or two gimple stmt kinds and leaving 
the others unconverted.  so converting gimple_call_stmt and some of its 
access methods doesnt seem worthwhile to me right now when we could do 
the entire thing during the next stage1 for instance.   There isnt 
enough benefit.    Especially since as the work progresses you may 
discover improvements that make you go back and unwind some of the 
changes you would now commit.   I believe this is a large enough body of 
work that needs some serious implementation before any of it would be 
appropriate for mainline.

That said, the patch which enables this is more self contained, so 
wouldn't be subject to that. Its a matter of whether it has enough merit 
of its own to go in.   Having the first patch in mainline would actually 
allow someone to experiment more easily during the "off season" if they 
wanted to, but wouldn't be mandatory since they could apply it to their 
own branch to work on.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 22:09                 ` David Malcolm
  2013-11-04 22:31                   ` Andrew MacLeod
@ 2013-11-04 22:43                   ` Andrew MacLeod
  1 sibling, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-04 22:43 UTC (permalink / raw)
  To: David Malcolm; +Cc: Jakub Jelinek, gcc-patches

On 11/04/2013 05:03 PM, David Malcolm wrote:

> I believe it would be easiest to do them one subclass at-a-time e.g.
> convert all gimple_call_* functions to accepting a gimple_call, then
> another subclass etc - assuming that this approach is blessed by the
> core reviewers.
>
I think the strategy for reworking the gimple stmts needs quite a bit of 
experimenting to determine what would have to be done and what it would 
look like, and to get buy in from more people that the end result is 
indeed acceptable.  There are complex situation, and I dont see how we 
can avoid virtual functions in some cases (at least not easily without 
resorting to ugly as_a/is_a/dyn_cast functions). So I thinkit needs 
research.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 22:28                 ` Jakub Jelinek
@ 2013-11-04 22:49                   ` Andrew MacLeod
  2013-11-05 21:09                   ` Jeff Law
  1 sibling, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-04 22:49 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: David Malcolm, gcc-patches

On 11/04/2013 05:25 PM, Jakub Jelinek wrote:
> On Mon, Nov 04, 2013 at 04:43:33PM -0500, David Malcolm wrote:
>> I tried converting gimple_call_set_lhs to accept a gimple_call, rather
>> than a gimple, and excitingly, it was easiest to also convert
>> cgraph_edge's call_stmt to also be a gimple_call, rather than just a
>> gimple.
>>
>> Am attaching a patch (on top of the patch series being discussed) which
>> adds this compile-time typesafety; bootstrap is in-progress.   IMHO very
>> little use of is-a.h was needed (5 instances of as_a, and 3 of dyn_cast;
>> no use of is_a).
> But that was just for gimple_call_set_lhs, which indeed usually is done just
> for newly created calls, not for inspecting preexisting IL.  If you do it
> for say gimple_call_arg, gimple_call_fndecl and/or even gimple_call_lhs, I'm
> afraid suddenly it would be hundreds of ugly dyn_casts/as_a and similar mess
> everywhere.  And, calls are still far less common gimple statements than
> gimple assign.
>
> 	
Indeed, we need to look at a much larger swath of code before even 
thinking of committing anything.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 21:52               ` David Malcolm
  2013-11-04 22:09                 ` David Malcolm
  2013-11-04 22:28                 ` Jakub Jelinek
@ 2013-11-05 11:53                 ` Richard Biener
  2013-11-05 12:33                   ` David Malcolm
  2 siblings, 1 reply; 116+ messages in thread
From: Richard Biener @ 2013-11-05 11:53 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrew MacLeod, Jakub Jelinek, GCC Patches

On Mon, Nov 4, 2013 at 10:43 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Mon, 2013-11-04 at 08:19 -0500, Andrew MacLeod wrote:
>> On 11/01/2013 06:58 PM, David Malcolm wrote:
>> > On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
>> >> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
>> >>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
>> >>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>> >>>>>    static inline void
>> >>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
>> >>>>>    {
>> >>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>> >> The checking you are removing here.
>> >>
>> >>> What checking?  There ought to be no checking at all in this
>> >>> example...  gimple_build_call_vec returns a gimple_call, and
>> >>> gimple_call_set_lhs()  doesn't have to check anything because it
>> >>> only accepts gimple_call's.. so there is no checking other than the
>> >>> usual "does my parameter match" that the compiler has to do...
>> >> and want to replace it by checking of the types at compile time.
>> >> The problem is that it uglifies the source too much, and, when you
>> >> actually don't have a gimple_call but supposedly a base class of it,
>> >> I expect you'd do as_a which is not only further uglification, but has
>> >> runtime cost also for --enable-checking=release.
>> > I can have a look next week at every call to gimple_call_set_lhs in the
>> > tree, and see to what extent we know at compile-time that the initial
>> > arg is indeed a call (of the ones I quickly grepped just now, most are
>> > from gimple_build_call and friends, but one was from a gimple_copy).
>> >
>> > FWIW I did some performance testing of the is_a/as_a code in the earlier
>> > version of the patch, and it didn't have a noticable runtime cost
>> > compared to the GIMPLE_CHECK in the existing code:
>> > Size of compiler executable:
>> > http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
>> > Compile times:
>> > http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html
>> I actually really dislike as_a<> and is_a<>, and  think code needs to be
>> restructured rather than use them, other than possibly at the very
>> bottom level when we're allocating memory or something like that, or
>> some kind of emergency :-)...   If we require frequent uses of those,
>> I'd be against it, I find them quite ugly.
>>
>> Like I said in the other reply, no rush, I don't think any of this
>> follow up is appropriate this late in stage 1.  It would be more of an
>> "interest" examination right now.. at least in my opinion...  I suspect
>> thinks like gimple_assign are more complex cases, but without looking
>> its hard to tell for sure.
>
> I tried converting gimple_call_set_lhs to accept a gimple_call, rather
> than a gimple, and excitingly, it was easiest to also convert
> cgraph_edge's call_stmt to also be a gimple_call, rather than just a
> gimple.

Does that work (using gimple_call * objects) for our garbage collector?
That is, does it know it is looking at a 'gimple'?  It doesn't matter for this
case as all stmts are reachable from struct function as sequence of 'gimple',
but in general?

Richard.

> Am attaching a patch (on top of the patch series being discussed) which
> adds this compile-time typesafety; bootstrap is in-progress.   IMHO very
> little use of is-a.h was needed (5 instances of as_a, and 3 of dyn_cast;
> no use of is_a).
>
> I'm also attaching a followup patch which eliminates gimple_call_set_lhs
> in favor of a method of gimple_statement_call.
>

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 11:53                 ` Richard Biener
@ 2013-11-05 12:33                   ` David Malcolm
  2013-11-05 12:52                     ` Richard Biener
  0 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-11-05 12:33 UTC (permalink / raw)
  To: Richard Biener; +Cc: Andrew MacLeod, Jakub Jelinek, GCC Patches

On Tue, 2013-11-05 at 12:47 +0100, Richard Biener wrote:
> On Mon, Nov 4, 2013 at 10:43 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> > On Mon, 2013-11-04 at 08:19 -0500, Andrew MacLeod wrote:
> >> On 11/01/2013 06:58 PM, David Malcolm wrote:
> >> > On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
> >> >> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
> >> >>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
> >> >>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
> >> >>>>>    static inline void
> >> >>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
> >> >>>>>    {
> >> >>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
> >> >> The checking you are removing here.
> >> >>
> >> >>> What checking?  There ought to be no checking at all in this
> >> >>> example...  gimple_build_call_vec returns a gimple_call, and
> >> >>> gimple_call_set_lhs()  doesn't have to check anything because it
> >> >>> only accepts gimple_call's.. so there is no checking other than the
> >> >>> usual "does my parameter match" that the compiler has to do...
> >> >> and want to replace it by checking of the types at compile time.
> >> >> The problem is that it uglifies the source too much, and, when you
> >> >> actually don't have a gimple_call but supposedly a base class of it,
> >> >> I expect you'd do as_a which is not only further uglification, but has
> >> >> runtime cost also for --enable-checking=release.
> >> > I can have a look next week at every call to gimple_call_set_lhs in the
> >> > tree, and see to what extent we know at compile-time that the initial
> >> > arg is indeed a call (of the ones I quickly grepped just now, most are
> >> > from gimple_build_call and friends, but one was from a gimple_copy).
> >> >
> >> > FWIW I did some performance testing of the is_a/as_a code in the earlier
> >> > version of the patch, and it didn't have a noticable runtime cost
> >> > compared to the GIMPLE_CHECK in the existing code:
> >> > Size of compiler executable:
> >> > http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
> >> > Compile times:
> >> > http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html
> >> I actually really dislike as_a<> and is_a<>, and  think code needs to be
> >> restructured rather than use them, other than possibly at the very
> >> bottom level when we're allocating memory or something like that, or
> >> some kind of emergency :-)...   If we require frequent uses of those,
> >> I'd be against it, I find them quite ugly.
> >>
> >> Like I said in the other reply, no rush, I don't think any of this
> >> follow up is appropriate this late in stage 1.  It would be more of an
> >> "interest" examination right now.. at least in my opinion...  I suspect
> >> thinks like gimple_assign are more complex cases, but without looking
> >> its hard to tell for sure.
> >
> > I tried converting gimple_call_set_lhs to accept a gimple_call, rather
> > than a gimple, and excitingly, it was easiest to also convert
> > cgraph_edge's call_stmt to also be a gimple_call, rather than just a
> > gimple.
> 
> Does that work (using gimple_call * objects) for our garbage collector?
> That is, does it know it is looking at a 'gimple'?  It doesn't matter for this
> case as all stmts are reachable from struct function as sequence of 'gimple',
> but in general?
Yes (as of r204146, I believe).

For example, the patch converts cgraph_edge's call_stmt to be a
"gimple_call", rather than just a "gimple", but gengtype handles this by
emitting a call to the base class visitor for call_stmt i.e.
gimple_statement_base:

void
gt_ggc_mx_cgraph_edge (void *x_p)
{
  struct cgraph_edge * x = (struct cgraph_edge *)x_p;
  [...snip chain_next/prev handling...]
  [...snip other fields...]
      gt_ggc_m_21gimple_statement_base ((*x).call_stmt);
  [..etc..]
}


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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 12:33                   ` David Malcolm
@ 2013-11-05 12:52                     ` Richard Biener
  0 siblings, 0 replies; 116+ messages in thread
From: Richard Biener @ 2013-11-05 12:52 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrew MacLeod, Jakub Jelinek, GCC Patches

On Tue, Nov 5, 2013 at 1:30 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Tue, 2013-11-05 at 12:47 +0100, Richard Biener wrote:
>> On Mon, Nov 4, 2013 at 10:43 PM, David Malcolm <dmalcolm@redhat.com> wrote:
>> > On Mon, 2013-11-04 at 08:19 -0500, Andrew MacLeod wrote:
>> >> On 11/01/2013 06:58 PM, David Malcolm wrote:
>> >> > On Fri, 2013-11-01 at 22:57 +0100, Jakub Jelinek wrote:
>> >> >> On Fri, Nov 01, 2013 at 05:47:14PM -0400, Andrew MacLeod wrote:
>> >> >>> On 11/01/2013 05:41 PM, Jakub Jelinek wrote:
>> >> >>>> On Fri, Nov 01, 2013 at 05:36:34PM -0400, Andrew MacLeod wrote:
>> >> >>>>>    static inline void
>> >> >>>>> ! gimple_call_set_lhs (gimple gs, tree lhs)
>> >> >>>>>    {
>> >> >>>>> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>> >> >> The checking you are removing here.
>> >> >>
>> >> >>> What checking?  There ought to be no checking at all in this
>> >> >>> example...  gimple_build_call_vec returns a gimple_call, and
>> >> >>> gimple_call_set_lhs()  doesn't have to check anything because it
>> >> >>> only accepts gimple_call's.. so there is no checking other than the
>> >> >>> usual "does my parameter match" that the compiler has to do...
>> >> >> and want to replace it by checking of the types at compile time.
>> >> >> The problem is that it uglifies the source too much, and, when you
>> >> >> actually don't have a gimple_call but supposedly a base class of it,
>> >> >> I expect you'd do as_a which is not only further uglification, but has
>> >> >> runtime cost also for --enable-checking=release.
>> >> > I can have a look next week at every call to gimple_call_set_lhs in the
>> >> > tree, and see to what extent we know at compile-time that the initial
>> >> > arg is indeed a call (of the ones I quickly grepped just now, most are
>> >> > from gimple_build_call and friends, but one was from a gimple_copy).
>> >> >
>> >> > FWIW I did some performance testing of the is_a/as_a code in the earlier
>> >> > version of the patch, and it didn't have a noticable runtime cost
>> >> > compared to the GIMPLE_CHECK in the existing code:
>> >> > Size of compiler executable:
>> >> > http://gcc.gnu.org/ml/gcc-patches/2013-08/msg01920.html
>> >> > Compile times:
>> >> > http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00171.html
>> >> I actually really dislike as_a<> and is_a<>, and  think code needs to be
>> >> restructured rather than use them, other than possibly at the very
>> >> bottom level when we're allocating memory or something like that, or
>> >> some kind of emergency :-)...   If we require frequent uses of those,
>> >> I'd be against it, I find them quite ugly.
>> >>
>> >> Like I said in the other reply, no rush, I don't think any of this
>> >> follow up is appropriate this late in stage 1.  It would be more of an
>> >> "interest" examination right now.. at least in my opinion...  I suspect
>> >> thinks like gimple_assign are more complex cases, but without looking
>> >> its hard to tell for sure.
>> >
>> > I tried converting gimple_call_set_lhs to accept a gimple_call, rather
>> > than a gimple, and excitingly, it was easiest to also convert
>> > cgraph_edge's call_stmt to also be a gimple_call, rather than just a
>> > gimple.
>>
>> Does that work (using gimple_call * objects) for our garbage collector?
>> That is, does it know it is looking at a 'gimple'?  It doesn't matter for this
>> case as all stmts are reachable from struct function as sequence of 'gimple',
>> but in general?
> Yes (as of r204146, I believe).
>
> For example, the patch converts cgraph_edge's call_stmt to be a
> "gimple_call", rather than just a "gimple", but gengtype handles this by
> emitting a call to the base class visitor for call_stmt i.e.
> gimple_statement_base:
>
> void
> gt_ggc_mx_cgraph_edge (void *x_p)
> {
>   struct cgraph_edge * x = (struct cgraph_edge *)x_p;
>   [...snip chain_next/prev handling...]
>   [...snip other fields...]
>       gt_ggc_m_21gimple_statement_base ((*x).call_stmt);
>   [..etc..]
> }

Ah, nice to know.

Thanks,
Richard.

>

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

* [patch]  Create gimple-expr..[ch]  ...  was Re: RFC: gimple.[ch] break apart
  2013-10-31  5:45 RFC: gimple.[ch] break apart Andrew MacLeod
  2013-10-31  6:15 ` Jeff Law
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
@ 2013-11-05 16:58 ` Andrew MacLeod
  2013-11-05 17:52   ` Jeff Law
  2013-11-07 10:58   ` Basile Starynkevitch
  2 siblings, 2 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-05 16:58 UTC (permalink / raw)
  To: gcc-patches, Richard Biener, Jeff Law, Diego Novillo

[-- Attachment #1: Type: text/plain, Size: 3393 bytes --]

On 10/30/2013 11:18 PM, Andrew MacLeod wrote:
>
>
> As a result, any gimple queries regarding types, decls, or expressions
> are actually tree queries. They are sprinkled throughout gimple.[ch] and
> gimplify.[ch], not to mention tree.[ch] as well as other parts of the
> compiler where they happened to be needed.  This has caused various
> ordering issues among the inline functions when I tried to split out the
> stmt, iterator, and gimplification bits from gimple.[ch].  Not to
> mention a lack of an obvious home for some of these functions.
>
> I'd like to move these as I encounter them into a new file,
> gimple-decl.[ch].  When I'm working on the other gimple classes, this
> will be further split into gimple-decl, gimple-type and gimple-expr as
> appropriate but it seems reasonable to create just the one file now to
> clump them since there is no other formal organization. So any function
> which is actually querying/setting/building a decl, type, or expression
> for gimple would go here.

I decided to name the new file gimple-expr.[ch] instead of 
gimple-decl....   This will eventually split into gimple-type.[ch], 
gimple-decl.[ch], and gimple-expr.[ch].  I could split them that way now 
if desired, but isn't critical yet. maybe I should just do that... 
Anyway, of the 3 files, gimple-expr will depend on the other 2, and thus 
is likely to be the one #included in places like the rtl generation 
files that need access to all these gimple dictionary/expression 
routines.   (eventually those rtl files will include only gimple-expr.h 
and not tree.h :-).

In any case, I had to do this split from gimple.h first since 
gimple-stmt.[ch] and the others require some of these basic routines, 
and I can't split anything else out first without then getting an 
include dependency cycle between gimple.h and gimple-stmt.h for 
instance.  This way gimple-stmt.h can include gimple-expr.h, and then 
gimple.h can include gimpe-stmt.h and no chicken/egg situation.

This contains just the functions that are in either in, or prototyped 
in, gimple.h, and is just the first cut.  There are more things that 
will eventually get put here from gimple.c, but their prototypes are in 
places like tree.h and more include cycles or poor requirements on files 
to include are exposed if I move them now since  front ends or rtl files 
are using those routines (like get_base_address).  There are also a few 
I wanted to hold off on and see how things work out before moving them.

In any case, I tried to pull out the functions that operated on trees 
currently and performed an operation on a type, decl, or expression.  My 
litmus test was usually, "Is this liekly going to be a method of a type, 
decl or expr class relating to the object itself." and moved it if it 
seemed so.

The slightly iffier ones were extract_ops_from_tree*() and 
gimple_cond_get_ops_from_tree()... Those clearly worked on expressions 
and not statements, but are utilized in places like rtl land that don't 
deal with stmts...  so they need to be exposed via the expression 
processing and interface.  Its also quite possible those will end up in 
gimplify.[ch] once I get that far...

I do expect there will still be a little bit of fine tuning, but this is 
the first cut to enable me to split out gimple-stmts.[ch] next.

Bootstraps on x86_64-unknown-linux-gnu with no new regressions.  OK?

Andrew


[-- Attachment #2: gexpr.patch --]
[-- Type: text/x-patch, Size: 63834 bytes --]



	* gimple.h: Move some prototypes to gimple-expr.h and add to include
	list.
	(extract_ops_from_tree, gimple_call_addr_fndecl, is_gimple_reg_type):
	Move to gimple-expr.h.
	* gimple-expr.h: New file.  Relocate some prototypes from gimple.h.
	(types_compatible_p, is_gimple_reg_type, is_gimple_variable,
	is_gimple_id, virtual_operand_p, is_gimple_addressable,
	is_gimple_constant, extract_ops_from_tree, gimple_call_addr_fndecl):
	Relocate here.
	* gimple.c (extract_ops_from_tree_1, gimple_cond_get_ops_from_tree,
	gimple_set_body, gimple_body, gimple_has_body_p, is_gimple_lvalue,
	is_gimple_condexpr, is_gimple_addressable, is_gimple_constant,
	is_gimple_address, is_gimple_invariant_address,
	is_gimple_ip_invariant_address, is_gimple_min_invariant,
	is_gimple_ip_invariant, is_gimple_variable, is_gimple_id,
	virtual_operand_p, is_gimple_reg, is_gimple_val, is_gimple_asm_val,
	is_gimple_min_lval, is_gimple_call_addr, is_gimple_mem_ref_addr,
	gimple_decl_printable_name, useless_type_conversion_p,
	types_compatible_p, gimple_can_coalesce_p, copy_var_decl): Move to 
	gimple-expr.[ch].
	* gimple-expr.c: New File.
	(useless_type_conversion_p, gimple_set_body, gimple_body,
	gimple_has_body_p, gimple_decl_printable_name, copy_var_decl,
	gimple_can_coalesce_p, extract_ops_from_tree_1, 
	gimple_cond_get_ops_from_tree, is_gimple_lvalue, is_gimple_condexpr,
	is_gimple_address, is_gimple_invariant_address,
	is_gimple_ip_invariant_address, is_gimple_min_invariant,
	is_gimple_ip_invariant, is_gimple_reg, is_gimple_val,
	is_gimple_asm_val, is_gimple_min_lval, is_gimple_call_addr,
	is_gimple_mem_ref_addr): Relocate here.
	* Makefile.in (OBJS): Add gimple-expr.o.

Index: gimple.h
===================================================================
*** gimple.h	(revision 204350)
--- gimple.h	(working copy)
*************** along with GCC; see the file COPYING3.
*** 31,36 ****
--- 31,37 ----
  #include "internal-fn.h"
  #include "gimple-fold.h"
  #include "tree-eh.h"
+ #include "gimple-expr.h"
  
  typedef gimple gimple_seq_node;
  
*************** gimple gimple_build_return (tree);
*** 745,752 ****
  gimple gimple_build_assign_stat (tree, tree MEM_STAT_DECL);
  #define gimple_build_assign(l,r) gimple_build_assign_stat (l, r MEM_STAT_INFO)
  
- void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *, tree *);
- 
  gimple
  gimple_build_assign_with_ops (enum tree_code, tree,
  			      tree, tree CXX_MEM_STAT_INFO);
--- 746,751 ----
*************** gimple gimple_build_predict (enum br_pre
*** 809,817 ****
  enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
  void sort_case_labels (vec<tree> );
  void preprocess_case_label_vec_for_gimple (vec<tree> , tree, tree *);
- void gimple_set_body (tree, gimple_seq);
- gimple_seq gimple_body (tree);
- bool gimple_has_body_p (tree);
  gimple_seq gimple_seq_alloc (void);
  void gimple_seq_free (gimple_seq);
  void gimple_seq_add_seq (gimple_seq *, gimple_seq);
--- 808,813 ----
*************** tree gimple_get_lhs (const_gimple);
*** 832,838 ****
  void gimple_set_lhs (gimple, tree);
  void gimple_replace_lhs (gimple, tree);
  gimple gimple_copy (gimple);
- void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *, tree *);
  gimple gimple_build_cond_from_tree (tree, tree, tree);
  void gimple_cond_set_condition_from_tree (gimple, tree);
  bool gimple_has_side_effects (const_gimple);
--- 828,833 ----
*************** bool empty_body_p (gimple_seq);
*** 844,891 ****
  unsigned get_gimple_rhs_num_ops (enum tree_code);
  #define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO)
  gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
- const char *gimple_decl_printable_name (tree, int);
- 
- /* Returns true iff T is a virtual ssa name decl.  */
- extern bool virtual_operand_p (tree);
- /* Returns true iff T is a scalar register variable.  */
- extern bool is_gimple_reg (tree);
- /* Returns true iff T is any sort of variable.  */
- extern bool is_gimple_variable (tree);
- /* Returns true iff T is any sort of symbol.  */
- extern bool is_gimple_id (tree);
- /* Returns true iff T is a variable or an INDIRECT_REF (of a variable).  */
- extern bool is_gimple_min_lval (tree);
- /* Returns true iff T is something whose address can be taken.  */
- extern bool is_gimple_addressable (tree);
- /* Returns true iff T is any valid GIMPLE lvalue.  */
- extern bool is_gimple_lvalue (tree);
- 
- /* Returns true iff T is a GIMPLE address.  */
- bool is_gimple_address (const_tree);
- /* Returns true iff T is a GIMPLE invariant address.  */
- bool is_gimple_invariant_address (const_tree);
- /* Returns true iff T is a GIMPLE invariant address at interprocedural
-    level.  */
- bool is_gimple_ip_invariant_address (const_tree);
- /* Returns true iff T is a valid GIMPLE constant.  */
- bool is_gimple_constant (const_tree);
- /* Returns true iff T is a GIMPLE restricted function invariant.  */
- extern bool is_gimple_min_invariant (const_tree);
- /* Returns true iff T is a GIMPLE restricted interprecodural invariant.  */
- extern bool is_gimple_ip_invariant (const_tree);
- /* Returns true iff T is a GIMPLE rvalue.  */
- extern bool is_gimple_val (tree);
- /* Returns true iff T is a GIMPLE asm statement input.  */
- extern bool is_gimple_asm_val (tree);
- /* Returns true iff T is a valid address operand of a MEM_REF.  */
- bool is_gimple_mem_ref_addr (tree);
- 
- /* Returns true iff T is a valid if-statement condition.  */
- extern bool is_gimple_condexpr (tree);
- 
- /* Returns true iff T is a valid call address expression.  */
- extern bool is_gimple_call_addr (tree);
  
  /* Return TRUE iff stmt is a call to a built-in function.  */
  extern bool is_gimple_builtin_call (gimple stmt);
--- 839,844 ----
*************** extern bool gimple_ior_addresses_taken (
*** 906,913 ****
  extern bool gimple_call_builtin_p (gimple, enum built_in_class);
  extern bool gimple_call_builtin_p (gimple, enum built_in_function);
  extern bool gimple_asm_clobbers_memory_p (const_gimple);
- extern bool useless_type_conversion_p (tree, tree);
- extern bool types_compatible_p (tree, tree);
  
  /* In gimplify.c  */
  extern tree create_tmp_var_raw (tree, const char *);
--- 859,864 ----
*************** extern tree gimple_boolify (tree);
*** 1086,1094 ****
  extern gimple_predicate rhs_predicate_for (tree);
  extern tree canonicalize_cond_expr_cond (tree);
  extern void dump_decl_set (FILE *, bitmap);
- extern bool gimple_can_coalesce_p (tree, tree);
  extern bool nonfreeing_call_p (gimple);
- extern tree copy_var_decl (tree, tree, tree);
  
  /* In trans-mem.c.  */
  extern void diagnose_tm_safe_errors (tree);
--- 1037,1043 ----
*************** gimple_assign_set_rhs_with_ops (gimple_s
*** 2042,2059 ****
    gimple_assign_set_rhs_with_ops_1 (gsi, code, op1, op2, NULL);
  }
  
- /* A wrapper around extract_ops_from_tree_1, for callers which expect
-    to see only a maximum of two operands.  */
- 
- static inline void
- extract_ops_from_tree (tree expr, enum tree_code *code, tree *op0,
- 		       tree *op1)
- {
-   tree op2;
-   extract_ops_from_tree_1 (expr, code, op0, op1, &op2);
-   gcc_assert (op2 == NULL_TREE);
- }
- 
  /* Returns true if GS is a nontemporal move.  */
  
  static inline bool
--- 1991,1996 ----
*************** gimple_call_set_internal_fn (gimple gs,
*** 2316,2340 ****
  }
  
  
- /* Given a valid GIMPLE_CALL function address return the FUNCTION_DECL
-    associated with the callee if known.  Otherwise return NULL_TREE.  */
- 
- static inline tree
- gimple_call_addr_fndecl (const_tree fn)
- {
-   if (fn && TREE_CODE (fn) == ADDR_EXPR)
-     {
-       tree fndecl = TREE_OPERAND (fn, 0);
-       if (TREE_CODE (fndecl) == MEM_REF
- 	  && TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
- 	  && integer_zerop (TREE_OPERAND (fndecl, 1)))
- 	fndecl = TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
-       if (TREE_CODE (fndecl) == FUNCTION_DECL)
- 	return fndecl;
-     }
-   return NULL_TREE;
- }
- 
  /* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
     Otherwise return NULL.  This function is analogous to
     get_callee_fndecl in tree land.  */
--- 2253,2258 ----
*************** gimple_expr_type (const_gimple stmt)
*** 5398,5411 ****
      return void_type_node;
  }
  
- /* Return true if TYPE is a suitable type for a scalar register variable.  */
- 
- static inline bool
- is_gimple_reg_type (tree type)
- {
-   return !AGGREGATE_TYPE_P (type);
- }
- 
  /* Return a new iterator pointing to GIMPLE_SEQ's first statement.  */
  
  static inline gimple_stmt_iterator
--- 5316,5321 ----
Index: gimple-expr.h
===================================================================
*** gimple-expr.h	(revision 0)
--- gimple-expr.h	(working copy)
***************
*** 0 ****
--- 1,171 ----
+ /* Header file for gimple decl, type and expressions.
+    Copyright (C) 2013 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_GIMPLE_EXPR_H
+ #define GCC_GIMPLE_EXPR_H
+ 
+ extern bool useless_type_conversion_p (tree, tree);
+ 
+ extern void gimple_set_body (tree, gimple_seq);
+ extern gimple_seq gimple_body (tree);
+ extern bool gimple_has_body_p (tree);
+ extern const char *gimple_decl_printable_name (tree, int);
+ extern tree copy_var_decl (tree, tree, tree);
+ extern bool gimple_can_coalesce_p (tree, tree);
+ 
+ extern void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *,
+ 				     tree *);
+ extern void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *,
+ 					   tree *);
+ extern bool is_gimple_lvalue (tree);
+ extern bool is_gimple_condexpr (tree);
+ extern bool is_gimple_address (const_tree);
+ extern bool is_gimple_invariant_address (const_tree);
+ extern bool is_gimple_ip_invariant_address (const_tree);
+ extern bool is_gimple_min_invariant (const_tree);
+ extern bool is_gimple_ip_invariant (const_tree);
+ extern bool is_gimple_reg (tree);
+ extern bool is_gimple_val (tree);
+ extern bool is_gimple_asm_val (tree);
+ extern bool is_gimple_min_lval (tree);
+ extern bool is_gimple_call_addr (tree);
+ extern bool is_gimple_mem_ref_addr (tree);
+ 
+ /* Return true if a conversion from either type of TYPE1 and TYPE2
+    to the other is not required.  Otherwise return false.  */
+ 
+ static inline bool
+ types_compatible_p (tree type1, tree type2)
+ {
+   return (type1 == type2
+ 	  || (useless_type_conversion_p (type1, type2)
+ 	      && useless_type_conversion_p (type2, type1)));
+ }
+ 
+ /* Return true if TYPE is a suitable type for a scalar register variable.  */
+ 
+ static inline bool
+ is_gimple_reg_type (tree type)
+ {
+   return !AGGREGATE_TYPE_P (type);
+ }
+ 
+ /* Return true if T is a variable.  */
+ 
+ static inline bool
+ is_gimple_variable (tree t)
+ {
+   return (TREE_CODE (t) == VAR_DECL
+ 	  || TREE_CODE (t) == PARM_DECL
+ 	  || TREE_CODE (t) == RESULT_DECL
+ 	  || TREE_CODE (t) == SSA_NAME);
+ }
+ 
+ /*  Return true if T is a GIMPLE identifier (something with an address).  */
+ 
+ static inline bool
+ is_gimple_id (tree t)
+ {
+   return (is_gimple_variable (t)
+ 	  || TREE_CODE (t) == FUNCTION_DECL
+ 	  || TREE_CODE (t) == LABEL_DECL
+ 	  || TREE_CODE (t) == CONST_DECL
+ 	  /* Allow string constants, since they are addressable.  */
+ 	  || TREE_CODE (t) == STRING_CST);
+ }
+ 
+ /* Return true if OP, an SSA name or a DECL is a virtual operand.  */
+ 
+ static inline bool
+ virtual_operand_p (tree op)
+ {
+   if (TREE_CODE (op) == SSA_NAME)
+     {
+       op = SSA_NAME_VAR (op);
+       if (!op)
+ 	return false;
+     }
+ 
+   if (TREE_CODE (op) == VAR_DECL)
+     return VAR_DECL_IS_VIRTUAL_OPERAND (op);
+ 
+   return false;
+ }
+ 
+ /*  Return true if T is something whose address can be taken.  */
+ 
+ static inline bool
+ is_gimple_addressable (tree t)
+ {
+   return (is_gimple_id (t) || handled_component_p (t)
+ 	  || TREE_CODE (t) == MEM_REF);
+ }
+ 
+ /* Return true if T is a valid gimple constant.  */
+ 
+ static inline bool
+ is_gimple_constant (const_tree t)
+ {
+   switch (TREE_CODE (t))
+     {
+     case INTEGER_CST:
+     case REAL_CST:
+     case FIXED_CST:
+     case STRING_CST:
+     case COMPLEX_CST:
+     case VECTOR_CST:
+       return true;
+ 
+     default:
+       return false;
+     }
+ }
+ 
+ /* A wrapper around extract_ops_from_tree_1, for callers which expect
+    to see only a maximum of two operands.  */
+ 
+ static inline void
+ extract_ops_from_tree (tree expr, enum tree_code *code, tree *op0,
+ 		       tree *op1)
+ {
+   tree op2;
+   extract_ops_from_tree_1 (expr, code, op0, op1, &op2);
+   gcc_assert (op2 == NULL_TREE);
+ }
+ 
+ /* Given a valid GIMPLE_CALL function address return the FUNCTION_DECL
+    associated with the callee if known.  Otherwise return NULL_TREE.  */
+ 
+ static inline tree
+ gimple_call_addr_fndecl (const_tree fn)
+ {
+   if (fn && TREE_CODE (fn) == ADDR_EXPR)
+     {
+       tree fndecl = TREE_OPERAND (fn, 0);
+       if (TREE_CODE (fndecl) == MEM_REF
+ 	  && TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
+ 	  && integer_zerop (TREE_OPERAND (fndecl, 1)))
+ 	fndecl = TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
+       if (TREE_CODE (fndecl) == FUNCTION_DECL)
+ 	return fndecl;
+     }
+   return NULL_TREE;
+ }
+ 
+ #endif /* GCC_GIMPLE_EXPR_H */
Index: gimple.c
===================================================================
*** gimple.c	(revision 204350)
--- gimple.c	(working copy)
*************** gimple_call_get_nobnd_arg_index (const_g
*** 386,432 ****
  }
  
  
- /* Extract the operands and code for expression EXPR into *SUBCODE_P,
-    *OP1_P, *OP2_P and *OP3_P respectively.  */
- 
- void
- extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p,
- 			 tree *op2_p, tree *op3_p)
- {
-   enum gimple_rhs_class grhs_class;
- 
-   *subcode_p = TREE_CODE (expr);
-   grhs_class = get_gimple_rhs_class (*subcode_p);
- 
-   if (grhs_class == GIMPLE_TERNARY_RHS)
-     {
-       *op1_p = TREE_OPERAND (expr, 0);
-       *op2_p = TREE_OPERAND (expr, 1);
-       *op3_p = TREE_OPERAND (expr, 2);
-     }
-   else if (grhs_class == GIMPLE_BINARY_RHS)
-     {
-       *op1_p = TREE_OPERAND (expr, 0);
-       *op2_p = TREE_OPERAND (expr, 1);
-       *op3_p = NULL_TREE;
-     }
-   else if (grhs_class == GIMPLE_UNARY_RHS)
-     {
-       *op1_p = TREE_OPERAND (expr, 0);
-       *op2_p = NULL_TREE;
-       *op3_p = NULL_TREE;
-     }
-   else if (grhs_class == GIMPLE_SINGLE_RHS)
-     {
-       *op1_p = expr;
-       *op2_p = NULL_TREE;
-       *op3_p = NULL_TREE;
-     }
-   else
-     gcc_unreachable ();
- }
- 
- 
  /* Build a GIMPLE_ASSIGN statement.
  
     LHS of the assignment.
--- 386,391 ----
*************** gimple_build_cond (enum tree_code pred_c
*** 526,562 ****
    return p;
  }
  
- 
- /* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND.  */
- 
- void
- gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
-                                tree *lhs_p, tree *rhs_p)
- {
-   gcc_assert (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
- 	      || TREE_CODE (cond) == TRUTH_NOT_EXPR
- 	      || is_gimple_min_invariant (cond)
- 	      || SSA_VAR_P (cond));
- 
-   extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
- 
-   /* Canonicalize conditionals of the form 'if (!VAL)'.  */
-   if (*code_p == TRUTH_NOT_EXPR)
-     {
-       *code_p = EQ_EXPR;
-       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-       *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
-     }
-   /* Canonicalize conditionals of the form 'if (VAL)'  */
-   else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
-     {
-       *code_p = NE_EXPR;
-       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
-       *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
-     }
- }
- 
- 
  /* Build a GIMPLE_COND statement from the conditional expression tree
     COND.  T_LABEL and F_LABEL are as in gimple_build_cond.  */
  
--- 485,490 ----
*************** walk_gimple_stmt (gimple_stmt_iterator *
*** 1906,1950 ****
  }
  
  
- /* Set sequence SEQ to be the GIMPLE body for function FN.  */
- 
- void
- gimple_set_body (tree fndecl, gimple_seq seq)
- {
-   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
-   if (fn == NULL)
-     {
-       /* If FNDECL still does not have a function structure associated
- 	 with it, then it does not make sense for it to receive a
- 	 GIMPLE body.  */
-       gcc_assert (seq == NULL);
-     }
-   else
-     fn->gimple_body = seq;
- }
- 
- 
- /* Return the body of GIMPLE statements for function FN.  After the
-    CFG pass, the function body doesn't exist anymore because it has
-    been split up into basic blocks.  In this case, it returns
-    NULL.  */
- 
- gimple_seq
- gimple_body (tree fndecl)
- {
-   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
-   return fn ? fn->gimple_body : NULL;
- }
- 
- /* Return true when FNDECL has Gimple body either in unlowered
-    or CFG form.  */
- bool
- gimple_has_body_p (tree fndecl)
- {
-   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
-   return (gimple_body (fndecl) || (fn && fn->cfg));
- }
- 
  /* Return true if calls C1 and C2 are known to go to the same function.  */
  
  bool
--- 1834,1839 ----
*************** const unsigned char gimple_rhs_class_tab
*** 2602,2926 ****
  #undef DEFTREECODE
  #undef END_OF_BASE_TREE_CODES
  
- /* For the definitive definition of GIMPLE, see doc/tree-ssa.texi.  */
- 
- /* Validation of GIMPLE expressions.  */
- 
- /*  Return true if T is a valid LHS for a GIMPLE assignment expression.  */
- 
- bool
- is_gimple_lvalue (tree t)
- {
-   return (is_gimple_addressable (t)
- 	  || TREE_CODE (t) == WITH_SIZE_EXPR
- 	  /* These are complex lvalues, but don't have addresses, so they
- 	     go here.  */
- 	  || TREE_CODE (t) == BIT_FIELD_REF);
- }
- 
- /*  Return true if T is a GIMPLE condition.  */
- 
- bool
- is_gimple_condexpr (tree t)
- {
-   return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
- 				&& !tree_could_throw_p (t)
- 				&& is_gimple_val (TREE_OPERAND (t, 0))
- 				&& is_gimple_val (TREE_OPERAND (t, 1))));
- }
- 
- /*  Return true if T is something whose address can be taken.  */
- 
- bool
- is_gimple_addressable (tree t)
- {
-   return (is_gimple_id (t) || handled_component_p (t)
- 	  || TREE_CODE (t) == MEM_REF);
- }
- 
- /* Return true if T is a valid gimple constant.  */
- 
- bool
- is_gimple_constant (const_tree t)
- {
-   switch (TREE_CODE (t))
-     {
-     case INTEGER_CST:
-     case REAL_CST:
-     case FIXED_CST:
-     case STRING_CST:
-     case COMPLEX_CST:
-     case VECTOR_CST:
-       return true;
- 
-     default:
-       return false;
-     }
- }
- 
- /* Return true if T is a gimple address.  */
- 
- bool
- is_gimple_address (const_tree t)
- {
-   tree op;
- 
-   if (TREE_CODE (t) != ADDR_EXPR)
-     return false;
- 
-   op = TREE_OPERAND (t, 0);
-   while (handled_component_p (op))
-     {
-       if ((TREE_CODE (op) == ARRAY_REF
- 	   || TREE_CODE (op) == ARRAY_RANGE_REF)
- 	  && !is_gimple_val (TREE_OPERAND (op, 1)))
- 	    return false;
- 
-       op = TREE_OPERAND (op, 0);
-     }
- 
-   if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
-     return true;
- 
-   switch (TREE_CODE (op))
-     {
-     case PARM_DECL:
-     case RESULT_DECL:
-     case LABEL_DECL:
-     case FUNCTION_DECL:
-     case VAR_DECL:
-     case CONST_DECL:
-       return true;
- 
-     default:
-       return false;
-     }
- }
- 
- /* Return true if T is a gimple invariant address.  */
- 
- bool
- is_gimple_invariant_address (const_tree t)
- {
-   const_tree op;
- 
-   if (TREE_CODE (t) != ADDR_EXPR)
-     return false;
- 
-   op = strip_invariant_refs (TREE_OPERAND (t, 0));
-   if (!op)
-     return false;
- 
-   if (TREE_CODE (op) == MEM_REF)
-     {
-       const_tree op0 = TREE_OPERAND (op, 0);
-       return (TREE_CODE (op0) == ADDR_EXPR
- 	      && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
- 		  || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
-     }
- 
-   return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
- }
- 
- /* Return true if T is a gimple invariant address at IPA level
-    (so addresses of variables on stack are not allowed).  */
- 
- bool
- is_gimple_ip_invariant_address (const_tree t)
- {
-   const_tree op;
- 
-   if (TREE_CODE (t) != ADDR_EXPR)
-     return false;
- 
-   op = strip_invariant_refs (TREE_OPERAND (t, 0));
-   if (!op)
-     return false;
- 
-   if (TREE_CODE (op) == MEM_REF)
-     {
-       const_tree op0 = TREE_OPERAND (op, 0);
-       return (TREE_CODE (op0) == ADDR_EXPR
- 	      && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
- 		  || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
-     }
- 
-   return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
- }
- 
- /* Return true if T is a GIMPLE minimal invariant.  It's a restricted
-    form of function invariant.  */
- 
- bool
- is_gimple_min_invariant (const_tree t)
- {
-   if (TREE_CODE (t) == ADDR_EXPR)
-     return is_gimple_invariant_address (t);
- 
-   return is_gimple_constant (t);
- }
- 
- /* Return true if T is a GIMPLE interprocedural invariant.  It's a restricted
-    form of gimple minimal invariant.  */
- 
- bool
- is_gimple_ip_invariant (const_tree t)
- {
-   if (TREE_CODE (t) == ADDR_EXPR)
-     return is_gimple_ip_invariant_address (t);
- 
-   return is_gimple_constant (t);
- }
- 
- /* Return true if T is a variable.  */
- 
- bool
- is_gimple_variable (tree t)
- {
-   return (TREE_CODE (t) == VAR_DECL
- 	  || TREE_CODE (t) == PARM_DECL
- 	  || TREE_CODE (t) == RESULT_DECL
- 	  || TREE_CODE (t) == SSA_NAME);
- }
- 
- /*  Return true if T is a GIMPLE identifier (something with an address).  */
- 
- bool
- is_gimple_id (tree t)
- {
-   return (is_gimple_variable (t)
- 	  || TREE_CODE (t) == FUNCTION_DECL
- 	  || TREE_CODE (t) == LABEL_DECL
- 	  || TREE_CODE (t) == CONST_DECL
- 	  /* Allow string constants, since they are addressable.  */
- 	  || TREE_CODE (t) == STRING_CST);
- }
- 
- /* Return true if OP, an SSA name or a DECL is a virtual operand.  */
- 
- bool
- virtual_operand_p (tree op)
- {
-   if (TREE_CODE (op) == SSA_NAME)
-     {
-       op = SSA_NAME_VAR (op);
-       if (!op)
- 	return false;
-     }
- 
-   if (TREE_CODE (op) == VAR_DECL)
-     return VAR_DECL_IS_VIRTUAL_OPERAND (op);
- 
-   return false;
- }
- 
- 
- /* Return true if T is a non-aggregate register variable.  */
- 
- bool
- is_gimple_reg (tree t)
- {
-   if (virtual_operand_p (t))
-     return false;
- 
-   if (TREE_CODE (t) == SSA_NAME)
-     return true;
- 
-   if (!is_gimple_variable (t))
-     return false;
- 
-   if (!is_gimple_reg_type (TREE_TYPE (t)))
-     return false;
- 
-   /* A volatile decl is not acceptable because we can't reuse it as
-      needed.  We need to copy it into a temp first.  */
-   if (TREE_THIS_VOLATILE (t))
-     return false;
- 
-   /* We define "registers" as things that can be renamed as needed,
-      which with our infrastructure does not apply to memory.  */
-   if (needs_to_live_in_memory (t))
-     return false;
- 
-   /* Hard register variables are an interesting case.  For those that
-      are call-clobbered, we don't know where all the calls are, since
-      we don't (want to) take into account which operations will turn
-      into libcalls at the rtl level.  For those that are call-saved,
-      we don't currently model the fact that calls may in fact change
-      global hard registers, nor do we examine ASM_CLOBBERS at the tree
-      level, and so miss variable changes that might imply.  All around,
-      it seems safest to not do too much optimization with these at the
-      tree level at all.  We'll have to rely on the rtl optimizers to
-      clean this up, as there we've got all the appropriate bits exposed.  */
-   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
-     return false;
- 
-   /* Complex and vector values must have been put into SSA-like form.
-      That is, no assignments to the individual components.  */
-   if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-       || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-     return DECL_GIMPLE_REG_P (t);
- 
-   return true;
- }
- 
- 
- /* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant.  */
- 
- bool
- is_gimple_val (tree t)
- {
-   /* Make loads from volatiles and memory vars explicit.  */
-   if (is_gimple_variable (t)
-       && is_gimple_reg_type (TREE_TYPE (t))
-       && !is_gimple_reg (t))
-     return false;
- 
-   return (is_gimple_variable (t) || is_gimple_min_invariant (t));
- }
- 
- /* Similarly, but accept hard registers as inputs to asm statements.  */
- 
- bool
- is_gimple_asm_val (tree t)
- {
-   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
-     return true;
- 
-   return is_gimple_val (t);
- }
- 
- /* Return true if T is a GIMPLE minimal lvalue.  */
- 
- bool
- is_gimple_min_lval (tree t)
- {
-   if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
-     return false;
-   return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
- }
- 
- /* Return true if T is a valid function operand of a CALL_EXPR.  */
- 
- bool
- is_gimple_call_addr (tree t)
- {
-   return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
- }
- 
- /* Return true if T is a valid address operand of a MEM_REF.  */
- 
- bool
- is_gimple_mem_ref_addr (tree t)
- {
-   return (is_gimple_reg (t)
- 	  || TREE_CODE (t) == INTEGER_CST
- 	  || (TREE_CODE (t) == ADDR_EXPR
- 	      && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
- 		  || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
- }
- 
- 
  /* Given a memory reference expression T, return its base address.
     The base address of a memory reference expression is the main
     object being referenced.  For instance, the base address for
--- 2491,2496 ----
*************** gimple_ior_addresses_taken (bitmap addre
*** 3642,3678 ****
  }
  
  
- /* Return a printable name for symbol DECL.  */
- 
- const char *
- gimple_decl_printable_name (tree decl, int verbosity)
- {
-   if (!DECL_NAME (decl))
-     return NULL;
- 
-   if (DECL_ASSEMBLER_NAME_SET_P (decl))
-     {
-       const char *str, *mangled_str;
-       int dmgl_opts = DMGL_NO_OPTS;
- 
-       if (verbosity >= 2)
- 	{
- 	  dmgl_opts = DMGL_VERBOSE
- 		      | DMGL_ANSI
- 		      | DMGL_GNU_V3
- 		      | DMGL_RET_POSTFIX;
- 	  if (TREE_CODE (decl) == FUNCTION_DECL)
- 	    dmgl_opts |= DMGL_PARAMS;
- 	}
- 
-       mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-       str = cplus_demangle_v3 (mangled_str, dmgl_opts);
-       return (str) ? str : mangled_str;
-     }
- 
-   return IDENTIFIER_POINTER (DECL_NAME (decl));
- }
- 
  /* Return TRUE iff stmt is a call to a built-in function.  */
  
  bool
--- 3212,3217 ----
*************** gimple_asm_clobbers_memory_p (const_gimp
*** 3763,4023 ****
    return false;
  }
  
- 
- /* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
-    useless type conversion, otherwise return false.
- 
-    This function implicitly defines the middle-end type system.  With
-    the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
-    holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
-    the following invariants shall be fulfilled:
- 
-      1) useless_type_conversion_p is transitive.
- 	If a < b and b < c then a < c.
- 
-      2) useless_type_conversion_p is not symmetric.
- 	From a < b does not follow a > b.
- 
-      3) Types define the available set of operations applicable to values.
- 	A type conversion is useless if the operations for the target type
- 	is a subset of the operations for the source type.  For example
- 	casts to void* are useless, casts from void* are not (void* can't
- 	be dereferenced or offsetted, but copied, hence its set of operations
- 	is a strict subset of that of all other data pointer types).  Casts
- 	to const T* are useless (can't be written to), casts from const T*
- 	to T* are not.  */
- 
- bool
- useless_type_conversion_p (tree outer_type, tree inner_type)
- {
-   /* Do the following before stripping toplevel qualifiers.  */
-   if (POINTER_TYPE_P (inner_type)
-       && POINTER_TYPE_P (outer_type))
-     {
-       /* Do not lose casts between pointers to different address spaces.  */
-       if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
- 	  != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
- 	return false;
-     }
- 
-   /* From now on qualifiers on value types do not matter.  */
-   inner_type = TYPE_MAIN_VARIANT (inner_type);
-   outer_type = TYPE_MAIN_VARIANT (outer_type);
- 
-   if (inner_type == outer_type)
-     return true;
- 
-   /* If we know the canonical types, compare them.  */
-   if (TYPE_CANONICAL (inner_type)
-       && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type))
-     return true;
- 
-   /* Changes in machine mode are never useless conversions unless we
-      deal with aggregate types in which case we defer to later checks.  */
-   if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type)
-       && !AGGREGATE_TYPE_P (inner_type))
-     return false;
- 
-   /* If both the inner and outer types are integral types, then the
-      conversion is not necessary if they have the same mode and
-      signedness and precision, and both or neither are boolean.  */
-   if (INTEGRAL_TYPE_P (inner_type)
-       && INTEGRAL_TYPE_P (outer_type))
-     {
-       /* Preserve changes in signedness or precision.  */
-       if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
- 	  || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
- 	return false;
- 
-       /* Preserve conversions to/from BOOLEAN_TYPE if types are not
- 	 of precision one.  */
-       if (((TREE_CODE (inner_type) == BOOLEAN_TYPE)
- 	   != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
- 	  && TYPE_PRECISION (outer_type) != 1)
- 	return false;
- 
-       /* We don't need to preserve changes in the types minimum or
- 	 maximum value in general as these do not generate code
- 	 unless the types precisions are different.  */
-       return true;
-     }
- 
-   /* Scalar floating point types with the same mode are compatible.  */
-   else if (SCALAR_FLOAT_TYPE_P (inner_type)
- 	   && SCALAR_FLOAT_TYPE_P (outer_type))
-     return true;
- 
-   /* Fixed point types with the same mode are compatible.  */
-   else if (FIXED_POINT_TYPE_P (inner_type)
- 	   && FIXED_POINT_TYPE_P (outer_type))
-     return true;
- 
-   /* We need to take special care recursing to pointed-to types.  */
-   else if (POINTER_TYPE_P (inner_type)
- 	   && POINTER_TYPE_P (outer_type))
-     {
-       /* Do not lose casts to function pointer types.  */
-       if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
- 	   || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
- 	  && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
- 	       || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
- 	return false;
- 
-       /* We do not care for const qualification of the pointed-to types
- 	 as const qualification has no semantic value to the middle-end.  */
- 
-       /* Otherwise pointers/references are equivalent.  */
-       return true;
-     }
- 
-   /* Recurse for complex types.  */
-   else if (TREE_CODE (inner_type) == COMPLEX_TYPE
- 	   && TREE_CODE (outer_type) == COMPLEX_TYPE)
-     return useless_type_conversion_p (TREE_TYPE (outer_type),
- 				      TREE_TYPE (inner_type));
- 
-   /* Recurse for vector types with the same number of subparts.  */
-   else if (TREE_CODE (inner_type) == VECTOR_TYPE
- 	   && TREE_CODE (outer_type) == VECTOR_TYPE
- 	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
-     return useless_type_conversion_p (TREE_TYPE (outer_type),
- 				      TREE_TYPE (inner_type));
- 
-   else if (TREE_CODE (inner_type) == ARRAY_TYPE
- 	   && TREE_CODE (outer_type) == ARRAY_TYPE)
-     {
-       /* Preserve string attributes.  */
-       if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
- 	return false;
- 
-       /* Conversions from array types with unknown extent to
- 	 array types with known extent are not useless.  */
-       if (!TYPE_DOMAIN (inner_type)
- 	  && TYPE_DOMAIN (outer_type))
- 	return false;
- 
-       /* Nor are conversions from array types with non-constant size to
-          array types with constant size or to different size.  */
-       if (TYPE_SIZE (outer_type)
- 	  && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
- 	  && (!TYPE_SIZE (inner_type)
- 	      || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
- 	      || !tree_int_cst_equal (TYPE_SIZE (outer_type),
- 				      TYPE_SIZE (inner_type))))
- 	return false;
- 
-       /* Check conversions between arrays with partially known extents.
- 	 If the array min/max values are constant they have to match.
- 	 Otherwise allow conversions to unknown and variable extents.
- 	 In particular this declares conversions that may change the
- 	 mode to BLKmode as useless.  */
-       if (TYPE_DOMAIN (inner_type)
- 	  && TYPE_DOMAIN (outer_type)
- 	  && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
- 	{
- 	  tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
- 	  tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
- 	  tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
- 	  tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));
- 
- 	  /* After gimplification a variable min/max value carries no
- 	     additional information compared to a NULL value.  All that
- 	     matters has been lowered to be part of the IL.  */
- 	  if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
- 	    inner_min = NULL_TREE;
- 	  if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
- 	    outer_min = NULL_TREE;
- 	  if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
- 	    inner_max = NULL_TREE;
- 	  if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
- 	    outer_max = NULL_TREE;
- 
- 	  /* Conversions NULL / variable <- cst are useless, but not
- 	     the other way around.  */
- 	  if (outer_min
- 	      && (!inner_min
- 		  || !tree_int_cst_equal (inner_min, outer_min)))
- 	    return false;
- 	  if (outer_max
- 	      && (!inner_max
- 		  || !tree_int_cst_equal (inner_max, outer_max)))
- 	    return false;
- 	}
- 
-       /* Recurse on the element check.  */
-       return useless_type_conversion_p (TREE_TYPE (outer_type),
- 					TREE_TYPE (inner_type));
-     }
- 
-   else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
- 	    || TREE_CODE (inner_type) == METHOD_TYPE)
- 	   && TREE_CODE (inner_type) == TREE_CODE (outer_type))
-     {
-       tree outer_parm, inner_parm;
- 
-       /* If the return types are not compatible bail out.  */
-       if (!useless_type_conversion_p (TREE_TYPE (outer_type),
- 				      TREE_TYPE (inner_type)))
- 	return false;
- 
-       /* Method types should belong to a compatible base class.  */
-       if (TREE_CODE (inner_type) == METHOD_TYPE
- 	  && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
- 					 TYPE_METHOD_BASETYPE (inner_type)))
- 	return false;
- 
-       /* A conversion to an unprototyped argument list is ok.  */
-       if (!prototype_p (outer_type))
- 	return true;
- 
-       /* If the unqualified argument types are compatible the conversion
- 	 is useless.  */
-       if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
- 	return true;
- 
-       for (outer_parm = TYPE_ARG_TYPES (outer_type),
- 	   inner_parm = TYPE_ARG_TYPES (inner_type);
- 	   outer_parm && inner_parm;
- 	   outer_parm = TREE_CHAIN (outer_parm),
- 	   inner_parm = TREE_CHAIN (inner_parm))
- 	if (!useless_type_conversion_p
- 	       (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)),
- 		TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm))))
- 	  return false;
- 
-       /* If there is a mismatch in the number of arguments the functions
- 	 are not compatible.  */
-       if (outer_parm || inner_parm)
- 	return false;
- 
-       /* Defer to the target if necessary.  */
-       if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
- 	return comp_type_attributes (outer_type, inner_type) != 0;
- 
-       return true;
-     }
- 
-   /* For aggregates we rely on TYPE_CANONICAL exclusively and require
-      explicit conversions for types involving to be structurally
-      compared types.  */
-   else if (AGGREGATE_TYPE_P (inner_type)
- 	   && TREE_CODE (inner_type) == TREE_CODE (outer_type))
-     return false;
- 
-   return false;
- }
- 
- /* Return true if a conversion from either type of TYPE1 and TYPE2
-    to the other is not required.  Otherwise return false.  */
- 
- bool
- types_compatible_p (tree type1, tree type2)
- {
-   return (type1 == type2
- 	  || (useless_type_conversion_p (type1, type2)
- 	      && useless_type_conversion_p (type2, type1)));
- }
- 
  /* Dump bitmap SET (assumed to contain VAR_DECLs) to FILE.  */
  
  void
--- 3302,3307 ----
*************** dump_decl_set (FILE *file, bitmap set)
*** 4042,4086 ****
      fprintf (file, "NIL");
  }
  
- /* Given SSA_NAMEs NAME1 and NAME2, return true if they are candidates for
-    coalescing together, false otherwise.
- 
-    This must stay consistent with var_map_base_init in tree-ssa-live.c.  */
- 
- bool
- gimple_can_coalesce_p (tree name1, tree name2)
- {
-   /* First check the SSA_NAME's associated DECL.  We only want to
-      coalesce if they have the same DECL or both have no associated DECL.  */
-   tree var1 = SSA_NAME_VAR (name1);
-   tree var2 = SSA_NAME_VAR (name2);
-   var1 = (var1 && (!VAR_P (var1) || !DECL_IGNORED_P (var1))) ? var1 : NULL_TREE;
-   var2 = (var2 && (!VAR_P (var2) || !DECL_IGNORED_P (var2))) ? var2 : NULL_TREE;
-   if (var1 != var2)
-     return false;
- 
-   /* Now check the types.  If the types are the same, then we should
-      try to coalesce V1 and V2.  */
-   tree t1 = TREE_TYPE (name1);
-   tree t2 = TREE_TYPE (name2);
-   if (t1 == t2)
-     return true;
- 
-   /* If the types are not the same, check for a canonical type match.  This
-      (for example) allows coalescing when the types are fundamentally the
-      same, but just have different names. 
- 
-      Note pointer types with different address spaces may have the same
-      canonical type.  Those are rejected for coalescing by the
-      types_compatible_p check.  */
-   if (TYPE_CANONICAL (t1)
-       && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)
-       && types_compatible_p (t1, t2))
-     return true;
- 
-   return false;
- }
- 
  /* Return true when CALL is a call stmt that definitely doesn't
     free any memory or makes it unavailable otherwise.  */
  bool
--- 3326,3331 ----
*************** nonfreeing_call_p (gimple call)
*** 4102,4125 ****
  
    return false;
  }
- 
- /* Create a new VAR_DECL and copy information from VAR to it.  */
- 
- tree
- copy_var_decl (tree var, tree name, tree type)
- {
-   tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
- 
-   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
-   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
-   DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
-   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
-   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
-   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
-   TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
-   TREE_USED (copy) = 1;
-   DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
-   DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
- 
-   return copy;
- }
--- 3347,3349 ----
Index: gimple-expr.c
===================================================================
*** gimple-expr.c	(revision 0)
--- gimple-expr.c	(working copy)
***************
*** 0 ****
--- 1,721 ----
+ /* Gimple decl, type, and expression support functions.
+ 
+    Copyright (C) 2007-2013 Free Software Foundation, Inc.
+    Contributed by Aldy Hernandez <aldyh@redhat.com>
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "tree.h"
+ #include "gimple.h"
+ #include "demangle.h"
+ 
+ /* ----- Type related -----  */
+ 
+ /* Return true if the conversion from INNER_TYPE to OUTER_TYPE is a
+    useless type conversion, otherwise return false.
+ 
+    This function implicitly defines the middle-end type system.  With
+    the notion of 'a < b' meaning that useless_type_conversion_p (a, b)
+    holds and 'a > b' meaning that useless_type_conversion_p (b, a) holds,
+    the following invariants shall be fulfilled:
+ 
+      1) useless_type_conversion_p is transitive.
+ 	If a < b and b < c then a < c.
+ 
+      2) useless_type_conversion_p is not symmetric.
+ 	From a < b does not follow a > b.
+ 
+      3) Types define the available set of operations applicable to values.
+ 	A type conversion is useless if the operations for the target type
+ 	is a subset of the operations for the source type.  For example
+ 	casts to void* are useless, casts from void* are not (void* can't
+ 	be dereferenced or offsetted, but copied, hence its set of operations
+ 	is a strict subset of that of all other data pointer types).  Casts
+ 	to const T* are useless (can't be written to), casts from const T*
+ 	to T* are not.  */
+ 
+ bool
+ useless_type_conversion_p (tree outer_type, tree inner_type)
+ {
+   /* Do the following before stripping toplevel qualifiers.  */
+   if (POINTER_TYPE_P (inner_type)
+       && POINTER_TYPE_P (outer_type))
+     {
+       /* Do not lose casts between pointers to different address spaces.  */
+       if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
+ 	  != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
+ 	return false;
+     }
+ 
+   /* From now on qualifiers on value types do not matter.  */
+   inner_type = TYPE_MAIN_VARIANT (inner_type);
+   outer_type = TYPE_MAIN_VARIANT (outer_type);
+ 
+   if (inner_type == outer_type)
+     return true;
+ 
+   /* If we know the canonical types, compare them.  */
+   if (TYPE_CANONICAL (inner_type)
+       && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type))
+     return true;
+ 
+   /* Changes in machine mode are never useless conversions unless we
+      deal with aggregate types in which case we defer to later checks.  */
+   if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type)
+       && !AGGREGATE_TYPE_P (inner_type))
+     return false;
+ 
+   /* If both the inner and outer types are integral types, then the
+      conversion is not necessary if they have the same mode and
+      signedness and precision, and both or neither are boolean.  */
+   if (INTEGRAL_TYPE_P (inner_type)
+       && INTEGRAL_TYPE_P (outer_type))
+     {
+       /* Preserve changes in signedness or precision.  */
+       if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
+ 	  || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
+ 	return false;
+ 
+       /* Preserve conversions to/from BOOLEAN_TYPE if types are not
+ 	 of precision one.  */
+       if (((TREE_CODE (inner_type) == BOOLEAN_TYPE)
+ 	   != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
+ 	  && TYPE_PRECISION (outer_type) != 1)
+ 	return false;
+ 
+       /* We don't need to preserve changes in the types minimum or
+ 	 maximum value in general as these do not generate code
+ 	 unless the types precisions are different.  */
+       return true;
+     }
+ 
+   /* Scalar floating point types with the same mode are compatible.  */
+   else if (SCALAR_FLOAT_TYPE_P (inner_type)
+ 	   && SCALAR_FLOAT_TYPE_P (outer_type))
+     return true;
+ 
+   /* Fixed point types with the same mode are compatible.  */
+   else if (FIXED_POINT_TYPE_P (inner_type)
+ 	   && FIXED_POINT_TYPE_P (outer_type))
+     return true;
+ 
+   /* We need to take special care recursing to pointed-to types.  */
+   else if (POINTER_TYPE_P (inner_type)
+ 	   && POINTER_TYPE_P (outer_type))
+     {
+       /* Do not lose casts to function pointer types.  */
+       if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
+ 	   || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
+ 	  && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
+ 	       || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
+ 	return false;
+ 
+       /* We do not care for const qualification of the pointed-to types
+ 	 as const qualification has no semantic value to the middle-end.  */
+ 
+       /* Otherwise pointers/references are equivalent.  */
+       return true;
+     }
+ 
+   /* Recurse for complex types.  */
+   else if (TREE_CODE (inner_type) == COMPLEX_TYPE
+ 	   && TREE_CODE (outer_type) == COMPLEX_TYPE)
+     return useless_type_conversion_p (TREE_TYPE (outer_type),
+ 				      TREE_TYPE (inner_type));
+ 
+   /* Recurse for vector types with the same number of subparts.  */
+   else if (TREE_CODE (inner_type) == VECTOR_TYPE
+ 	   && TREE_CODE (outer_type) == VECTOR_TYPE
+ 	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
+     return useless_type_conversion_p (TREE_TYPE (outer_type),
+ 				      TREE_TYPE (inner_type));
+ 
+   else if (TREE_CODE (inner_type) == ARRAY_TYPE
+ 	   && TREE_CODE (outer_type) == ARRAY_TYPE)
+     {
+       /* Preserve string attributes.  */
+       if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
+ 	return false;
+ 
+       /* Conversions from array types with unknown extent to
+ 	 array types with known extent are not useless.  */
+       if (!TYPE_DOMAIN (inner_type)
+ 	  && TYPE_DOMAIN (outer_type))
+ 	return false;
+ 
+       /* Nor are conversions from array types with non-constant size to
+          array types with constant size or to different size.  */
+       if (TYPE_SIZE (outer_type)
+ 	  && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
+ 	  && (!TYPE_SIZE (inner_type)
+ 	      || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
+ 	      || !tree_int_cst_equal (TYPE_SIZE (outer_type),
+ 				      TYPE_SIZE (inner_type))))
+ 	return false;
+ 
+       /* Check conversions between arrays with partially known extents.
+ 	 If the array min/max values are constant they have to match.
+ 	 Otherwise allow conversions to unknown and variable extents.
+ 	 In particular this declares conversions that may change the
+ 	 mode to BLKmode as useless.  */
+       if (TYPE_DOMAIN (inner_type)
+ 	  && TYPE_DOMAIN (outer_type)
+ 	  && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
+ 	{
+ 	  tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
+ 	  tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
+ 	  tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
+ 	  tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));
+ 
+ 	  /* After gimplification a variable min/max value carries no
+ 	     additional information compared to a NULL value.  All that
+ 	     matters has been lowered to be part of the IL.  */
+ 	  if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
+ 	    inner_min = NULL_TREE;
+ 	  if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
+ 	    outer_min = NULL_TREE;
+ 	  if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
+ 	    inner_max = NULL_TREE;
+ 	  if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
+ 	    outer_max = NULL_TREE;
+ 
+ 	  /* Conversions NULL / variable <- cst are useless, but not
+ 	     the other way around.  */
+ 	  if (outer_min
+ 	      && (!inner_min
+ 		  || !tree_int_cst_equal (inner_min, outer_min)))
+ 	    return false;
+ 	  if (outer_max
+ 	      && (!inner_max
+ 		  || !tree_int_cst_equal (inner_max, outer_max)))
+ 	    return false;
+ 	}
+ 
+       /* Recurse on the element check.  */
+       return useless_type_conversion_p (TREE_TYPE (outer_type),
+ 					TREE_TYPE (inner_type));
+     }
+ 
+   else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
+ 	    || TREE_CODE (inner_type) == METHOD_TYPE)
+ 	   && TREE_CODE (inner_type) == TREE_CODE (outer_type))
+     {
+       tree outer_parm, inner_parm;
+ 
+       /* If the return types are not compatible bail out.  */
+       if (!useless_type_conversion_p (TREE_TYPE (outer_type),
+ 				      TREE_TYPE (inner_type)))
+ 	return false;
+ 
+       /* Method types should belong to a compatible base class.  */
+       if (TREE_CODE (inner_type) == METHOD_TYPE
+ 	  && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
+ 					 TYPE_METHOD_BASETYPE (inner_type)))
+ 	return false;
+ 
+       /* A conversion to an unprototyped argument list is ok.  */
+       if (!prototype_p (outer_type))
+ 	return true;
+ 
+       /* If the unqualified argument types are compatible the conversion
+ 	 is useless.  */
+       if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
+ 	return true;
+ 
+       for (outer_parm = TYPE_ARG_TYPES (outer_type),
+ 	   inner_parm = TYPE_ARG_TYPES (inner_type);
+ 	   outer_parm && inner_parm;
+ 	   outer_parm = TREE_CHAIN (outer_parm),
+ 	   inner_parm = TREE_CHAIN (inner_parm))
+ 	if (!useless_type_conversion_p
+ 	       (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)),
+ 		TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm))))
+ 	  return false;
+ 
+       /* If there is a mismatch in the number of arguments the functions
+ 	 are not compatible.  */
+       if (outer_parm || inner_parm)
+ 	return false;
+ 
+       /* Defer to the target if necessary.  */
+       if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
+ 	return comp_type_attributes (outer_type, inner_type) != 0;
+ 
+       return true;
+     }
+ 
+   /* For aggregates we rely on TYPE_CANONICAL exclusively and require
+      explicit conversions for types involving to be structurally
+      compared types.  */
+   else if (AGGREGATE_TYPE_P (inner_type)
+ 	   && TREE_CODE (inner_type) == TREE_CODE (outer_type))
+     return false;
+ 
+   return false;
+ }
+ 
+ 
+ /* ----- Decl related -----  */
+ 
+ /* Set sequence SEQ to be the GIMPLE body for function FN.  */
+ 
+ void
+ gimple_set_body (tree fndecl, gimple_seq seq)
+ {
+   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+   if (fn == NULL)
+     {
+       /* If FNDECL still does not have a function structure associated
+ 	 with it, then it does not make sense for it to receive a
+ 	 GIMPLE body.  */
+       gcc_assert (seq == NULL);
+     }
+   else
+     fn->gimple_body = seq;
+ }
+ 
+ 
+ /* Return the body of GIMPLE statements for function FN.  After the
+    CFG pass, the function body doesn't exist anymore because it has
+    been split up into basic blocks.  In this case, it returns
+    NULL.  */
+ 
+ gimple_seq
+ gimple_body (tree fndecl)
+ {
+   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+   return fn ? fn->gimple_body : NULL;
+ }
+ 
+ /* Return true when FNDECL has Gimple body either in unlowered
+    or CFG form.  */
+ bool
+ gimple_has_body_p (tree fndecl)
+ {
+   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+   return (gimple_body (fndecl) || (fn && fn->cfg));
+ }
+ 
+ /* Return a printable name for symbol DECL.  */
+ 
+ const char *
+ gimple_decl_printable_name (tree decl, int verbosity)
+ {
+   if (!DECL_NAME (decl))
+     return NULL;
+ 
+   if (DECL_ASSEMBLER_NAME_SET_P (decl))
+     {
+       const char *str, *mangled_str;
+       int dmgl_opts = DMGL_NO_OPTS;
+ 
+       if (verbosity >= 2)
+ 	{
+ 	  dmgl_opts = DMGL_VERBOSE
+ 		      | DMGL_ANSI
+ 		      | DMGL_GNU_V3
+ 		      | DMGL_RET_POSTFIX;
+ 	  if (TREE_CODE (decl) == FUNCTION_DECL)
+ 	    dmgl_opts |= DMGL_PARAMS;
+ 	}
+ 
+       mangled_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+       str = cplus_demangle_v3 (mangled_str, dmgl_opts);
+       return (str) ? str : mangled_str;
+     }
+ 
+   return IDENTIFIER_POINTER (DECL_NAME (decl));
+ }
+ 
+ 
+ /* Create a new VAR_DECL and copy information from VAR to it.  */
+ 
+ tree
+ copy_var_decl (tree var, tree name, tree type)
+ {
+   tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
+ 
+   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
+   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
+   DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
+   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
+   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
+   TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
+   TREE_USED (copy) = 1;
+   DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
+   DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
+ 
+   return copy;
+ }
+ 
+ /* Given SSA_NAMEs NAME1 and NAME2, return true if they are candidates for
+    coalescing together, false otherwise.
+ 
+    This must stay consistent with var_map_base_init in tree-ssa-live.c.  */
+ 
+ bool
+ gimple_can_coalesce_p (tree name1, tree name2)
+ {
+   /* First check the SSA_NAME's associated DECL.  We only want to
+      coalesce if they have the same DECL or both have no associated DECL.  */
+   tree var1 = SSA_NAME_VAR (name1);
+   tree var2 = SSA_NAME_VAR (name2);
+   var1 = (var1 && (!VAR_P (var1) || !DECL_IGNORED_P (var1))) ? var1 : NULL_TREE;
+   var2 = (var2 && (!VAR_P (var2) || !DECL_IGNORED_P (var2))) ? var2 : NULL_TREE;
+   if (var1 != var2)
+     return false;
+ 
+   /* Now check the types.  If the types are the same, then we should
+      try to coalesce V1 and V2.  */
+   tree t1 = TREE_TYPE (name1);
+   tree t2 = TREE_TYPE (name2);
+   if (t1 == t2)
+     return true;
+ 
+   /* If the types are not the same, check for a canonical type match.  This
+      (for example) allows coalescing when the types are fundamentally the
+      same, but just have different names. 
+ 
+      Note pointer types with different address spaces may have the same
+      canonical type.  Those are rejected for coalescing by the
+      types_compatible_p check.  */
+   if (TYPE_CANONICAL (t1)
+       && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)
+       && types_compatible_p (t1, t2))
+     return true;
+ 
+   return false;
+ }
+ 
+ 
+ /* ----- Expression related -----  */
+ 
+ /* Extract the operands and code for expression EXPR into *SUBCODE_P,
+    *OP1_P, *OP2_P and *OP3_P respectively.  */
+ 
+ void
+ extract_ops_from_tree_1 (tree expr, enum tree_code *subcode_p, tree *op1_p,
+ 			 tree *op2_p, tree *op3_p)
+ {
+   enum gimple_rhs_class grhs_class;
+ 
+   *subcode_p = TREE_CODE (expr);
+   grhs_class = get_gimple_rhs_class (*subcode_p);
+ 
+   if (grhs_class == GIMPLE_TERNARY_RHS)
+     {
+       *op1_p = TREE_OPERAND (expr, 0);
+       *op2_p = TREE_OPERAND (expr, 1);
+       *op3_p = TREE_OPERAND (expr, 2);
+     }
+   else if (grhs_class == GIMPLE_BINARY_RHS)
+     {
+       *op1_p = TREE_OPERAND (expr, 0);
+       *op2_p = TREE_OPERAND (expr, 1);
+       *op3_p = NULL_TREE;
+     }
+   else if (grhs_class == GIMPLE_UNARY_RHS)
+     {
+       *op1_p = TREE_OPERAND (expr, 0);
+       *op2_p = NULL_TREE;
+       *op3_p = NULL_TREE;
+     }
+   else if (grhs_class == GIMPLE_SINGLE_RHS)
+     {
+       *op1_p = expr;
+       *op2_p = NULL_TREE;
+       *op3_p = NULL_TREE;
+     }
+   else
+     gcc_unreachable ();
+ }
+ 
+ /* Extract operands for a GIMPLE_COND statement out of COND_EXPR tree COND.  */
+ 
+ void
+ gimple_cond_get_ops_from_tree (tree cond, enum tree_code *code_p,
+                                tree *lhs_p, tree *rhs_p)
+ {
+   gcc_assert (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison
+ 	      || TREE_CODE (cond) == TRUTH_NOT_EXPR
+ 	      || is_gimple_min_invariant (cond)
+ 	      || SSA_VAR_P (cond));
+ 
+   extract_ops_from_tree (cond, code_p, lhs_p, rhs_p);
+ 
+   /* Canonicalize conditionals of the form 'if (!VAL)'.  */
+   if (*code_p == TRUTH_NOT_EXPR)
+     {
+       *code_p = EQ_EXPR;
+       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
+       *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
+     }
+   /* Canonicalize conditionals of the form 'if (VAL)'  */
+   else if (TREE_CODE_CLASS (*code_p) != tcc_comparison)
+     {
+       *code_p = NE_EXPR;
+       gcc_assert (*lhs_p && *rhs_p == NULL_TREE);
+       *rhs_p = build_zero_cst (TREE_TYPE (*lhs_p));
+     }
+ }
+ 
+ /*  Return true if T is a valid LHS for a GIMPLE assignment expression.  */
+ 
+ bool
+ is_gimple_lvalue (tree t)
+ {
+   return (is_gimple_addressable (t)
+ 	  || TREE_CODE (t) == WITH_SIZE_EXPR
+ 	  /* These are complex lvalues, but don't have addresses, so they
+ 	     go here.  */
+ 	  || TREE_CODE (t) == BIT_FIELD_REF);
+ }
+ 
+ /*  Return true if T is a GIMPLE condition.  */
+ 
+ bool
+ is_gimple_condexpr (tree t)
+ {
+   return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
+ 				&& !tree_could_throw_p (t)
+ 				&& is_gimple_val (TREE_OPERAND (t, 0))
+ 				&& is_gimple_val (TREE_OPERAND (t, 1))));
+ }
+ 
+ /* Return true if T is a gimple address.  */
+ 
+ bool
+ is_gimple_address (const_tree t)
+ {
+   tree op;
+ 
+   if (TREE_CODE (t) != ADDR_EXPR)
+     return false;
+ 
+   op = TREE_OPERAND (t, 0);
+   while (handled_component_p (op))
+     {
+       if ((TREE_CODE (op) == ARRAY_REF
+ 	   || TREE_CODE (op) == ARRAY_RANGE_REF)
+ 	  && !is_gimple_val (TREE_OPERAND (op, 1)))
+ 	    return false;
+ 
+       op = TREE_OPERAND (op, 0);
+     }
+ 
+   if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF)
+     return true;
+ 
+   switch (TREE_CODE (op))
+     {
+     case PARM_DECL:
+     case RESULT_DECL:
+     case LABEL_DECL:
+     case FUNCTION_DECL:
+     case VAR_DECL:
+     case CONST_DECL:
+       return true;
+ 
+     default:
+       return false;
+     }
+ }
+ 
+ /* Return true if T is a gimple invariant address.  */
+ 
+ bool
+ is_gimple_invariant_address (const_tree t)
+ {
+   const_tree op;
+ 
+   if (TREE_CODE (t) != ADDR_EXPR)
+     return false;
+ 
+   op = strip_invariant_refs (TREE_OPERAND (t, 0));
+   if (!op)
+     return false;
+ 
+   if (TREE_CODE (op) == MEM_REF)
+     {
+       const_tree op0 = TREE_OPERAND (op, 0);
+       return (TREE_CODE (op0) == ADDR_EXPR
+ 	      && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
+ 		  || decl_address_invariant_p (TREE_OPERAND (op0, 0))));
+     }
+ 
+   return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
+ }
+ 
+ /* Return true if T is a gimple invariant address at IPA level
+    (so addresses of variables on stack are not allowed).  */
+ 
+ bool
+ is_gimple_ip_invariant_address (const_tree t)
+ {
+   const_tree op;
+ 
+   if (TREE_CODE (t) != ADDR_EXPR)
+     return false;
+ 
+   op = strip_invariant_refs (TREE_OPERAND (t, 0));
+   if (!op)
+     return false;
+ 
+   if (TREE_CODE (op) == MEM_REF)
+     {
+       const_tree op0 = TREE_OPERAND (op, 0);
+       return (TREE_CODE (op0) == ADDR_EXPR
+ 	      && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))
+ 		  || decl_address_ip_invariant_p (TREE_OPERAND (op0, 0))));
+     }
+ 
+   return CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op);
+ }
+ 
+ /* Return true if T is a GIMPLE minimal invariant.  It's a restricted
+    form of function invariant.  */
+ 
+ bool
+ is_gimple_min_invariant (const_tree t)
+ {
+   if (TREE_CODE (t) == ADDR_EXPR)
+     return is_gimple_invariant_address (t);
+ 
+   return is_gimple_constant (t);
+ }
+ 
+ /* Return true if T is a GIMPLE interprocedural invariant.  It's a restricted
+    form of gimple minimal invariant.  */
+ 
+ bool
+ is_gimple_ip_invariant (const_tree t)
+ {
+   if (TREE_CODE (t) == ADDR_EXPR)
+     return is_gimple_ip_invariant_address (t);
+ 
+   return is_gimple_constant (t);
+ }
+ 
+ /* Return true if T is a non-aggregate register variable.  */
+ 
+ bool
+ is_gimple_reg (tree t)
+ {
+   if (virtual_operand_p (t))
+     return false;
+ 
+   if (TREE_CODE (t) == SSA_NAME)
+     return true;
+ 
+   if (!is_gimple_variable (t))
+     return false;
+ 
+   if (!is_gimple_reg_type (TREE_TYPE (t)))
+     return false;
+ 
+   /* A volatile decl is not acceptable because we can't reuse it as
+      needed.  We need to copy it into a temp first.  */
+   if (TREE_THIS_VOLATILE (t))
+     return false;
+ 
+   /* We define "registers" as things that can be renamed as needed,
+      which with our infrastructure does not apply to memory.  */
+   if (needs_to_live_in_memory (t))
+     return false;
+ 
+   /* Hard register variables are an interesting case.  For those that
+      are call-clobbered, we don't know where all the calls are, since
+      we don't (want to) take into account which operations will turn
+      into libcalls at the rtl level.  For those that are call-saved,
+      we don't currently model the fact that calls may in fact change
+      global hard registers, nor do we examine ASM_CLOBBERS at the tree
+      level, and so miss variable changes that might imply.  All around,
+      it seems safest to not do too much optimization with these at the
+      tree level at all.  We'll have to rely on the rtl optimizers to
+      clean this up, as there we've got all the appropriate bits exposed.  */
+   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
+     return false;
+ 
+   /* Complex and vector values must have been put into SSA-like form.
+      That is, no assignments to the individual components.  */
+   if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+       || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+     return DECL_GIMPLE_REG_P (t);
+ 
+   return true;
+ }
+ 
+ 
+ /* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant.  */
+ 
+ bool
+ is_gimple_val (tree t)
+ {
+   /* Make loads from volatiles and memory vars explicit.  */
+   if (is_gimple_variable (t)
+       && is_gimple_reg_type (TREE_TYPE (t))
+       && !is_gimple_reg (t))
+     return false;
+ 
+   return (is_gimple_variable (t) || is_gimple_min_invariant (t));
+ }
+ 
+ /* Similarly, but accept hard registers as inputs to asm statements.  */
+ 
+ bool
+ is_gimple_asm_val (tree t)
+ {
+   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
+     return true;
+ 
+   return is_gimple_val (t);
+ }
+ 
+ /* Return true if T is a GIMPLE minimal lvalue.  */
+ 
+ bool
+ is_gimple_min_lval (tree t)
+ {
+   if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
+     return false;
+   return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF);
+ }
+ 
+ /* Return true if T is a valid function operand of a CALL_EXPR.  */
+ 
+ bool
+ is_gimple_call_addr (tree t)
+ {
+   return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t));
+ }
+ 
+ /* Return true if T is a valid address operand of a MEM_REF.  */
+ 
+ bool
+ is_gimple_mem_ref_addr (tree t)
+ {
+   return (is_gimple_reg (t)
+ 	  || TREE_CODE (t) == INTEGER_CST
+ 	  || (TREE_CODE (t) == ADDR_EXPR
+ 	      && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0))
+ 		  || decl_address_invariant_p (TREE_OPERAND (t, 0)))));
+ }
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 204350)
--- Makefile.in	(working copy)
*************** OBJS = \
*** 1230,1235 ****
--- 1230,1236 ----
  	ggc-common.o \
  	gimple.o \
  	gimple-builder.o \
+ 	gimple-expr.o \
  	gimple-iterator.o \
  	gimple-fold.o \
  	gimple-low.o \

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

* [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-01 21:36   ` Andrew MacLeod
  2013-11-01 21:41     ` Jakub Jelinek
  2013-11-01 22:43     ` David Malcolm
@ 2013-11-05 17:23     ` David Malcolm
  2013-11-06 16:53       ` Michael Matz
  2013-11-05 18:22     ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) Andrew MacLeod
  3 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-11-05 17:23 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4812 bytes --]

On Fri, 2013-11-01 at 17:36 -0400, Andrew MacLeod wrote:
> On 10/31/2013 12:26 PM, David Malcolm wrote:
> > [Shamelessly hijacking Andrew's thread about gimple.h refactoring,
> > since this seems on-topic for that, and I'm keen to hear from Andrew on
> > how the following would interact with his work - I *think* our two
> > cleanups are orthogonal.
> 
> Mostly orthogonal anyway... just stomping on the same bits :-).
> 
> Since you hijacked a planning thread, do you plan to take this any 
> further, or make this change and move on to something else?
> 
> It is a start, but it doesnt do the rest of the work that needs doing to 
> really take advantage of it... which will be extensive.
> for instance, we should change:
> 
>    static inline void
> ! gimple_call_set_lhs (gimple gs, tree lhs)
>    {
> -   GIMPLE_CHECK (gs, GIMPLE_CALL);
>      gimple_set_op (gs, 0, lhs);
> to
>      static inline void
> ! gimple_call_set_lhs (gimple_statement_call *gs, tree lhs)
>    {
>      gimple_set_op (gs, 0, lhs);
> 
> 
> but then every location that calls it needs an appropriate change:
> 
> !       gimple call;
> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> alias), vargs);
>          gimple_call_set_lhs (call, atree);
> 
> --- 1518,1524 ----
> 
> !       gimple_statement_call *call;
> !       call = as_a<gimple_statement_call> (gimple_build_call_vec 
> (build_fold_addr_expr_loc (0, alias), vargs));
>          gimple_call_set_lhs (call, atree);
> 
> And in fact there is a ripple effect to then change 
> gimple_build_call_vec to simply return a gimple_statement_call *... Then 
> this doesn't look as ugly either...
> 
> !       gimple_statement_call *call;
> !       call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> alias), vargs);
>          gimple_call_set_lhs (call, atree);
> 
> that is looking much better :-)
> 
> 
> Leaving the names as they are should be ok, but the I'd also add a 
> typedef for the pointer without the 'statement' in the name.. ie
>      typedef gimple_statement_call *gimple_call;
> That seems in line with what we do with 'gimple' right now and the short 
> form is the type we'd normally use.
> 
> That adds a touch of difficulty with "as_a", since that requires the 
> type name, not the shorthand pointer.... so you have something like
> gimple_call call = as_a <gimple_statement_call> blah().
> I think as the changes to use the gimple_call type are pushed through 
> all the callers and callee's, the requirement of as_a and the long name 
> being ugly begins to rapidly disappear...  it'll only exist in the core 
> creation routines and no one will usually see it.   So I don't *think* 
> this is an issue...  but it is an ugly transition if its only partially 
> done.
> 
> And eventually we can pull the accessor routines and others into the 
> class itself:
>         gimple_call call;
>         call = gimple_build_call_vec (build_fold_addr_expr_loc (0, 
> alias), vargs);
>         call->set_lhs (atree);
> 
> Which results in a similar feel to the new gimple_type, gimple_decl, 
> etc. classes with my upcoming tree wrappers.  Changing gimple statements 
> to behave something like this is actually mentioned in the plan, but out 
> in the future once trees have been taken care of.
> 
> I would also plan to create instances for each of the gimple statements 
> that don't have them now, like gimple_statement_assign. Its lumped in as 
> a general GSS_WITH_MEM_OPS, so there is no gimple_statement_assign 
> class/struct to use.
> 
> It would really be nice to use the DEFGSCODE macro and gimple.def to 
> make this happen automagically somehow... Its tantalizingly close now I 
> think, especially combined with the info in gsstruct.def... Although if 
> we are moving to proper classes eventually its probably better to 
> explicitly write the required class for a statement kind.
> 
> That all said, this change enables that work to proceed if someone wants 
> to do it.
> 
> My question is: Is anyone going to do it, and if so,  who and when? :-)

Here's a followup patch which ensures that every gimple code has its own
subclass, by adding empty subclasses derived from the GSS_-based
subclasses as appropriate (I don't bother for gimple codes that already
have their own subclass due to having their own GSS layout).  I also
copied the comments from gimple.def into gimple.h, so that Doxygen picks
up on the descriptions and uses them to describe each subclass.

Posting for discussion (i.e. am still bootstrapping this; it also needs
the gengtype fix posted as
http://gcc.gnu.org/ml/gcc-patches/2013-11/msg00425.html)

You can see what the resulting gimple class hierarchy (as reported by
Doxygen) looks like here:
http://dmalcolm.fedorapeople.org/gcc/2013-11-05/doxygen/html/structgimple__statement__base.html



[-- Attachment #2: add-leaf-gimple-subclasses.patch --]
[-- Type: text/x-patch, Size: 24339 bytes --]

commit ec6a05ed9ff15b4fc458c668cfd5227a1506042b
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Tue Nov 5 04:30:15 2013 -0500

    Ensure every gimple code has a subclasses; document.
    
    Add empty subclasses to gimple.h as appropriate to ensure that every
    gimple code has its own gimple subclass.
    
    Add a copy of the documentation from gimple.def to every gimple subclass
    in gimple.h (both new and existing ones) so that the per-code documentation
    shows up per-class within Doxygen-generated docs.
    
    gcc/
    
    	* gimple.h (struct gimple_statement_error_mark): New subclass of
    	gimple_statement_base.
    	(struct gimple_statement_cond): New subclass of
    	gimple_statement_with_ops.
    	(struct gimple_statement_debug): New subclass of
    	gimple_statement_with_ops.
    	(gimple_statement_goto): New subclass of gimple_statement_with_ops.
    	(gimple_statement_label): New subclass of gimple_statement_with_ops.
    	(gimple_statement_switch): New subclass of
    	gimple_statement_with_ops.
    	(gimple_statement_assign): New subclass of
    	gimple_statement_with_memory_ops.
    	(gimple_statement_call): Add documentation from gimple.def.
    	(gimple_statement_bind): Likewise.
    	(gimple_statement_catch): Likewise.
    	(gimple_statement_eh_filter): Likewise.
    	(gimple_statement_eh_else): Likewise.
    	(gimple_statement_eh_mnt): Likewise.
    	(gimple_statement_phi): Likewise.
    	(gimple_statement_resx): New subclass of gimple_statement_eh_ctrl.
    	(gimple_statement_dispatch): Likewise.
    	(gimple_statement_try): Add documentation from gimple.def.
    	(gimple_statement_nop): New subclass of gimple_statement_base.
    	(gimple_statement_wce): Add documentation from gimple.def.
    	(gimple_statement_asm): Likewise.
    	(gimple_statement_omp_critical): Likewise.
    	(gimple_statement_omp_for): Likewise.
    	(gimple_statement_omp_master): New subclass of gimple_statement_omp.
    	(gimple_statement_omp_taskgroup): Likewise.
    	(gimple_statement_omp_ordered): Likewise.
    	(gimple_statement_omp_parallel): Add documentation from
    	gimple.def.
    	(gimple_statement_omp_task): Likewise.
    	(gimple_statement_omp_section): New subclass of
    	gimple_statement_omp.
    	(gimple_statement_omp_sections): Add documentation from gimple.def.
    	(gimple_statement_omp_sections_switch): New subclass of
    	gimple_statement_base.
    	(gimple_statement_omp_continue): Add documentation from gimple.def.
    	(gimple_statement_omp_target): New subclass of
    	gimple_statement_omp_parallel.
    	(gimple_statement_omp_teams): New subclass of
    	gimple_statement_omp_single.
    	(gimple_predict): New subclass of gimple_statement_base.
    	(gimple_statement_omp_atomic_load): Add documentation from
    	gimple.def.
    	(gimple_statement_omp_atomic_store): Update comment.
    	(gimple_statement_omp_return): New subclass of
    	gimple_statement_omp_atomic_store.
    	(gimple_statement_transaction): Add documentation from gimple.def.
    	(gimple_statement_return): New subclass of
    	gimple_statement_with_memory_ops.

diff --git a/gcc/gimple.h b/gcc/gimple.h
index 35bfa06..318953c 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -223,6 +223,13 @@ struct GTY((desc ("gimple_statement_structure (&%h)"), tag ("GSS_BASE"),
   gimple GTY((skip)) prev;
 };
 
+/* code == GIMPLE_ERROR_MARK, an error marker.  */
+
+struct GTY(())
+  gimple_statement_error_mark : public gimple_statement_base
+{
+  /* no additional fields; this uses the layout for GSS_BASE. */
+};
 
 /* Base structure for tuples with operands.  */
 
@@ -255,6 +262,81 @@ struct GTY((tag("GSS_WITH_OPS")))
   tree GTY((length ("%h.num_ops"))) op[1];
 };
 
+/* code == GIMPLE_COND:
+
+   GIMPLE_COND <COND_CODE, OP1, OP2, TRUE_LABEL, FALSE_LABEL>
+   represents the conditional jump:
+
+   if (OP1 COND_CODE OP2) goto TRUE_LABEL else goto FALSE_LABEL
+
+   COND_CODE is the tree code used as the comparison predicate.  It
+   must be of class tcc_comparison.
+
+   OP1 and OP2 are the operands used in the comparison.  They must be
+   accepted by is_gimple_operand.
+
+   TRUE_LABEL and FALSE_LABEL are the LABEL_DECL nodes used as the
+   jump target for the comparison.  */
+
+struct GTY(())
+  gimple_statement_cond : public gimple_statement_with_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
+/* code == GIMPLE_DEBUG, a debug statement.  */
+
+struct GTY(())
+  gimple_statement_debug : public gimple_statement_with_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
+/* code == GIMPLE_GOTO
+
+   GIMPLE_GOTO <TARGET> represents unconditional jumps.
+   TARGET is a LABEL_DECL or an expression node for computed GOTOs.  */
+
+struct GTY(())
+  gimple_statement_goto : public gimple_statement_with_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
+/* code == GIMPLE_LABEL
+
+   GIMPLE_LABEL <LABEL> represents label statements.  LABEL is a
+   LABEL_DECL representing a jump target.  */
+
+struct GTY(())
+  gimple_statement_label : public gimple_statement_with_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
+/* code == GIMPLE_SWITCH
+
+   GIMPLE_SWITCH <INDEX, DEFAULT_LAB, LAB1, ..., LABN> represents the
+   multiway branch:
+
+   switch (INDEX)
+   {
+     case LAB1: ...; break;
+     ...
+     case LABN: ...; break;
+     default: ...
+   }
+
+   INDEX is the variable evaluated to decide which label to jump to.
+
+   DEFAULT_LAB, LAB1 ... LABN are the tree nodes representing case labels.
+   They must be CASE_LABEL_EXPR nodes.  */
+
+struct GTY(())
+  gimple_statement_switch : public gimple_statement_with_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
 
 /* Base for statements that take both memory and register operands.  */
 
@@ -286,8 +368,49 @@ struct GTY((tag("GSS_WITH_MEM_OPS")))
   tree GTY((length ("%h.num_ops"))) op[1];
 };
 
+/* code == GIMPLE_ASSIGN:
+
+   GIMPLE_ASSIGN <SUBCODE, LHS, RHS1[, RHS2]> represents the assignment
+   statement
+
+   LHS = RHS1 SUBCODE RHS2.
+
+   SUBCODE is the tree code for the expression computed by the RHS of the
+   assignment.  It must be one of the tree codes accepted by
+   get_gimple_rhs_class.  If LHS is not a gimple register according to
+   is_gimple_reg, SUBCODE must be of class GIMPLE_SINGLE_RHS.
+
+   LHS is the operand on the LHS of the assignment.  It must be a tree node
+   accepted by is_gimple_lvalue.
+
+   RHS1 is the first operand on the RHS of the assignment.  It must always be
+   present.  It must be a tree node accepted by is_gimple_val.
+
+   RHS2 is the second operand on the RHS of the assignment.  It must be a tree
+   node accepted by is_gimple_val.  This argument exists only if SUBCODE is
+   of class GIMPLE_BINARY_RHS.  */
+
+struct GTY(())
+  gimple_statement_assign : public gimple_statement_with_memory_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_MEM_OPS. */
+};
+
+
+/* code == GIMPLE_CALL.
+
+   GIMPLE_CALL <FN, LHS, ARG1, ..., ARGN[, CHAIN]> represents function
+   calls.
+
+   FN is the callee.  It must be accepted by is_gimple_call_addr.
 
-/* Call statements that take both memory and register operands.  */
+   LHS is the operand where the return value from FN is stored.  It may
+   be NULL.
+
+   ARG1 ... ARGN are the arguments.  They must all be accepted by
+   is_gimple_operand.
+
+   CHAIN is the optional static chain link for nested functions.  */
 
 struct GTY((tag("GSS_CALL")))
   gimple_statement_call : public gimple_statement_with_memory_ops_base
@@ -324,7 +447,12 @@ struct GTY((tag("GSS_OMP")))
 };
 
 
-/* GIMPLE_BIND */
+/* code == GIMPLE_BIND:
+
+   GIMPLE_BIND <VARS, BLOCK, BODY> represents a lexical scope.
+   VARS is the set of variables declared in that scope.
+   BLOCK is the symbol binding block used for debug information.
+   BODY is the sequence of statements in the scope.  */
 
 struct GTY((tag("GSS_BIND")))
   gimple_statement_bind : public gimple_statement_base
@@ -348,7 +476,11 @@ struct GTY((tag("GSS_BIND")))
 };
 
 
-/* GIMPLE_CATCH */
+/* code == GIMPLE_CATCH:
+
+   GIMPLE_CATCH <TYPES, HANDLER> represents a typed exception handler.
+   TYPES is the type (or list of types) handled.  HANDLER is the
+   sequence of statements that handle these types.  */
 
 struct GTY((tag("GSS_CATCH")))
   gimple_statement_catch : public gimple_statement_base
@@ -363,7 +495,11 @@ struct GTY((tag("GSS_CATCH")))
 };
 
 
-/* GIMPLE_EH_FILTER */
+/* code == GIMPLE_EH_FILTER:
+
+   GIMPLE_EH_FILTER <TYPES, FAILURE> represents an exception
+   specification.  TYPES is a list of allowed types and FAILURE is the
+   sequence of statements to execute on failure.  */
 
 struct GTY((tag("GSS_EH_FILTER")))
   gimple_statement_eh_filter : public gimple_statement_base
@@ -379,7 +515,12 @@ struct GTY((tag("GSS_EH_FILTER")))
   gimple_seq failure;
 };
 
-/* GIMPLE_EH_ELSE */
+/* code == GIMPLE_EH_ELSE:
+
+   GIMPLE_EH_ELSE <N_BODY, E_BODY> must be the sole contents of
+   a GIMPLE_TRY_FINALLY node.  For all normal exits from the try block,
+   N_BODY is run; for all exception exits from the try block,
+   E_BODY is run.  */
 
 struct GTY((tag("GSS_EH_ELSE")))
   gimple_statement_eh_else : public gimple_statement_base
@@ -390,7 +531,11 @@ struct GTY((tag("GSS_EH_ELSE")))
   gimple_seq n_body, e_body;
 };
 
-/* GIMPLE_EH_MUST_NOT_THROW */
+/* code == GIMPLE_EH_MUST_NOT_THROW:
+
+   GIMPLE_EH_MUST_NOT_THROW <DECL> represents an exception barrier.
+   DECL is a noreturn function decl taking no arguments that will
+   be invoked if an exception propagates to this point.  */
 
 struct GTY((tag("GSS_EH_MNT")))
   gimple_statement_eh_mnt : public gimple_statement_base
@@ -401,7 +546,18 @@ struct GTY((tag("GSS_EH_MNT")))
   tree fndecl;
 };
 
-/* GIMPLE_PHI */
+/* code == GIMPLE_PHI:
+
+   GIMPLE_PHI <RESULT, ARG1, ..., ARGN> represents the PHI node
+
+   RESULT = PHI <ARG1, ..., ARGN>
+
+   RESULT is the SSA name created by this PHI node.
+
+   ARG1 ... ARGN are the arguments to the PHI node.  N must be
+   exactly the same as the number of incoming edges to the basic block
+   holding the PHI node.  Every argument is either an SSA name or a
+   tree node of class tcc_constant.  */
 
 struct GTY((tag("GSS_PHI")))
   gimple_statement_phi : public gimple_statement_base
@@ -432,8 +588,43 @@ struct GTY((tag("GSS_EH_CTRL")))
   int region;
 };
 
+/* code == GIMPLE_RESX:
+
+   GIMPLE_RESX resumes execution after an exception.  */
+
+struct GTY(())
+  gimple_statement_resx : public gimple_statement_eh_ctrl
+{
+  /* no additional fields; this uses the layout for GSS_EH_CTRL. */
+};
+
+/* code == GIMPLE_EH_DISPATCH:
 
-/* GIMPLE_TRY */
+   GIMPLE_EH_DISPATCH demultiplexes an exception edge based on
+   the FILTER argument.  */
+
+struct GTY(())
+  gimple_statement_dispatch : public gimple_statement_eh_ctrl
+{
+  /* no additional fields; this uses the layout for GSS_EH_CTRL. */
+};
+
+
+/* code == GIMPLE_TRY:
+
+   GIMPLE_TRY <TRY_KIND, EVAL, CLEANUP>
+   represents a try/catch or a try/finally statement.
+
+   TRY_KIND is either GIMPLE_TRY_CATCH or GIMPLE_TRY_FINALLY.
+
+   EVAL is the sequence of statements to execute on entry to GIMPLE_TRY.
+
+   CLEANUP is the sequence of statements to execute according to
+   TRY_KIND.  If TRY_KIND is GIMPLE_TRY_CATCH, CLEANUP is only exected
+   if an exception is thrown during execution of EVAL.  If TRY_KIND is
+   GIMPLE_TRY_FINALLY, CLEANUP is always executed after executing EVAL
+   (regardless of whether EVAL finished normally, or jumped out or an
+   exception was thrown).  */
 
 struct GTY((tag("GSS_TRY")))
   gimple_statement_try : public gimple_statement_base
@@ -463,7 +654,24 @@ enum gimple_try_flags
   GIMPLE_TRY_CATCH_IS_CLEANUP = 1 << 2
 };
 
-/* GIMPLE_WITH_CLEANUP_EXPR */
+/* code == GIMPLE_NOP:
+
+   GIMPLE_NOP represents the "do nothing" statement.  */
+
+struct GTY(())
+  gimple_statement_nop : public gimple_statement_base
+{
+  /* no additional fields; this uses the layout for GSS_BASE. */
+};
+
+
+/* code == GIMPLE_WITH_CLEANUP_EXPR:
+
+   This node represents a cleanup expression.  It is ONLY USED INTERNALLY
+   by the gimplifier as a placeholder for cleanups, and its uses will be
+   cleaned up by the time gimplification is done.
+
+   This tuple should not exist outside of the gimplifier proper.  */
 
 struct GTY((tag("GSS_WCE")))
   gimple_statement_wce : public gimple_statement_base
@@ -481,7 +689,16 @@ struct GTY((tag("GSS_WCE")))
 };
 
 
-/* GIMPLE_ASM  */
+/* code == GIMPLE_ASM:
+
+   GIMPLE_ASM <STRING, I1, ..., IN, O1, ... OM, C1, ..., CP>
+   represents inline assembly statements.
+
+   STRING is the string containing the assembly statements.
+   I1 ... IN are the N input operands.
+   O1 ... OM are the M output operands.
+   C1 ... CP are the P clobber operands.
+   L1 ... LQ are the Q label operands.  */
 
 struct GTY((tag("GSS_ASM")))
   gimple_statement_asm : public gimple_statement_with_memory_ops_base
@@ -506,7 +723,13 @@ struct GTY((tag("GSS_ASM")))
   tree GTY((length ("%h.num_ops"))) op[1];
 };
 
-/* GIMPLE_OMP_CRITICAL */
+/* code == GIMPLE_OMP_CRITICAL:
+   GIMPLE_OMP_CRITICAL <NAME, BODY> represents
+
+   #pragma omp critical [name]
+
+   NAME is the name given to the critical section.
+   BODY is the sequence of statements that are inside the critical section.  */
 
 struct GTY((tag("GSS_OMP_CRITICAL")))
   gimple_statement_omp_critical : public gimple_statement_omp
@@ -536,7 +759,43 @@ struct GTY(()) gimple_omp_for_iter {
   tree incr;
 };
 
-/* GIMPLE_OMP_FOR */
+/* code == GIMPLE_OMP_FOR:
+
+   GIMPLE_OMP_FOR <BODY, CLAUSES, INDEX, INITIAL, FINAL, COND, INCR, PRE_BODY>
+   represents
+
+   PRE_BODY
+   #pragma omp for [clause1 ... clauseN]
+   for (INDEX = INITIAL; INDEX COND FINAL; INDEX {+=,-=} INCR)
+   BODY
+
+   BODY is the loop body.
+
+   CLAUSES is the list of clauses.
+
+   INDEX must be an integer or pointer variable, which is implicitly thread
+   private.  It must be accepted by is_gimple_operand.
+
+   INITIAL is the initial value given to INDEX. It must be
+   accepted by is_gimple_operand.
+
+   FINAL is the final value that INDEX should take. It must
+   be accepted by is_gimple_operand.
+
+   COND is the condition code for the controlling predicate.  It must
+   be one of { <, >, <=, >= }
+
+   INCR is the loop index increment.  It must be tree node of type
+   tcc_constant.
+
+   PRE_BODY is a landing pad filled by the gimplifier with things from
+   INIT, COND, and INCR that are technically part of the OMP_FOR
+   structured block, but are evaluated before the loop body begins.
+
+   INITIAL, FINAL and INCR are required to be loop invariant integer
+   expressions that are evaluated without any synchronization.
+   The evaluation order, frequency of evaluation and side-effects are
+   unspecified by the standard.  */
 
 struct GTY((tag("GSS_OMP_FOR")))
   gimple_statement_omp_for : public gimple_statement_omp
@@ -558,8 +817,58 @@ struct GTY((tag("GSS_OMP_FOR")))
   gimple_seq pre_body;
 };
 
+/* code == GIMPLE_OMP_MASTER:
+
+   GIMPLE_OMP_MASTER <BODY> represents #pragma omp master.
+   BODY is the sequence of statements to execute in the master section.  */
+
+struct GTY(())
+  gimple_statement_omp_master : public gimple_statement_omp
+{
+  /* no additional fields; this uses the layout for GSS_OMP.  */
+};
+
+/* code == GIMPLE_OMP_TASKGROUP:
+
+   GIMPLE_OMP_TASKGROUP <BODY> represents #pragma omp taskgroup.
+   BODY is the sequence of statements to execute in the taskgroup section.  */
+
+struct GTY(())
+  gimple_statement_omp_taskgroup : public gimple_statement_omp
+{
+  /* no additional fields; this uses the layout for GSS_OMP.  */
+};
+
+/* code == GIMPLE_OMP_ORDERED:
 
-/* GIMPLE_OMP_PARALLEL */
+   GIMPLE_OMP_ORDERED <BODY> represents #pragma omp ordered.
+   BODY is the sequence of statements to execute in the ordered section.  */
+
+struct GTY(())
+  gimple_statement_omp_ordered : public gimple_statement_omp
+{
+  /* no additional fields; this uses the layout for GSS_OMP.  */
+};
+
+
+/* code == GIMPLE_OMP_PARALLEL:
+
+   GIMPLE_OMP_PARALLEL <BODY, CLAUSES, CHILD_FN, DATA_ARG> represents
+
+   #pragma omp parallel [CLAUSES]
+   BODY
+
+   BODY is a the sequence of statements to be executed by all threads.
+
+   CLAUSES is an OMP_CLAUSE chain with all the clauses.
+
+   CHILD_FN is set when outlining the body of the parallel region.
+   All the statements in BODY are moved into this newly created
+   function when converting OMP constructs into low-GIMPLE.
+
+   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.  */
 
 struct GTY((tag("GSS_OMP_PARALLEL")))
   gimple_statement_omp_parallel : public gimple_statement_omp
@@ -580,7 +889,33 @@ struct GTY((tag("GSS_OMP_PARALLEL")))
 };
 
 
-/* GIMPLE_OMP_TASK */
+/* code == GIMPLE_OMP_TASK:
+
+   GIMPLE_OMP_TASK <BODY, CLAUSES, CHILD_FN, DATA_ARG, COPY_FN,
+		    ARG_SIZE, ARG_ALIGN> represents
+
+   #pragma omp task [CLAUSES]
+   BODY
+
+   BODY is a the sequence of statements to be executed by all threads.
+
+   CLAUSES is an OMP_CLAUSE chain with all the clauses.
+
+   CHILD_FN is set when outlining the body of the explicit task region.
+   All the statements in BODY are moved into this newly created
+   function when converting OMP constructs into low-GIMPLE.
+
+   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.
+
+   COPY_FN is set when outlining the firstprivate var initialization.
+   All the needed statements are emitted into the newly created
+   function, or when only memcpy is needed, it is NULL.
+
+   ARG_SIZE and ARG_ALIGN are the size and alignment of the incoming
+   data area allocated by GOMP_task and passed to CHILD_FN.  */
+
 
 struct GTY((tag("GSS_OMP_TASK")))
   gimple_statement_omp_task : public gimple_statement_omp_parallel
@@ -597,12 +932,25 @@ struct GTY((tag("GSS_OMP_TASK")))
   tree arg_align;
 };
 
+/* code == GIMPLE_OMP_SECTION:
+
+   OMP_SECTION <BODY> represents #pragma omp section.
+   BODY is the sequence of statements in the section body.  */
 
-/* GIMPLE_OMP_SECTION */
-/* Uses struct gimple_statement_omp.  */
+struct GTY(())
+  gimple_statement_omp_section : public gimple_statement_omp
+{
+  /* no additional fields; this uses the layout for GSS_OMP. */
+};
 
+/* code == GIMPLE_OMP_SECTIONS:
 
-/* GIMPLE_OMP_SECTIONS */
+   OMP_SECTIONS <BODY, CLAUSES, CONTROL> represents #pragma omp sections.
+
+   BODY is the sequence of statements in the sections body.
+   CLAUSES is an OMP_CLAUSE chain holding the list of associated clauses.
+   CONTROL is a VAR_DECL used for deciding which of the sections
+   to execute.  */
 
 struct GTY((tag("GSS_OMP_SECTIONS")))
   gimple_statement_omp_sections : public gimple_statement_omp
@@ -618,10 +966,25 @@ struct GTY((tag("GSS_OMP_SECTIONS")))
   tree control;
 };
 
-/* GIMPLE_OMP_CONTINUE.
+/* code == GIMPLE_OMP_SECTIONS_SWITCH:
+
+   GIMPLE_OMP_SECTIONS_SWITCH is a marker placed immediately after
+   OMP_SECTIONS.  It represents the GIMPLE_SWITCH used to decide which
+   branch is taken.  */
+
+struct GTY(())
+  gimple_statement_omp_sections_switch : public gimple_statement_base
+{
+  /* no additional fields; this uses the layout for GSS_BASE. */
+};
+
+/* code == GIMPLE_OMP_CONTINUE:
 
    Note: This does not inherit from gimple_statement_omp, because we
-         do not need the body field.  */
+         do not need the body field.
+
+   GIMPLE_OMP_CONTINUE marks the location of the loop or sections
+   iteration in partially lowered OpenMP code.  */
 
 struct GTY((tag("GSS_OMP_CONTINUE")))
   gimple_statement_omp_continue : public gimple_statement_base
@@ -646,10 +1009,65 @@ struct GTY((tag("GSS_OMP_SINGLE")))
   tree clauses;
 };
 
+/* code == GIMPLE_OMP_TARGET:
+
+   GIMPLE_OMP_TARGET <BODY, CLAUSES, CHILD_FN> represents
+   #pragma omp target {,data,update}
+   BODY is the sequence of statements inside the target construct
+   (NULL for target update).
+   CLAUSES is an OMP_CLAUSE chain holding the associated clauses.
+   CHILD_FN is set when outlining the body of the target region.
+   All the statements in BODY are moved into this newly created
+   function when converting OMP constructs into low-GIMPLE.
+   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.  */
+
+struct GTY(())
+  gimple_statement_omp_target : public gimple_statement_omp_parallel
+{
+  /* no additional fields; this uses the layout for GSS_OMP_PARALLEL. */
+};
+
+/* code == GIMPLE_OMP_TEAMS:
+
+   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.  */
+
+struct GTY(())
+  gimple_statement_omp_teams : public gimple_statement_omp_single
+{
+  /* no additional fields; this uses the layout for GSS_OMP_SINGLE. */
+};
+
+/* code = GIMPLE_PREDICT:
+
+   GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction.
+
+   PREDICT is one of the predictors from predict.def.
+
+   OUTCOME is NOT_TAKEN or TAKEN.  */
 
-/* GIMPLE_OMP_ATOMIC_LOAD.
+struct GTY(())
+  gimple_predict : public gimple_statement_base
+{
+  /* no additional fields; this uses the layout for GSS_BASE. */
+};
+
+/* code == GIMPLE_OMP_ATOMIC_LOAD.
    Note: This is based on gimple_statement_base, not g_s_omp, because g_s_omp
-   contains a sequence, which we don't need here.  */
+   contains a sequence, which we don't need here.
+
+   Tuples used for lowering of OMP_ATOMIC.  Although the form of the OMP_ATOMIC
+   expression is very simple (just in form mem op= expr), various implicit
+   conversions may cause the expression to become more complex, so that it does
+   not fit the gimple grammar very well.  To overcome this problem, OMP_ATOMIC
+   is rewritten as a sequence of two codes in gimplification:
+
+   GIMPLE_OMP_LOAD (tmp, mem)
+   val = some computations involving tmp;
+   GIMPLE_OMP_STORE (val).  */
 
 struct GTY((tag("GSS_OMP_ATOMIC_LOAD")))
   gimple_statement_omp_atomic_load : public gimple_statement_base
@@ -660,7 +1078,8 @@ struct GTY((tag("GSS_OMP_ATOMIC_LOAD")))
   tree rhs, lhs;
 };
 
-/* GIMPLE_OMP_ATOMIC_STORE.
+/* code == GIMPLE_OMP_ATOMIC_STORE:
+
    See note on GIMPLE_OMP_ATOMIC_LOAD.  */
 
 struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
@@ -672,6 +1091,16 @@ struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
   tree val;
 };
 
+/* code == OMP_RETURN:
+
+   OMP_RETURN marks the end of an OpenMP directive.  */
+
+struct GTY(())
+  gimple_statement_omp_return : public gimple_statement_omp_atomic_store
+{
+  /* no additional fields; this uses the layout for GSS_OMP_ATOMIC_STORE.  */
+};
+
 /* GIMPLE_TRANSACTION.  */
 
 /* Bits to be stored in the GIMPLE_TRANSACTION subcode.  */
@@ -700,6 +1129,16 @@ struct GTY((tag("GSS_OMP_ATOMIC_STORE")))
    likely because it is guaranteed to go irrevocable upon entry.  */
 #define GTMA_HAS_NO_INSTRUMENTATION	(1u << 7)
 
+
+/* code == GIMPLE_TRANSACTION:
+
+   GIMPLE_TRANSACTION <BODY, LABEL> represents __transaction_atomic and
+   __transaction_relaxed blocks.
+   BODY is the sequence of statements inside the transaction.
+   LABEL is a label for the statement immediately following the
+   transaction.  This is before RETURN so that it has MEM_OPS,
+   so that it can clobber global memory.  */
+
 struct GTY((tag("GSS_TRANSACTION")))
   gimple_statement_transaction : public gimple_statement_with_memory_ops_base
 {
@@ -712,6 +1151,19 @@ struct GTY((tag("GSS_TRANSACTION")))
   tree label;
 };
 
+/* code == GIMPLE_RETURN:
+
+   GIMPLE_RETURN <RETVAL> represents return statements.
+
+   RETVAL is the value to return or NULL.  If a value is returned it
+   must be accepted by is_gimple_operand.  */
+
+struct GTY(())
+  gimple_statement_return : public gimple_statement_with_memory_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_MEM_OPS. */
+};
+
 #define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP)	SYM,
 enum gimple_statement_structure_enum {
 #include "gsstruct.def"

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

* Re: [patch]  Create gimple-expr..[ch]  ...  was Re: RFC: gimple.[ch] break apart
  2013-11-05 16:58 ` [patch] Create gimple-expr..[ch] ... was Re: RFC: gimple.[ch] break apart Andrew MacLeod
@ 2013-11-05 17:52   ` Jeff Law
  2013-11-07 10:58   ` Basile Starynkevitch
  1 sibling, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-05 17:52 UTC (permalink / raw)
  To: Andrew MacLeod, gcc-patches, Richard Biener, Diego Novillo

On 11/05/13 09:26, Andrew MacLeod wrote:
> On 10/30/2013 11:18 PM, Andrew MacLeod wrote:
>>
>>
>> As a result, any gimple queries regarding types, decls, or expressions
>> are actually tree queries. They are sprinkled throughout gimple.[ch] and
>> gimplify.[ch], not to mention tree.[ch] as well as other parts of the
>> compiler where they happened to be needed.  This has caused various
>> ordering issues among the inline functions when I tried to split out the
>> stmt, iterator, and gimplification bits from gimple.[ch].  Not to
>> mention a lack of an obvious home for some of these functions.
>>
>> I'd like to move these as I encounter them into a new file,
>> gimple-decl.[ch].  When I'm working on the other gimple classes, this
>> will be further split into gimple-decl, gimple-type and gimple-expr as
>> appropriate but it seems reasonable to create just the one file now to
>> clump them since there is no other formal organization. So any function
>> which is actually querying/setting/building a decl, type, or expression
>> for gimple would go here.
>
> I decided to name the new file gimple-expr.[ch] instead of
> gimple-decl....   This will eventually split into gimple-type.[ch],
> gimple-decl.[ch], and gimple-expr.[ch].  I could split them that way now
> if desired, but isn't critical yet. maybe I should just do that...
> Anyway, of the 3 files, gimple-expr will depend on the other 2, and thus
> is likely to be the one #included in places like the rtl generation
> files that need access to all these gimple dictionary/expression
> routines.   (eventually those rtl files will include only gimple-expr.h
> and not tree.h :-).
>
> In any case, I had to do this split from gimple.h first since
> gimple-stmt.[ch] and the others require some of these basic routines,
> and I can't split anything else out first without then getting an
> include dependency cycle between gimple.h and gimple-stmt.h for
> instance.  This way gimple-stmt.h can include gimple-expr.h, and then
> gimple.h can include gimpe-stmt.h and no chicken/egg situation.
>
> This contains just the functions that are in either in, or prototyped
> in, gimple.h, and is just the first cut.  There are more things that
> will eventually get put here from gimple.c, but their prototypes are in
> places like tree.h and more include cycles or poor requirements on files
> to include are exposed if I move them now since  front ends or rtl files
> are using those routines (like get_base_address).  There are also a few
> I wanted to hold off on and see how things work out before moving them.
>
> In any case, I tried to pull out the functions that operated on trees
> currently and performed an operation on a type, decl, or expression.  My
> litmus test was usually, "Is this liekly going to be a method of a type,
> decl or expr class relating to the object itself." and moved it if it
> seemed so.
>
> The slightly iffier ones were extract_ops_from_tree*() and
> gimple_cond_get_ops_from_tree()... Those clearly worked on expressions
> and not statements, but are utilized in places like rtl land that don't
> deal with stmts...  so they need to be exposed via the expression
> processing and interface.  Its also quite possible those will end up in
> gimplify.[ch] once I get that far...
>
> I do expect there will still be a little bit of fine tuning, but this is
> the first cut to enable me to split out gimple-stmts.[ch] next.
>
> Bootstraps on x86_64-unknown-linux-gnu with no new regressions.  OK?
OK.

jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-01 21:36   ` Andrew MacLeod
                       ` (2 preceding siblings ...)
  2013-11-05 17:23     ` [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)) David Malcolm
@ 2013-11-05 18:22     ` Andrew MacLeod
  3 siblings, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-05 18:22 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Richard Biener, Jeff Law, Jakub Jelinek

On 11/01/2013 05:36 PM, Andrew MacLeod wrote:
> On 10/31/2013 12:26 PM, David Malcolm wrote:
>> [Shamelessly hijacking Andrew's thread about gimple.h refactoring,
>> since this seems on-topic for that, and I'm keen to hear from Andrew on
>> how the following would interact with his work - I *think* our two
>> cleanups are orthogonal.
>
<...>
>
> That all said, this change enables that work to proceed if someone 
> wants to do it.
>
> My question is: Is anyone going to do it, and if so,  who and when? :-)

So in case the waters have gotten muddy...  I am not resisting this 
patch for 4.9...  I think its a reasonable cleanup and was pointing out 
another way it could be useful down the road..  I'd be happy to see some 
form of it go in.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 22:28                 ` Jakub Jelinek
  2013-11-04 22:49                   ` Andrew MacLeod
@ 2013-11-05 21:09                   ` Jeff Law
  1 sibling, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-05 21:09 UTC (permalink / raw)
  To: Jakub Jelinek, David Malcolm; +Cc: Andrew MacLeod, gcc-patches

On 11/04/13 15:25, Jakub Jelinek wrote:
> On Mon, Nov 04, 2013 at 04:43:33PM -0500, David Malcolm wrote:
>> I tried converting gimple_call_set_lhs to accept a gimple_call, rather
>> than a gimple, and excitingly, it was easiest to also convert
>> cgraph_edge's call_stmt to also be a gimple_call, rather than just a
>> gimple.
>>
>> Am attaching a patch (on top of the patch series being discussed) which
>> adds this compile-time typesafety; bootstrap is in-progress.   IMHO very
>> little use of is-a.h was needed (5 instances of as_a, and 3 of dyn_cast;
>> no use of is_a).
>
> But that was just for gimple_call_set_lhs, which indeed usually is done just
> for newly created calls, not for inspecting preexisting IL.  If you do it
> for say gimple_call_arg, gimple_call_fndecl and/or even gimple_call_lhs, I'm
> afraid suddenly it would be hundreds of ugly dyn_casts/as_a and similar mess
> everywhere.  And, calls are still far less common gimple statements than
> gimple assign.
Understood.  I think one of the questions we need to answer is when a 
conversion of this nature is done (towards static typechecking), how 
often will we know the static type vs how often we're going to have to 
play these is_a/as_a games.

I'd claim that often if we're stuck with needing is_a/as_a, then we've 
got some refactoring to do.

Based on discussions Andrew, David & myself had today, my gut says let's 
try to go foward with the basic conversion based on its merits as they 
stand today, but without taking the step towards static typing at this time.

Jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-04 22:31                   ` Andrew MacLeod
@ 2013-11-05 21:27                     ` Jeff Law
  0 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-05 21:27 UTC (permalink / raw)
  To: Andrew MacLeod, David Malcolm; +Cc: Jakub Jelinek, gcc-patches

On 11/04/13 15:28, Andrew MacLeod wrote:
>
> That said, the patch which enables this is more self contained, so
> wouldn't be subject to that. Its a matter of whether it has enough merit
> of its own to go in.   Having the first patch in mainline would actually
> allow someone to experiment more easily during the "off season" if they
> wanted to, but wouldn't be mandatory since they could apply it to their
> own branch to work on.
Let's go with this as our "plan".

Jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
                     ` (7 preceding siblings ...)
  2013-11-01 21:36   ` Andrew MacLeod
@ 2013-11-05 21:33   ` Jeff Law
  2013-11-05 22:01     ` David Malcolm
                       ` (2 more replies)
  2013-11-14  8:40   ` Jeff Law
  9 siblings, 3 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-05 21:33 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
> The gimple statement types are currently implemented using a hand-coded
> C inheritance scheme, with a "union gimple_statement_d" holding the
> various possible structs for a statement.
>
> The following series of patches convert it to a C++ hierarchy, using the
> existing structs, eliminating the union. The "gimple" typedef changes
> from being a
>    (union gimple_statement_d *)
> to being a:
>    (struct gimple_statement_base *)
>
> There are no virtual functions in the new code: the sizes of the various
> structs are unchanged.
>
> It makes use of "is-a.h", using the as_a <T> template function to
> perform downcasts, which are checked (via gcc_checking_assert) in an
> ENABLE_CHECKING build, and are simple casts in an unchecked build,
> albeit it in an inlined function rather than a macro.
>
> For example, one can write:
>
>    gimple_statement_phi *phi =
>      as_a <gimple_statement_phi> (gsi_stmt (gsi));
>
> and then directly access the fields of the phi, as a phi.  The existing
> accessor functions in gimple.h become somewhat redundant in this
> scheme, but are preserved.
>
> The earlier versions of the patches made all of the types GTY((user))
> and provided hand-written implementations of the gc and pch marker
> routines.  In this new version we rely on the support for simple
> inheritance that I recently added to gengtype, by adding a "desc"
> to the GTY marking for the base class, and a "tag" to the marking
> for all of the concrete subclasses.  (I say "class", but all the types
> remain structs since their fields are all publicly accessible).
>
> As noted in the earlier patch, I believe this is a superior scheme to
> the C implementation:
>
>    * We can get closer to compile-time type-safety, checking the gimple
>      code once and downcasting with an as_a, then directly accessing
>      fields, rather than going through accessor functions that check
>      each time.  In some places we may want to replace a "gimple" with
>      a subclass e.g. phis are always of the phi subclass, to get full
>      compile-time type-safety.
>
>    * This scheme is likely to be easier for newbies to understand.
>
>    * Currently in gdb, dereferencing a gimple leads to screenfuls of text,
>      showing all the various union values.  With this, you get just the base
>      class, and can cast it to the appropriate subclass.
>
>    * With this, we're working directly with the language constructs,
>      rather than rolling our own, and thus other tools can better
>      understand the code. (e.g. doxygen).
>
> Again, as noted in the earlier patch series, the names of the structs
> are rather verbose.  I would prefer to also rename them all to eliminate
> the "_statement" component:
>    "gimple_statement_base" -> "gimple_base"
>    "gimple_statement_phi"  -> "gimple_phi"
>    "gimple_statement_omp"  -> "gimple_omp"
> etc, but I didn't do this to mimimize the patch size.  But if the core
> maintainers are up for that, I can redo the patch series with that
> change also, or do that as a followup.
>
> The patch is in 6 parts; all of them are needed together.
And that's part of the problem.  There's understandable resistance to 
(for example) the as_a casting.

There's a bit of natural tension between the desire to keep patches 
small and self-contained and the size/scope of the changes necessary to 
do any serious reorganization work.  This set swings too far in the 
latter direction :-)

Is there any way to go forward without the is_a/as_a stuff?  ie, is 
there're a simpler step towards where we're trying to go that allows 
most of this to go forward now rather than waiting?

>
>    * Patch 1 of 6: This patch adds inheritance to the various gimple
>      types, eliminating the initial baseclass fields, and eliminating the
>      union gimple_statement_d.   All the types remain structs.  They
>      become marked with GTY(()), gaining GSS_ tag values.
>
>    * Patch 2 of 6: This patch ports various accessor functions within
>      gimple.h to the new scheme.
>
>    * Patch 3 of 6: This patch is autogenerated by "refactor_gimple.py"
>      from https://github.com/davidmalcolm/gcc-refactoring-scripts
>      There is a test suite "test_refactor_gimple.py" which may give a
>      clearer idea of the changes that the script makes (and add
>      confidence that it's doing the right thing).
>      The patch converts code of the form:
>        {
>          GIMPLE_CHECK (gs, SOME_CODE);
>          gimple_subclass_get/set_some_field (gs, value);
>        }
>      to code of this form:
>        {
>          some_subclass *stmt = as_a <some_subclass> (gs);
>          stmt->some_field = value;
>        }
>      It also autogenerates specializations of
>          is_a_helper <T>::test
>      equivalent to a GIMPLE_CHECK() for use by is_a and as_a.
Conceptually I'm fine with #1-#3.

>
>    * Patch 4 of 6: This patch implement further specializations of
>      is_a_helper <T>::test, for gimple_has_ops and gimple_has_mem_ops.
Here's where I start to get more concerned.

>
>    * Patch 5 of 6: This patch does the rest of porting from union access
>      to subclass access (all the fiddly places that the script in patch 3
>      couldn't handle).
>
>    * Patch 6 of 6: This patch updates the gdb python pretty-printing
>      hook.
Conceptually #5 and #6 shouldn't be terribly controversial.

THe question is can we move forward without patch #4, even if that means 
we aren't getting the static typechecking we want?

Jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 21:33   ` Jeff Law
@ 2013-11-05 22:01     ` David Malcolm
  2013-11-05 22:17       ` Jeff Law
  2013-11-05 22:24       ` Andrew MacLeod
  2013-11-05 22:12     ` Andrew MacLeod
  2013-11-06  9:37     ` Richard Biener
  2 siblings, 2 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-05 22:01 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Andrew MacLeod

On Tue, 2013-11-05 at 14:18 -0700, Jeff Law wrote:
> On 10/31/13 10:26, David Malcolm wrote:
> > The gimple statement types are currently implemented using a hand-coded
> > C inheritance scheme, with a "union gimple_statement_d" holding the
> > various possible structs for a statement.
> >
> > The following series of patches convert it to a C++ hierarchy, using the
> > existing structs, eliminating the union. The "gimple" typedef changes
> > from being a
> >    (union gimple_statement_d *)
> > to being a:
> >    (struct gimple_statement_base *)
> >
> > There are no virtual functions in the new code: the sizes of the various
> > structs are unchanged.
> >
> > It makes use of "is-a.h", using the as_a <T> template function to
> > perform downcasts, which are checked (via gcc_checking_assert) in an
> > ENABLE_CHECKING build, and are simple casts in an unchecked build,
> > albeit it in an inlined function rather than a macro.
> >
> > For example, one can write:
> >
> >    gimple_statement_phi *phi =
> >      as_a <gimple_statement_phi> (gsi_stmt (gsi));
> >
> > and then directly access the fields of the phi, as a phi.  The existing
> > accessor functions in gimple.h become somewhat redundant in this
> > scheme, but are preserved.
> >
> > The earlier versions of the patches made all of the types GTY((user))
> > and provided hand-written implementations of the gc and pch marker
> > routines.  In this new version we rely on the support for simple
> > inheritance that I recently added to gengtype, by adding a "desc"
> > to the GTY marking for the base class, and a "tag" to the marking
> > for all of the concrete subclasses.  (I say "class", but all the types
> > remain structs since their fields are all publicly accessible).
> >
> > As noted in the earlier patch, I believe this is a superior scheme to
> > the C implementation:
> >
> >    * We can get closer to compile-time type-safety, checking the gimple
> >      code once and downcasting with an as_a, then directly accessing
> >      fields, rather than going through accessor functions that check
> >      each time.  In some places we may want to replace a "gimple" with
> >      a subclass e.g. phis are always of the phi subclass, to get full
> >      compile-time type-safety.
> >
> >    * This scheme is likely to be easier for newbies to understand.
> >
> >    * Currently in gdb, dereferencing a gimple leads to screenfuls of text,
> >      showing all the various union values.  With this, you get just the base
> >      class, and can cast it to the appropriate subclass.
> >
> >    * With this, we're working directly with the language constructs,
> >      rather than rolling our own, and thus other tools can better
> >      understand the code. (e.g. doxygen).
> >
> > Again, as noted in the earlier patch series, the names of the structs
> > are rather verbose.  I would prefer to also rename them all to eliminate
> > the "_statement" component:
> >    "gimple_statement_base" -> "gimple_base"
> >    "gimple_statement_phi"  -> "gimple_phi"
> >    "gimple_statement_omp"  -> "gimple_omp"
> > etc, but I didn't do this to mimimize the patch size.  But if the core
> > maintainers are up for that, I can redo the patch series with that
> > change also, or do that as a followup.
> >
> > The patch is in 6 parts; all of them are needed together.
> And that's part of the problem.  There's understandable resistance to 
> (for example) the as_a casting.
> 
> There's a bit of natural tension between the desire to keep patches 
> small and self-contained and the size/scope of the changes necessary to 
> do any serious reorganization work.  This set swings too far in the 
> latter direction :-)
> 
> Is there any way to go forward without the is_a/as_a stuff?  ie, is 
> there're a simpler step towards where we're trying to go that allows 
> most of this to go forward now rather than waiting?
> 
> >
> >    * Patch 1 of 6: This patch adds inheritance to the various gimple
> >      types, eliminating the initial baseclass fields, and eliminating the
> >      union gimple_statement_d.   All the types remain structs.  They
> >      become marked with GTY(()), gaining GSS_ tag values.
> >
> >    * Patch 2 of 6: This patch ports various accessor functions within
> >      gimple.h to the new scheme.
> >
> >    * Patch 3 of 6: This patch is autogenerated by "refactor_gimple.py"
> >      from https://github.com/davidmalcolm/gcc-refactoring-scripts
> >      There is a test suite "test_refactor_gimple.py" which may give a
> >      clearer idea of the changes that the script makes (and add
> >      confidence that it's doing the right thing).
> >      The patch converts code of the form:
> >        {
> >          GIMPLE_CHECK (gs, SOME_CODE);
> >          gimple_subclass_get/set_some_field (gs, value);
> >        }
> >      to code of this form:
> >        {
> >          some_subclass *stmt = as_a <some_subclass> (gs);
> >          stmt->some_field = value;
> >        }
> >      It also autogenerates specializations of
> >          is_a_helper <T>::test
> >      equivalent to a GIMPLE_CHECK() for use by is_a and as_a.
> Conceptually I'm fine with #1-#3.
> 
> >
> >    * Patch 4 of 6: This patch implement further specializations of
> >      is_a_helper <T>::test, for gimple_has_ops and gimple_has_mem_ops.
> Here's where I start to get more concerned.

Thanks for looking through this.

Both you and Andrew objected to my use of the is-a.h stuff.  Is this due
to the use of C++ templates in that code?   If I were to rewrite things
in a more C idiom, would that be acceptable?

For instance, rather than, say:

  p = as_a <gimple_statement_asm> (
        gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
                              ninputs + noutputs + nclobbers + nlabels));

we could have an inlined as_a equivalent in C syntax:

  p = gimple_as_a_gimple_asm (
        gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
                              ninputs + noutputs + nclobbers + nlabels));

where there could be, say, a pair of functions like this (to handle
const vs non-const):

inline gimple_asm
gimple_as_a_gimple_asm (gimple gs)
{
  GIMPLE_CHECK (gs->code == GIMPLE_ASM);
  return (gimple_asm)gs;
}

inline const_gimple_asm
gimple_as_a_gimple_asm (const_gimple gs)
{
  GIMPLE_CHECK (gs->code == GIMPLE_ASM);
  return (const_gimple_asm)gs;
}

(where typedef gimple_statement_asm *gimple_asm)

That would avoid template usage within the patch, leaving the use of C++
inheritance as the only overtly C++ish aspect.

We could do the above using preprocessor magic, but I'd prefer to have
actual code to do it.

Similarly, instead of:

  const gimple_statement_with_ops *ops_stmt =
    dyn_cast <const gimple_statement_with_ops> (g);
  if (!ops_stmt)
    return NULL;

we could have:

  const_gimple_with_ops ops_stmt =
    gimple_dyn_cast_gimple_with_ops (g);
  if (!ops_stmt)
    return NULL;

> >    * Patch 5 of 6: This patch does the rest of porting from union access
> >      to subclass access (all the fiddly places that the script in patch 3
> >      couldn't handle).
> >
> >    * Patch 6 of 6: This patch updates the gdb python pretty-printing
> >      hook.
> Conceptually #5 and #6 shouldn't be terribly controversial.

(...though they're implicitly using the template specializations from #3
and #4)

> THe question is can we move forward without patch #4, even if that means 
> we aren't getting the static typechecking we want?

Maybe.  If the above idea is still too far, we could keep the
GIMPLE_CHECK checking, and cast by hand.  I suspect the results would be
more ugly (though it's clear that beauty is in the eye of the beholder
here :))

BTW, how do you feel about static_cast<> vs C-style casts?

Thanks
Dave

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 21:33   ` Jeff Law
  2013-11-05 22:01     ` David Malcolm
@ 2013-11-05 22:12     ` Andrew MacLeod
  2013-11-06  9:37     ` Richard Biener
  2 siblings, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-05 22:12 UTC (permalink / raw)
  To: Jeff Law; +Cc: David Malcolm, gcc-patches

On 11/05/2013 04:18 PM, Jeff Law wrote:
>
>>
>>    * Patch 4 of 6: This patch implement further specializations of
>>      is_a_helper <T>::test, for gimple_has_ops and gimple_has_mem_ops.
> Here's where I start to get more concerned.
>
>>
>>    * Patch 5 of 6: This patch does the rest of porting from union access
>>      to subclass access (all the fiddly places that the script in 
>> patch 3
>>      couldn't handle).
>>
>>    * Patch 6 of 6: This patch updates the gdb python pretty-printing
>>      hook.
> Conceptually #5 and #6 shouldn't be terribly controversial.
>
> THe question is can we move forward without patch #4, even if that 
> means we aren't getting the static typechecking we want?
>
I doubt it.  Patch 3 is full of as_a<>  in order to convert the accessor 
functions to work with just a base gimple parameter. At this early stage 
of conversion it is pretty hard to avoid as_a<> at this lowest level in 
order to support the same interface functions we've been using.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 22:01     ` David Malcolm
@ 2013-11-05 22:17       ` Jeff Law
  2013-11-06  1:14         ` Ian Lance Taylor
  2013-11-05 22:24       ` Andrew MacLeod
  1 sibling, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-05 22:17 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Andrew MacLeod

On 11/05/13 14:57, David Malcolm wrote:
>
> Thanks for looking through this.
>
> Both you and Andrew objected to my use of the is-a.h stuff.  Is this due
> to the use of C++ templates in that code?   If I were to rewrite things
> in a more C idiom, would that be acceptable?
I can't speak for Andrew, but my experience with this kind of object 
type casting in a large C++ project is that it's a red flag for a design 
problem.

You could certainly argue that the design problem already exists.  You 
could further argue that what you're doing is marking those warts 
visible in the code rather than in the data structures.  Whether or not 
that's a good thing I haven't pondered much.

For me personally it's less about the syntax.  Others may have other 
opinions.  I strongly suggest they chime in with them ;-)

>
> Maybe.  If the above idea is still too far, we could keep the
> GIMPLE_CHECK checking, and cast by hand.  I suspect the results would be
> more ugly (though it's clear that beauty is in the eye of the beholder
> here :))
>
> BTW, how do you feel about static_cast<> vs C-style casts?
Dislike them both :-)

jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 22:01     ` David Malcolm
  2013-11-05 22:17       ` Jeff Law
@ 2013-11-05 22:24       ` Andrew MacLeod
  1 sibling, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-05 22:24 UTC (permalink / raw)
  To: David Malcolm; +Cc: Jeff Law, gcc-patches

On 11/05/2013 04:57 PM, David Malcolm wrote:
>
> Thanks for looking through this.
>
> Both you and Andrew objected to my use of the is-a.h stuff.  Is this due
> to the use of C++ templates in that code?   If I were to rewrite things
> in a more C idiom, would that be acceptable?

Thats too strong a statement.  I don't like as_a<>, but it has a use.  
The follow on stuff you were showing was full of as_a<>'s which was what 
I was objecting to.

I think the as_a<>'s in this patch set is mostly necessary in order to 
carry out the conversion and leave it there.. The only way to get rid of 
them is to continue through with the rest of what I talked about...  
which isn't happening soon.  But when we do, it should start to reduce 
the numbert of as_a<>'s, not increase them.

I don't really object to them in this patchset.. we're replacing 
GIMPLE_CHECK() with an as_a<> call, so to me thats pretty much a wash in 
most ways.  And its a means to an end.


> For instance, rather than, say:
>
>    p = as_a <gimple_statement_asm> (
>          gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
>                                ninputs + noutputs + nclobbers + nlabels));
>
> we could have an inlined as_a equivalent in C syntax:
>
>    p = gimple_as_a_gimple_asm (
>          gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
>                                ninputs + noutputs + nclobbers + nlabels));
>
> where there could be, say, a pair of functions like this (to handle
> const vs non-const):
>
> inline gimple_asm
> gimple_as_a_gimple_asm (gimple gs)
> {
>    GIMPLE_CHECK (gs->code == GIMPLE_ASM);
>    return (gimple_asm)gs;
> }
>
> inline const_gimple_asm
> gimple_as_a_gimple_asm (const_gimple gs)
> {
>    GIMPLE_CHECK (gs->code == GIMPLE_ASM);
>    return (const_gimple_asm)gs;
> }

I really don't think we need to bend over and jump through hoops in 
order to implement as_a<>  in a different way.  That's just more 
hackery, and we're trying to get away from that.

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 22:17       ` Jeff Law
@ 2013-11-06  1:14         ` Ian Lance Taylor
  2013-11-06 20:49           ` Jeff Law
  0 siblings, 1 reply; 116+ messages in thread
From: Ian Lance Taylor @ 2013-11-06  1:14 UTC (permalink / raw)
  To: Jeff Law; +Cc: David Malcolm, gcc-patches, Andrew MacLeod

On Tue, Nov 5, 2013 at 2:12 PM, Jeff Law <law@redhat.com> wrote:
>
> I can't speak for Andrew, but my experience with this kind of object type
> casting in a large C++ project is that it's a red flag for a design problem.

I'm going to chime in to say that I think it's a pretty typical way to
represent a compiler IR in C++.  There is a base type that a lot of
code uses, but there is also a real type, and the way to get to that
real type is to use a cast.  We could do it all with virtual
functions, but those carry a different cost.  In effect, using virtual
functions increases the size of the code field from 16 bits to 64
bits.  It adds up.

Also this seems to be a pretty direct version of the data structures
we already have.

Ian

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-05 21:33   ` Jeff Law
  2013-11-05 22:01     ` David Malcolm
  2013-11-05 22:12     ` Andrew MacLeod
@ 2013-11-06  9:37     ` Richard Biener
  2013-11-06 11:20       ` Bernd Schmidt
  2013-11-06 21:26       ` Jeff Law
  2 siblings, 2 replies; 116+ messages in thread
From: Richard Biener @ 2013-11-06  9:37 UTC (permalink / raw)
  To: Jeff Law; +Cc: David Malcolm, GCC Patches, Andrew MacLeod

On Tue, Nov 5, 2013 at 10:18 PM, Jeff Law <law@redhat.com> wrote:
> On 10/31/13 10:26, David Malcolm wrote:
>>
>> The gimple statement types are currently implemented using a hand-coded
>> C inheritance scheme, with a "union gimple_statement_d" holding the
>> various possible structs for a statement.
>>
>> The following series of patches convert it to a C++ hierarchy, using the
>> existing structs, eliminating the union. The "gimple" typedef changes
>> from being a
>>    (union gimple_statement_d *)
>> to being a:
>>    (struct gimple_statement_base *)
>>
>> There are no virtual functions in the new code: the sizes of the various
>> structs are unchanged.
>>
>> It makes use of "is-a.h", using the as_a <T> template function to
>> perform downcasts, which are checked (via gcc_checking_assert) in an
>> ENABLE_CHECKING build, and are simple casts in an unchecked build,
>> albeit it in an inlined function rather than a macro.
>>
>> For example, one can write:
>>
>>    gimple_statement_phi *phi =
>>      as_a <gimple_statement_phi> (gsi_stmt (gsi));
>>
>> and then directly access the fields of the phi, as a phi.  The existing
>> accessor functions in gimple.h become somewhat redundant in this
>> scheme, but are preserved.
>>
>> The earlier versions of the patches made all of the types GTY((user))
>> and provided hand-written implementations of the gc and pch marker
>> routines.  In this new version we rely on the support for simple
>> inheritance that I recently added to gengtype, by adding a "desc"
>> to the GTY marking for the base class, and a "tag" to the marking
>> for all of the concrete subclasses.  (I say "class", but all the types
>> remain structs since their fields are all publicly accessible).
>>
>> As noted in the earlier patch, I believe this is a superior scheme to
>> the C implementation:
>>
>>    * We can get closer to compile-time type-safety, checking the gimple
>>      code once and downcasting with an as_a, then directly accessing
>>      fields, rather than going through accessor functions that check
>>      each time.  In some places we may want to replace a "gimple" with
>>      a subclass e.g. phis are always of the phi subclass, to get full
>>      compile-time type-safety.
>>
>>    * This scheme is likely to be easier for newbies to understand.
>>
>>    * Currently in gdb, dereferencing a gimple leads to screenfuls of text,
>>      showing all the various union values.  With this, you get just the
>> base
>>      class, and can cast it to the appropriate subclass.
>>
>>    * With this, we're working directly with the language constructs,
>>      rather than rolling our own, and thus other tools can better
>>      understand the code. (e.g. doxygen).
>>
>> Again, as noted in the earlier patch series, the names of the structs
>> are rather verbose.  I would prefer to also rename them all to eliminate
>> the "_statement" component:
>>    "gimple_statement_base" -> "gimple_base"
>>    "gimple_statement_phi"  -> "gimple_phi"
>>    "gimple_statement_omp"  -> "gimple_omp"
>> etc, but I didn't do this to mimimize the patch size.  But if the core
>> maintainers are up for that, I can redo the patch series with that
>> change also, or do that as a followup.
>>
>> The patch is in 6 parts; all of them are needed together.
>
> And that's part of the problem.  There's understandable resistance to (for
> example) the as_a casting.
>
> There's a bit of natural tension between the desire to keep patches small
> and self-contained and the size/scope of the changes necessary to do any
> serious reorganization work.  This set swings too far in the latter
> direction :-)
>
> Is there any way to go forward without the is_a/as_a stuff?  ie, is there're
> a simpler step towards where we're trying to go that allows most of this to
> go forward now rather than waiting?

We decided to move to C++.  As part of a later discussion we decided
to go with a single general dynamic-casting style, mimicing the "real"
C++ variant which is dynamic_cast < ... >.  Which resulted in
is-a.h.

So yes, we've decided to go C++ so we have to live with certain
uglinesses of that decisions (and maybe over time those uglinesses
will fade away and we get used to it and like it).

Thus, there isn't another option besides using the is-a.h machinery
and enabling and using RTTI.  Sticking to C for gimple doesn't seem
to be consistent with the decision to move to C++.

Oh, I'm not saying I'm a big fan of as_a / is_a or C++ in general
as it plays out right now.  But well, we've had the discussion and
had a decision.

Execute.

Richard.

>
>>
>>    * Patch 1 of 6: This patch adds inheritance to the various gimple
>>      types, eliminating the initial baseclass fields, and eliminating the
>>      union gimple_statement_d.   All the types remain structs.  They
>>      become marked with GTY(()), gaining GSS_ tag values.
>>
>>    * Patch 2 of 6: This patch ports various accessor functions within
>>      gimple.h to the new scheme.
>>
>>    * Patch 3 of 6: This patch is autogenerated by "refactor_gimple.py"
>>      from https://github.com/davidmalcolm/gcc-refactoring-scripts
>>      There is a test suite "test_refactor_gimple.py" which may give a
>>      clearer idea of the changes that the script makes (and add
>>      confidence that it's doing the right thing).
>>      The patch converts code of the form:
>>        {
>>          GIMPLE_CHECK (gs, SOME_CODE);
>>          gimple_subclass_get/set_some_field (gs, value);
>>        }
>>      to code of this form:
>>        {
>>          some_subclass *stmt = as_a <some_subclass> (gs);
>>          stmt->some_field = value;
>>        }
>>      It also autogenerates specializations of
>>          is_a_helper <T>::test
>>      equivalent to a GIMPLE_CHECK() for use by is_a and as_a.
>
> Conceptually I'm fine with #1-#3.
>
>
>>
>>    * Patch 4 of 6: This patch implement further specializations of
>>      is_a_helper <T>::test, for gimple_has_ops and gimple_has_mem_ops.
>
> Here's where I start to get more concerned.
>
>
>>
>>    * Patch 5 of 6: This patch does the rest of porting from union access
>>      to subclass access (all the fiddly places that the script in patch 3
>>      couldn't handle).
>>
>>    * Patch 6 of 6: This patch updates the gdb python pretty-printing
>>      hook.
>
> Conceptually #5 and #6 shouldn't be terribly controversial.
>
> THe question is can we move forward without patch #4, even if that means we
> aren't getting the static typechecking we want?
>
> Jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06  9:37     ` Richard Biener
@ 2013-11-06 11:20       ` Bernd Schmidt
  2013-11-06 11:43         ` Richard Biener
                           ` (2 more replies)
  2013-11-06 21:26       ` Jeff Law
  1 sibling, 3 replies; 116+ messages in thread
From: Bernd Schmidt @ 2013-11-06 11:20 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jeff Law, David Malcolm, GCC Patches, Andrew MacLeod

On 11/06/2013 10:31 AM, Richard Biener wrote:
> We decided to move to C++.  As part of a later discussion we decided
> to go with a single general dynamic-casting style, mimicing the "real"
> C++ variant which is dynamic_cast < ... >.  Which resulted in
> is-a.h.
> 
> So yes, we've decided to go C++ so we have to live with certain
> uglinesses of that decisions (and maybe over time those uglinesses
> will fade away and we get used to it and like it).
> 
> Thus, there isn't another option besides using the is-a.h machinery
> and enabling and using RTTI.  Sticking to C for gimple doesn't seem
> to be consistent with the decision to move to C++.
> 
> Oh, I'm not saying I'm a big fan of as_a / is_a or C++ in general
> as it plays out right now.  But well, we've had the discussion and
> had a decision.

Maybe we need to revisit it? As one of those who were not in favour of
the C++ move, can I ask you guys to step back for a moment and think
about - what do all of these changes buy us, exactly? Imagine the state
at the end, where everything is converted and supposedly the temporary
ugliness is gone, what have we gained over the code as it is now?

I still think all this effort is misdirected and distracts us from
making changes that improve gcc for its users.


Bernd

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:20       ` Bernd Schmidt
@ 2013-11-06 11:43         ` Richard Biener
  2013-11-06 11:53           ` Jakub Jelinek
                             ` (3 more replies)
  2013-11-06 11:56         ` Eric Botcazou
  2013-11-06 20:51         ` Jeff Law
  2 siblings, 4 replies; 116+ messages in thread
From: Richard Biener @ 2013-11-06 11:43 UTC (permalink / raw)
  To: Bernd Schmidt; +Cc: Jeff Law, David Malcolm, GCC Patches, Andrew MacLeod

On Wed, Nov 6, 2013 at 12:02 PM, Bernd Schmidt <bernds@codesourcery.com> wrote:
> On 11/06/2013 10:31 AM, Richard Biener wrote:
>> We decided to move to C++.  As part of a later discussion we decided
>> to go with a single general dynamic-casting style, mimicing the "real"
>> C++ variant which is dynamic_cast < ... >.  Which resulted in
>> is-a.h.
>>
>> So yes, we've decided to go C++ so we have to live with certain
>> uglinesses of that decisions (and maybe over time those uglinesses
>> will fade away and we get used to it and like it).
>>
>> Thus, there isn't another option besides using the is-a.h machinery
>> and enabling and using RTTI.  Sticking to C for gimple doesn't seem
>> to be consistent with the decision to move to C++.
>>
>> Oh, I'm not saying I'm a big fan of as_a / is_a or C++ in general
>> as it plays out right now.  But well, we've had the discussion and
>> had a decision.
>
> Maybe we need to revisit it? As one of those who were not in favour of
> the C++ move, can I ask you guys to step back for a moment and think
> about - what do all of these changes buy us, exactly? Imagine the state
> at the end, where everything is converted and supposedly the temporary
> ugliness is gone, what have we gained over the code as it is now?

as_a gains us less runtime checking and more static type checking
which is good.

> I still think all this effort is misdirected and distracts us from
> making changes that improve gcc for its users.

That I agree to.  Instead of fixing the less than optimal separation / boundary
between frontends and the middle-end, or fixing several other long-standing
issues with GCC we spend a lot of time refactoring things to be C++.
But that was kind of part of the decision (though I remember that we
mainly wanted to convert containters and isolated stuff, not gimple
or trees (I bet that'll be next)).

Of course I don't see contributors of "changes that improve gcc for its users"
now wasting their time with converting code to C++.  That conversion
may slow down those people, but only so much.  It'll get more interesting
with branch maintainance ...

Richard.

>
> Bernd
>

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:43         ` Richard Biener
@ 2013-11-06 11:53           ` Jakub Jelinek
  2013-11-06 13:14             ` Richard Biener
                               ` (2 more replies)
  2013-11-06 12:42           ` Bernd Schmidt
                             ` (2 subsequent siblings)
  3 siblings, 3 replies; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-06 11:53 UTC (permalink / raw)
  To: Richard Biener
  Cc: Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches, Andrew MacLeod

On Wed, Nov 06, 2013 at 12:31:00PM +0100, Richard Biener wrote:
> > Maybe we need to revisit it? As one of those who were not in favour of
> > the C++ move, can I ask you guys to step back for a moment and think
> > about - what do all of these changes buy us, exactly? Imagine the state
> > at the end, where everything is converted and supposedly the temporary
> > ugliness is gone, what have we gained over the code as it is now?
> 
> as_a gains us less runtime checking and more static type checking
> which is good.

But that really affects --enable-checking=yes builds (and only cases where
things aren't inlined).  If the price for that is uglier and less readable
code, then the price is just too high.

> > I still think all this effort is misdirected and distracts us from
> > making changes that improve gcc for its users.
> 
> That I agree to.  Instead of fixing the less than optimal separation / boundary
> between frontends and the middle-end, or fixing several other long-standing
> issues with GCC we spend a lot of time refactoring things to be C++.
> But that was kind of part of the decision (though I remember that we
> mainly wanted to convert containters and isolated stuff, not gimple
> or trees (I bet that'll be next)).
> 
> Of course I don't see contributors of "changes that improve gcc for its users"
> now wasting their time with converting code to C++.  That conversion
> may slow down those people, but only so much.  It'll get more interesting
> with branch maintainance ...

If the changes are done at least with some for users useful goal (like
perhaps making gcc usable as a library for JITting etc.), then I can see
the benefit, but as_s<> uglification doesn't seem to be beneficial to
users at all, and IMNSHO much better would be to instead
spend time on what is beneficial to users (restrict, vectorizer
cost model, vectorizer improvements, better diagnostics (say range
locations), ...).

	Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:20       ` Bernd Schmidt
  2013-11-06 11:43         ` Richard Biener
@ 2013-11-06 11:56         ` Eric Botcazou
  2013-11-06 20:51         ` Jeff Law
  2 siblings, 0 replies; 116+ messages in thread
From: Eric Botcazou @ 2013-11-06 11:56 UTC (permalink / raw)
  To: Bernd Schmidt
  Cc: gcc-patches, Richard Biener, Jeff Law, David Malcolm, Andrew MacLeod

> Maybe we need to revisit it? As one of those who were not in favour of
> the C++ move, can I ask you guys to step back for a moment and think
> about - what do all of these changes buy us, exactly? Imagine the state
> at the end, where everything is converted and supposedly the temporary
> ugliness is gone, what have we gained over the code as it is now?

Without going as far as revisiting the decision, I'd like to ask whether the 
impact of the recent changes on the speed of the compiler has been evaluated.
I didn't conduct real measurements but bootstrap times on mainline, which 
were slightly increasing as usual over the course of the year, started to 
increase at a faster pace over the last couple of months, at least for me.

-- 
Eric Botcazou

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:43         ` Richard Biener
  2013-11-06 11:53           ` Jakub Jelinek
@ 2013-11-06 12:42           ` Bernd Schmidt
  2013-11-06 21:04           ` Jeff Law
  2013-11-06 21:06           ` Andrew MacLeod
  3 siblings, 0 replies; 116+ messages in thread
From: Bernd Schmidt @ 2013-11-06 12:42 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jeff Law, David Malcolm, GCC Patches, Andrew MacLeod

On 11/06/2013 12:31 PM, Richard Biener wrote:
> That I agree to.  Instead of fixing the less than optimal separation / boundary
> between frontends and the middle-end, or fixing several other long-standing
> issues with GCC we spend a lot of time refactoring things to be C++.
> But that was kind of part of the decision (though I remember that we
> mainly wanted to convert containters and isolated stuff, not gimple
> or trees (I bet that'll be next)).

What I seem to remember is being told that we'd use C++ mostly for new
code and not engage in a wholesale rewrite of the compiler.

Instead things happened exactly as predicted, we're getting immense
amounts of churn for little real gain, and in some cases the C++ changes
are not even improvements and look like really strange examples of C++
code. I'll offer as evidence the pass manager with its bizarre has_gate
and has_execute variables, member functions for gate and execute
wrapping non-member functions, and a separate pass_data outside of its
class (not even as a static member).

Now that the question of what would happen after a C++ conversion is no
longer theoretical but has been answered, can we maybe just stop and
think for a while whether this is really the way we should be going?


Bernd

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:53           ` Jakub Jelinek
@ 2013-11-06 13:14             ` Richard Biener
  2013-11-06 13:23               ` Jakub Jelinek
  2013-11-06 13:31             ` Joseph S. Myers
  2013-11-06 21:09             ` Jeff Law
  2 siblings, 1 reply; 116+ messages in thread
From: Richard Biener @ 2013-11-06 13:14 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches, Andrew MacLeod

On Wed, Nov 6, 2013 at 12:42 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Nov 06, 2013 at 12:31:00PM +0100, Richard Biener wrote:
>> > Maybe we need to revisit it? As one of those who were not in favour of
>> > the C++ move, can I ask you guys to step back for a moment and think
>> > about - what do all of these changes buy us, exactly? Imagine the state
>> > at the end, where everything is converted and supposedly the temporary
>> > ugliness is gone, what have we gained over the code as it is now?
>>
>> as_a gains us less runtime checking and more static type checking
>> which is good.
>
> But that really affects --enable-checking=yes builds (and only cases where
> things aren't inlined).  If the price for that is uglier and less readable
> code, then the price is just too high.
>
>> > I still think all this effort is misdirected and distracts us from
>> > making changes that improve gcc for its users.
>>
>> That I agree to.  Instead of fixing the less than optimal separation / boundary
>> between frontends and the middle-end, or fixing several other long-standing
>> issues with GCC we spend a lot of time refactoring things to be C++.
>> But that was kind of part of the decision (though I remember that we
>> mainly wanted to convert containters and isolated stuff, not gimple
>> or trees (I bet that'll be next)).
>>
>> Of course I don't see contributors of "changes that improve gcc for its users"
>> now wasting their time with converting code to C++.  That conversion
>> may slow down those people, but only so much.  It'll get more interesting
>> with branch maintainance ...
>
> If the changes are done at least with some for users useful goal (like
> perhaps making gcc usable as a library for JITting etc.), then I can see
> the benefit, but as_s<> uglification doesn't seem to be beneficial to
> users at all, and IMNSHO much better would be to instead
> spend time on what is beneficial to users (restrict, vectorizer
> cost model, vectorizer improvements, better diagnostics (say range
> locations), ...).

Well, what else, besides as_a<> or keeping the current
global accessor functions would you propose?

Richard.

>         Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 13:14             ` Richard Biener
@ 2013-11-06 13:23               ` Jakub Jelinek
  2013-11-06 16:42                 ` David Malcolm
  0 siblings, 1 reply; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-06 13:23 UTC (permalink / raw)
  To: Richard Biener
  Cc: Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches, Andrew MacLeod

On Wed, Nov 06, 2013 at 02:00:56PM +0100, Richard Biener wrote:
> Well, what else, besides as_a<> or keeping the current
> global accessor functions would you propose?

I'd prefer to keep the current accessors.  Whether there is a class
hierarchy or we keep unions doesn't affect the code too much (unless
it makes debugging experience harder, as numerous past C++ification changes
have done :( ).

	Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:53           ` Jakub Jelinek
  2013-11-06 13:14             ` Richard Biener
@ 2013-11-06 13:31             ` Joseph S. Myers
  2013-11-06 21:25               ` Jeff Law
  2013-11-06 21:09             ` Jeff Law
  2 siblings, 1 reply; 116+ messages in thread
From: Joseph S. Myers @ 2013-11-06 13:31 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Richard Biener, Bernd Schmidt, Jeff Law, David Malcolm,
	GCC Patches, Andrew MacLeod

On Wed, 6 Nov 2013, Jakub Jelinek wrote:

> On Wed, Nov 06, 2013 at 12:31:00PM +0100, Richard Biener wrote:
> > > Maybe we need to revisit it? As one of those who were not in favour of
> > > the C++ move, can I ask you guys to step back for a moment and think
> > > about - what do all of these changes buy us, exactly? Imagine the state
> > > at the end, where everything is converted and supposedly the temporary
> > > ugliness is gone, what have we gained over the code as it is now?
> > 
> > as_a gains us less runtime checking and more static type checking
> > which is good.
> 
> But that really affects --enable-checking=yes builds (and only cases where
> things aren't inlined).  If the price for that is uglier and less readable
> code, then the price is just too high.

I see static type checking as being about preventing certain sorts of bugs 
getting in the compiler at all, rather than about saving time on runtime 
checks for --enable-checking=yes.

I don't have advice on the gimple case.  But certainly trees and RTL could 
both do with more static typing.  There, I'm thinking of different types 
of objects (types, expressions, ...) logically being completely separate 
static types, not inheriting from a common "tree" base class at all.  But 
if inheritance and as_a can be used as intermediate steps to allow an 
incremental transition to completely separate static types, where 
otherwise the whole source tree would need converting at once, that seems 
reasonable to me. (I have no comments about what things should look like 
in cases where completely separate static types don't make sense but there 
is still some sort of inheritance structure.)

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 13:23               ` Jakub Jelinek
@ 2013-11-06 16:42                 ` David Malcolm
  2013-11-06 16:55                   ` Jakub Jelinek
  0 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-11-06 16:42 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Richard Biener, Bernd Schmidt, Jeff Law, GCC Patches, Andrew MacLeod

On Wed, 2013-11-06 at 14:11 +0100, Jakub Jelinek wrote:
> On Wed, Nov 06, 2013 at 02:00:56PM +0100, Richard Biener wrote:
> > Well, what else, besides as_a<> or keeping the current
> > global accessor functions would you propose?
> 
> I'd prefer to keep the current accessors.  Whether there is a class
> hierarchy or we keep unions doesn't affect the code too much (unless
> it makes debugging experience harder, as numerous past C++ification changes
> have done :( ).

What specific things have become more difficult to debug due to the
changes you refer to?
I can have a look at improving them by extending gdbhooks.py, if that is
desirable.

Thanks
Dave

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-05 17:23     ` [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)) David Malcolm
@ 2013-11-06 16:53       ` Michael Matz
  2013-11-07  6:19         ` David Malcolm
  2013-11-08  0:07         ` Alec Teal
  0 siblings, 2 replies; 116+ messages in thread
From: Michael Matz @ 2013-11-06 16:53 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrew MacLeod, gcc-patches

Hi,

On Tue, 5 Nov 2013, David Malcolm wrote:

> Here's a followup patch which ensures that every gimple code has its own
> subclass, by adding empty subclasses derived from the GSS_-based
> subclasses as appropriate (I don't bother for gimple codes that already
> have their own subclass due to having their own GSS layout).  I also
> copied the comments from gimple.def into gimple.h, so that Doxygen picks
> up on the descriptions and uses them to describe each subclass.

I don't like that.  The empty classes are just useless, they imply a 
structure that isn't really there, some of the separate gimple codes are 
basically selectors of specific subtypes of a generic concept, without 
additional data or methods; creating a type for those is confusing.

Generally I don't like complicating the type system without good reasons 
(as in actually also making use of the complicated types).  The fewer 
types the better IMO.


Ciao,
Michael.

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 16:42                 ` David Malcolm
@ 2013-11-06 16:55                   ` Jakub Jelinek
  2013-11-06 18:34                     ` Tom Tromey
  0 siblings, 1 reply; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-06 16:55 UTC (permalink / raw)
  To: David Malcolm
  Cc: Richard Biener, Bernd Schmidt, Jeff Law, GCC Patches, Andrew MacLeod

On Wed, Nov 06, 2013 at 11:25:31AM -0500, David Malcolm wrote:
> On Wed, 2013-11-06 at 14:11 +0100, Jakub Jelinek wrote:
> > On Wed, Nov 06, 2013 at 02:00:56PM +0100, Richard Biener wrote:
> > > Well, what else, besides as_a<> or keeping the current
> > > global accessor functions would you propose?
> > 
> > I'd prefer to keep the current accessors.  Whether there is a class
> > hierarchy or we keep unions doesn't affect the code too much (unless
> > it makes debugging experience harder, as numerous past C++ification changes
> > have done :( ).
> 
> What specific things have become more difficult to debug due to the
> changes you refer to?
> I can have a look at improving them by extending gdbhooks.py, if that is
> desirable.

I'm refering to various things that have been mentioned already multiple
times, mostly from the switch to C++, like:
1) p debug_tree (0x7ffff18b3690)
   not working anymore, typically one would use this when just cut'n'pasting
   addresses seen in backtrace, other debug_tree etc., one now has to add
   explicitly a cast p debug_tree ((tree)0x7ffff18b3690).
   Perhaps this can be cured just by adding extra overloads for a few most
   popular debug_* routines that weren't initially overloaded, add them an
   overload with uintptr_t type or similar that will just cast it to the
   right type and call the original routine
2) tab completion often not working well for hundreds of functions, say type
   p gimple_can_m<tab>
   When gcc was written in C, this would complete it just fine into
   p gimple_can_merge_blocks_p
   but GDB is confused by the forward declarations and offers you:
   p gimple_can_merge_blocks_p(basic_block
   and doesn't autocomplete further from there, so, for functions that
   aren't really overloaded (fortunately so far most of them) one has to
   manually remove all the cruft until and including the (, or has to
   complete from memory or similar.  The issue is that gdb sees:
   gimple_can_merge_blocks_p(basic_block, basic_block)
   gimple_can_merge_blocks_p(basic_block_def*, basic_block_def*)
   gimple_can_merge_blocks_p(basic_block_def*, basic_block_def*)::__FUNCTION__
   and considers the two different thing, but of course:
   typedef struct basic_block_def *basic_block;
   and thus you really don't care which one is chosen from these, but
   preferrably just one, not both.
3) step got significantly worse over time, we have skip_file tree.h, but
   with all the recent header reorganizations gdbinit.in hasn't been
   updated on which other headers would greatly benefit from being skipped
   by default.  Certainly gimple.h IMHO, and various new headers that just
   contain small inline accessors
4) the gdbhooks.py printing is nice, but (talking just from memory), it is
   tied to just one spelling of various types, so say if something has
   basic_block type, it is printed nicely, but if it has basic_block_def *
   type, it isn't
5) the new "improved" C++ vec.h is harder to use in the debugger
This list is still very much incomplete.

	Jakub

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 16:55                   ` Jakub Jelinek
@ 2013-11-06 18:34                     ` Tom Tromey
  2013-11-06 19:15                       ` Jeff Law
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Tromey @ 2013-11-06 18:34 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: David Malcolm, Richard Biener, Bernd Schmidt, Jeff Law,
	GCC Patches, Andrew MacLeod

>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:

Jakub> 1) p debug_tree (0x7ffff18b3690)
Jakub>    not working anymore, typically one would use this when just
Jakub>    cut'n'pasting addresses seen in backtrace, other debug_tree
Jakub>    etc., one now has to add explicitly a cast p debug_tree
Jakub>    ((tree)0x7ffff18b3690).  Perhaps this can be cured just by
Jakub>    adding extra overloads for a few most popular debug_* routines
Jakub>    that weren't initially overloaded, add them an overload with
Jakub>    uintptr_t type or similar that will just cast it to the right
Jakub>    type and call the original routine

Last time this came up, we added the feature to gdb.  You have to enable
it, though.  Use "set check type off".

Tom

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 18:34                     ` Tom Tromey
@ 2013-11-06 19:15                       ` Jeff Law
  2013-11-06 20:05                         ` Tom Tromey
  0 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-06 19:15 UTC (permalink / raw)
  To: Tom Tromey, Jakub Jelinek
  Cc: David Malcolm, Richard Biener, Bernd Schmidt, GCC Patches,
	Andrew MacLeod

On 11/06/13 11:04, Tom Tromey wrote:
>>>>>> "Jakub" == Jakub Jelinek <jakub@redhat.com> writes:
>
> Jakub> 1) p debug_tree (0x7ffff18b3690)
> Jakub>    not working anymore, typically one would use this when just
> Jakub>    cut'n'pasting addresses seen in backtrace, other debug_tree
> Jakub>    etc., one now has to add explicitly a cast p debug_tree
> Jakub>    ((tree)0x7ffff18b3690).  Perhaps this can be cured just by
> Jakub>    adding extra overloads for a few most popular debug_* routines
> Jakub>    that weren't initially overloaded, add them an overload with
> Jakub>    uintptr_t type or similar that will just cast it to the right
> Jakub>    type and call the original routine
>
> Last time this came up, we added the feature to gdb.  You have to enable
> it, though.  Use "set check type off".
I'd been mildly annoyed by this behaviour, but not so much as to look 
for a solution and I can certainly see why gdb is doing what it's doing. 
  I certainly don't consider this something that should stand in the way 
of moving forward.

ISTM that one liner belongs in GCC's .gdbinit.  Until then, I'm adding 
it to my own :-)




jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 19:15                       ` Jeff Law
@ 2013-11-06 20:05                         ` Tom Tromey
  2013-11-06 20:45                           ` Jeff Law
  0 siblings, 1 reply; 116+ messages in thread
From: Tom Tromey @ 2013-11-06 20:05 UTC (permalink / raw)
  To: Jeff Law
  Cc: Jakub Jelinek, David Malcolm, Richard Biener, Bernd Schmidt,
	GCC Patches, Andrew MacLeod

>>>>> "Jeff" == Jeff Law <law@redhat.com> writes:

Jeff> ISTM that one liner belongs in GCC's .gdbinit.  Until then, I'm adding
Jeff> it to my own :-)

Yeah, I think that would be reasonable.
It seems like it isn't appropriate in many cases, so we left it off by
default.

Tom

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 20:05                         ` Tom Tromey
@ 2013-11-06 20:45                           ` Jeff Law
  0 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-06 20:45 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Jakub Jelinek, David Malcolm, Richard Biener, Bernd Schmidt,
	GCC Patches, Andrew MacLeod

[-- Attachment #1: Type: text/plain, Size: 395 bytes --]

On 11/06/13 13:01, Tom Tromey wrote:
>>>>>> "Jeff" == Jeff Law <law@redhat.com> writes:
>
> Jeff> ISTM that one liner belongs in GCC's .gdbinit.  Until then, I'm adding
> Jeff> it to my own :-)
>
> Yeah, I think that would be reasonable.
> It seems like it isn't appropriate in many cases, so we left it off by
> default.
Here's the patch I installed for GCC.   Thanks for the suggestion!

Jeff

[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 876 bytes --]

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dfaf4e3..43ebbda 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2013-11-06  Jeff Law  <law@redhat.com>
+	    Tom Tromey  <tromey@redhat.com>
+
+	* gdbinit.in: Disable strict type checking.
+
 2013-11-06  Vladimir Makarov  <vmakarov@redhat.com>
 
 	* tree-pass.h (make_pass_live_range_shrinkage): New external.
diff --git a/gcc/gdbinit.in b/gcc/gdbinit.in
index 503ef24..c60cab1 100644
--- a/gcc/gdbinit.in
+++ b/gcc/gdbinit.in
@@ -205,6 +205,11 @@ set complaints 0
 b exit
 b abort
 
+# Disable strict type checking.  This allows developers to (for example)
+# make inferior calls without casting absolute address to a suitable
+# pointer type.
+set check type off
+
 # Skip all inline functions in tree.h.
 # These are used in accessor macros.
 # Note that this is added at the end because older gdb versions

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06  1:14         ` Ian Lance Taylor
@ 2013-11-06 20:49           ` Jeff Law
  2013-11-06 20:57             ` Trevor Saunders
  0 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-06 20:49 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: David Malcolm, gcc-patches, Andrew MacLeod

On 11/05/13 16:23, Ian Lance Taylor wrote:
> On Tue, Nov 5, 2013 at 2:12 PM, Jeff Law <law@redhat.com> wrote:
>>
>> I can't speak for Andrew, but my experience with this kind of object type
>> casting in a large C++ project is that it's a red flag for a design problem.
>
> I'm going to chime in to say that I think it's a pretty typical way to
> represent a compiler IR in C++.  There is a base type that a lot of
> code uses, but there is also a real type, and the way to get to that
> real type is to use a cast.  We could do it all with virtual
> functions, but those carry a different cost.  In effect, using virtual
> functions increases the size of the code field from 16 bits to 64
> bits.  It adds up.
>
> Also this seems to be a pretty direct version of the data structures
> we already have.
Certainly and to some degree these casts in one form or another are a 
necessity.  My concern is we use them as a crutch (as I've seen in other 
projects) and we end up not getting the level of compile time static 
type checking that we want.

If the bulk are temporary in nature and we as a project agree to look at 
the refactoring necessary to minimize the is-a/as-a uses to a few low 
level idioms, then I'll hesitatingly go along.  If that's the choice we 
make, then folks should know I'll probably look at each is-a/as-a in 
patches I review and ask for a justification for their use.


jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:20       ` Bernd Schmidt
  2013-11-06 11:43         ` Richard Biener
  2013-11-06 11:56         ` Eric Botcazou
@ 2013-11-06 20:51         ` Jeff Law
  2 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-06 20:51 UTC (permalink / raw)
  To: Bernd Schmidt, Richard Biener; +Cc: David Malcolm, GCC Patches, Andrew MacLeod

On 11/06/13 04:02, Bernd Schmidt wrote:
> On 11/06/2013 10:31 AM, Richard Biener wrote:
>> We decided to move to C++.  As part of a later discussion we decided
>> to go with a single general dynamic-casting style, mimicing the "real"
>> C++ variant which is dynamic_cast < ... >.  Which resulted in
>> is-a.h.
>>
>> So yes, we've decided to go C++ so we have to live with certain
>> uglinesses of that decisions (and maybe over time those uglinesses
>> will fade away and we get used to it and like it).
>>
>> Thus, there isn't another option besides using the is-a.h machinery
>> and enabling and using RTTI.  Sticking to C for gimple doesn't seem
>> to be consistent with the decision to move to C++.
>>
>> Oh, I'm not saying I'm a big fan of as_a / is_a or C++ in general
>> as it plays out right now.  But well, we've had the discussion and
>> had a decision.
>
> Maybe we need to revisit it? As one of those who were not in favour of
> the C++ move, can I ask you guys to step back for a moment and think
> about - what do all of these changes buy us, exactly? Imagine the state
> at the end, where everything is converted and supposedly the temporary
> ugliness is gone, what have we gained over the code as it is now?
I think Andrew outlined much of this at the Cauldron.  I'd strongly 
recommend reviewing the talk/slides.  My personal favorite is the type 
checking and everything that implies.  For example, most/all of the tree 
checking crap just goes away as you'll almost always know what kind of 
tree you're working with.  Checking becomes limited to locations where 
we we have to do conversions.  It becomes a lot harder to mess something up.

>
> I still think all this effort is misdirected and distracts us from
> making changes that improve gcc for its users.
I disagree.  This effort is meant to restructure GCC so that we can 
continue to improve it without going insane.

In many respects it's similar to the tree-ssa work we undertook 10+ 
years ago and to some degree it's cleaning up things we decided not to 
deal with at that time -- namely reusing trees in gimple/ssa.


jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 20:49           ` Jeff Law
@ 2013-11-06 20:57             ` Trevor Saunders
  0 siblings, 0 replies; 116+ messages in thread
From: Trevor Saunders @ 2013-11-06 20:57 UTC (permalink / raw)
  To: gcc-patches

On Wed, Nov 06, 2013 at 01:38:23PM -0700, Jeff Law wrote:
> On 11/05/13 16:23, Ian Lance Taylor wrote:
> >On Tue, Nov 5, 2013 at 2:12 PM, Jeff Law <law@redhat.com> wrote:
> >>
> >>I can't speak for Andrew, but my experience with this kind of object type
> >>casting in a large C++ project is that it's a red flag for a design problem.
> >
> >I'm going to chime in to say that I think it's a pretty typical way to
> >represent a compiler IR in C++.  There is a base type that a lot of
> >code uses, but there is also a real type, and the way to get to that
> >real type is to use a cast.  We could do it all with virtual
> >functions, but those carry a different cost.  In effect, using virtual
> >functions increases the size of the code field from 16 bits to 64
> >bits.  It adds up.
> >
> >Also this seems to be a pretty direct version of the data structures
> >we already have.
> Certainly and to some degree these casts in one form or another are
> a necessity.  My concern is we use them as a crutch (as I've seen in
> other projects) and we end up not getting the level of compile time
> static type checking that we want.

So, thinking about this more the is_a / as_a is more or less just a
translation of the "union casting" we're already doing, which means
while we may not be getting everything we would like we're atleast
getting as good or better than what we have modulo stylistic tastes.

> If the bulk are temporary in nature and we as a project agree to
> look at the refactoring necessary to minimize the is-a/as-a uses to
> a few low level idioms, then I'll hesitatingly go along.  If that's
> the choice we make, then folks should know I'll probably look at
> each is-a/as-a in patches I review and ask for a justification for
> their use.

I think that's a reasonable thing to do fwiw.

Trev

> 
> 
> jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:43         ` Richard Biener
  2013-11-06 11:53           ` Jakub Jelinek
  2013-11-06 12:42           ` Bernd Schmidt
@ 2013-11-06 21:04           ` Jeff Law
  2013-11-06 21:06           ` Andrew MacLeod
  3 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-06 21:04 UTC (permalink / raw)
  To: Richard Biener, Bernd Schmidt; +Cc: David Malcolm, GCC Patches, Andrew MacLeod

On 11/06/13 04:31, Richard Biener wrote:
> On Wed, Nov 6, 2013 at 12:02 PM, Bernd Schmidt <bernds@codesourcery.com> wrote:
>> On 11/06/2013 10:31 AM, Richard Biener wrote:
>>> We decided to move to C++.  As part of a later discussion we decided
>>> to go with a single general dynamic-casting style, mimicing the "real"
>>> C++ variant which is dynamic_cast < ... >.  Which resulted in
>>> is-a.h.
>>>
>>> So yes, we've decided to go C++ so we have to live with certain
>>> uglinesses of that decisions (and maybe over time those uglinesses
>>> will fade away and we get used to it and like it).
>>>
>>> Thus, there isn't another option besides using the is-a.h machinery
>>> and enabling and using RTTI.  Sticking to C for gimple doesn't seem
>>> to be consistent with the decision to move to C++.
>>>
>>> Oh, I'm not saying I'm a big fan of as_a / is_a or C++ in general
>>> as it plays out right now.  But well, we've had the discussion and
>>> had a decision.
>>
>> Maybe we need to revisit it? As one of those who were not in favour of
>> the C++ move, can I ask you guys to step back for a moment and think
>> about - what do all of these changes buy us, exactly? Imagine the state
>> at the end, where everything is converted and supposedly the temporary
>> ugliness is gone, what have we gained over the code as it is now?
>
> as_a gains us less runtime checking and more static type checking
> which is good.
Absolutely.

> That I agree to.  Instead of fixing the less than optimal separation / boundary
> between frontends and the middle-end, or fixing several other long-standing
> issues with GCC we spend a lot of time refactoring things to be C++.
> But that was kind of part of the decision (though I remember that we
> mainly wanted to convert containters and isolated stuff, not gimple
> or trees (I bet that'll be next)).
That's a reasonable bet given what's already been said on this list WRT 
gimple.


>
> Of course I don't see contributors of "changes that improve gcc for its users"
> now wasting their time with converting code to C++.  That conversion
> may slow down those people, but only so much.  It'll get more interesting
> with branch maintainance ...
True.  But that's probabl more of an artifact of the engineers involved. 
  David (who's by far the most gung-ho on the C++ front) is fairly new 
to GCC and isn't really in a position right now to drive much user 
visible stuff.  So he's doing what he can right now.

jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:43         ` Richard Biener
                             ` (2 preceding siblings ...)
  2013-11-06 21:04           ` Jeff Law
@ 2013-11-06 21:06           ` Andrew MacLeod
  2013-11-06 21:52             ` Jeff Law
                               ` (2 more replies)
  3 siblings, 3 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-06 21:06 UTC (permalink / raw)
  To: Richard Biener; +Cc: Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches

On 11/06/2013 06:31 AM, Richard Biener wrote:
> On Wed, Nov 6, 2013 at 12:02 PM, Bernd Schmidt <bernds@codesourcery.com> wrote:
>>
>> Maybe we need to revisit it? As one of those who were not in favour of
>> the C++ move, can I ask you guys to step back for a moment and think
>> about - what do all of these changes buy us, exactly? Imagine the state
>> at the end, where everything is converted and supposedly the temporary
>> ugliness is gone, what have we gained over the code as it is now?
> as_a gains us less runtime checking and more static type checking
> which is good.
>
>> I still think all this effort is misdirected and distracts us from
>> making changes that improve gcc for its users.
> That I agree to.  Instead of fixing the less than optimal separation / boundary
> between frontends and the middle-end, or fixing several other long-standing
> issues with GCC we spend a lot of time refactoring things to be C++.
> But that was kind of part of the decision (though I remember that we
> mainly wanted to convert containters and isolated stuff, not gimple
> or trees (I bet that'll be next)).
>
> Of course I don't see contributors of "changes that improve gcc for its users"
> now wasting their time with converting code to C++.  That conversion
> may slow down those people, but only so much.  It'll get more interesting
> with branch maintainance ...
>
>
What does it buy us?  I won't comment on the merit of other changes, but 
I will reiterate what I'm doing.

1 - I think the code restructuring  to enable the changes I proposed is 
quite worthwhile.  Our includes are a mess and prototypes locations are 
all over the map. I think this is a worthwhile cleanup that I probably 
wouldn't be doing otherwise.

2 - I really believe gimple needs a type system different from front end 
trees, that is my primary motivation.  I'm tired of jumping through 
hoops to do anything slightly different, and I got fed up with it.  With 
a separate type system for gimple, we can rid ourselves of all the stuff 
that isn't related to optimization and codegen...   Could we do this 
with trees? possibly, but if I'm going to go to the effort of converting 
the front end tree types into a new or reduced-type subset, I might as 
well put that effort into something that is more appropriate right from 
the start.

3 - Trees are very polymorphic and as a result, its difficult to tell 
where types are being used. By replacing those uses with an actual type, 
we'll get static type checking which is another improvement.   There is 
only one way to move the middle/back end off of types as trees that I 
can see.  Go through the source base and find all the places which use 
trees as types, and replace them with an actual type.  This can't be 
done all at once, its too big a job...  So I propose a plan which allows 
a new gimple type and current trees to coexist.  Once the conversion is 
complete we can easily implement a type system that has the features and 
traits we want.

4 - I realized that if I am going through the entire code base to find 
all the type locations, its very little extra work to also do the same 
for decls and expressions. Then we'll have static type checking for 
those as well.

5 - When done we will be significantly closer to having the ability to 
create a self contained IL that we can strictly define...  That alone 
seems a worthwhile goal to me.  The IL then becomes appropriate for 
streaming at any point in during compilation.  This means any front end 
or tool can easily generate or consume a gimple stream which opens up 
numerous opportunities...  That is pretty hard to enable today.

Im going to do the initial bits on a branch for the first couple of 
months, and during that time convert a number of files over to the new 
gimple interface.  Then we can look at it, measure it, comment on it, 
tweak it, whatever.  You can see exactly what we'll be getting into 
before we fully commit.  I think it will be an improvement over what we 
have today and much easier to work with. If the consensus is that it 
bites, then we leave it on the branch, and what have we lost?  a few 
months of my time and we've gained some really useful knowledge.

And no, if I can get trees out of gimple, I don't intend to ever touch 
them again! :-)

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 11:53           ` Jakub Jelinek
  2013-11-06 13:14             ` Richard Biener
  2013-11-06 13:31             ` Joseph S. Myers
@ 2013-11-06 21:09             ` Jeff Law
  2 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-06 21:09 UTC (permalink / raw)
  To: Jakub Jelinek, Richard Biener
  Cc: Bernd Schmidt, David Malcolm, GCC Patches, Andrew MacLeod

On 11/06/13 04:42, Jakub Jelinek wrote:
> On Wed, Nov 06, 2013 at 12:31:00PM +0100, Richard Biener wrote:
>>> Maybe we need to revisit it? As one of those who were not in favour of
>>> the C++ move, can I ask you guys to step back for a moment and think
>>> about - what do all of these changes buy us, exactly? Imagine the state
>>> at the end, where everything is converted and supposedly the temporary
>>> ugliness is gone, what have we gained over the code as it is now?
>>
>> as_a gains us less runtime checking and more static type checking
>> which is good.
>
> But that really affects --enable-checking=yes builds (and only cases where
> things aren't inlined).  If the price for that is uglier and less readable
> code, then the price is just too high.
I totally disagree.  Getting to a better static typed system is good.

All the tree/rtl checking bits are really working around the sad fact 
that we don't have a statically typed system.  The checking stuff has 
been a big help to ensure we're not doing something stupid.  But those 
problems really need to be caught at compile time, not a runtime.

jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 13:31             ` Joseph S. Myers
@ 2013-11-06 21:25               ` Jeff Law
  0 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-06 21:25 UTC (permalink / raw)
  To: Joseph S. Myers, Jakub Jelinek
  Cc: Richard Biener, Bernd Schmidt, David Malcolm, GCC Patches,
	Andrew MacLeod

On 11/06/13 06:23, Joseph S. Myers wrote:
> On Wed, 6 Nov 2013, Jakub Jelinek wrote:
>
>> On Wed, Nov 06, 2013 at 12:31:00PM +0100, Richard Biener wrote:
>>>> Maybe we need to revisit it? As one of those who were not in favour of
>>>> the C++ move, can I ask you guys to step back for a moment and think
>>>> about - what do all of these changes buy us, exactly? Imagine the state
>>>> at the end, where everything is converted and supposedly the temporary
>>>> ugliness is gone, what have we gained over the code as it is now?
>>>
>>> as_a gains us less runtime checking and more static type checking
>>> which is good.
>>
>> But that really affects --enable-checking=yes builds (and only cases where
>> things aren't inlined).  If the price for that is uglier and less readable
>> code, then the price is just too high.
>
> I see static type checking as being about preventing certain sorts of bugs
> getting in the compiler at all, rather than about saving time on runtime
> checks for --enable-checking=yes.
Amen!  When I've described RTL & trees to other folks in the business 
that work(ed) on other compilers, most gasped in horror.  Doubly so when 
I did this prior to the introduction of the tree/rtl checking systems.


>
> I don't have advice on the gimple case.  But certainly trees and RTL could
> both do with more static typing.  There, I'm thinking of different types
> of objects (types, expressions, ...) logically being completely separate
> static types, not inheriting from a common "tree" base class at all.  But
> if inheritance and as_a can be used as intermediate steps to allow an
> incremental transition to completely separate static types, where
> otherwise the whole source tree would need converting at once, that seems
> reasonable to me. (I have no comments about what things should look like
> in cases where completely separate static types don't make sense but there
> is still some sort of inheritance structure.)
I hadn't really thought of it that way -- specifically that when we're 
done we don't necessarily need to have decls, types, expressions 
inheriting from a common tree base class.  I must say, I like it as a 
guiding principle.

Jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06  9:37     ` Richard Biener
  2013-11-06 11:20       ` Bernd Schmidt
@ 2013-11-06 21:26       ` Jeff Law
  1 sibling, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-06 21:26 UTC (permalink / raw)
  To: Richard Biener; +Cc: David Malcolm, GCC Patches, Andrew MacLeod

On 11/06/13 02:31, Richard Biener wrote:

>
> We decided to move to C++.  As part of a later discussion we decided
> to go with a single general dynamic-casting style, mimicing the "real"
> C++ variant which is dynamic_cast < ... >.  Which resulted in
> is-a.h.
>
> So yes, we've decided to go C++ so we have to live with certain
> uglinesses of that decisions (and maybe over time those uglinesses
> will fade away and we get used to it and like it).
>
> Thus, there isn't another option besides using the is-a.h machinery
> and enabling and using RTTI.  Sticking to C for gimple doesn't seem
> to be consistent with the decision to move to C++.
>
> Oh, I'm not saying I'm a big fan of as_a / is_a or C++ in general
> as it plays out right now.  But well, we've had the discussion and
> had a decision.
>
> Execute.
OK.  I'll hold my nose when I see the as_a/is_a stuff and try to get 
past them :-)

jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 21:06           ` Andrew MacLeod
@ 2013-11-06 21:52             ` Jeff Law
  2013-11-07 10:29             ` Richard Biener
  2013-11-10 12:35             ` Richard Sandiford
  2 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-06 21:52 UTC (permalink / raw)
  To: Andrew MacLeod, Richard Biener; +Cc: Bernd Schmidt, David Malcolm, GCC Patches

On 11/06/13 13:56, Andrew MacLeod wrote:
>
> 5 - When done we will be significantly closer to having the ability to
> create a self contained IL that we can strictly define...  That alone
> seems a worthwhile goal to me.  The IL then becomes appropriate for
> streaming at any point in during compilation.  This means any front end
> or tool can easily generate or consume a gimple stream which opens up
> numerous opportunities...  That is pretty hard to enable today.
And I think that when we get to this point we're going to find the 
capability to be quite a boon to our efficiency as developers.

jeff

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-06 16:53       ` Michael Matz
@ 2013-11-07  6:19         ` David Malcolm
  2013-11-07  7:08           ` Jeff Law
  2013-11-07 14:57           ` Michael Matz
  2013-11-08  0:07         ` Alec Teal
  1 sibling, 2 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-07  6:19 UTC (permalink / raw)
  To: Michael Matz; +Cc: Andrew MacLeod, gcc-patches

On Wed, 2013-11-06 at 16:32 +0100, Michael Matz wrote:
> Hi,
> 
> On Tue, 5 Nov 2013, David Malcolm wrote:
> 
> > Here's a followup patch which ensures that every gimple code has its own
> > subclass, by adding empty subclasses derived from the GSS_-based
> > subclasses as appropriate (I don't bother for gimple codes that already
> > have their own subclass due to having their own GSS layout).  I also
> > copied the comments from gimple.def into gimple.h, so that Doxygen picks
> > up on the descriptions and uses them to describe each subclass.
> 
> I don't like that.  The empty classes are just useless, they imply a 
> structure that isn't really there, some of the separate gimple codes are 
> basically selectors of specific subtypes of a generic concept, without 
> additional data or methods; creating a type for those is confusing.

A type system does more than just express memory layouts:
* it permits the proof of absence of certain bugs
* it supports abstraction
* it documents the intent of the code

To give an example from the patch, the proposed gimple_statement_switch
subclass of gimple_statement_with_ops adds no extra fields, but it adds
the invariant that (assuming the ptr is non-NULL), that code ==
GIMPLE_SWITCH, or, more intuitively, "it's a switch statement".

This means that if we have a gimple_statement_switch, that both a human
reading the code and the compiler can "know" at compile-time that the
code == GIMPLE_SWITCH. 

The accessors are the big use-case for this, which would be a large
patch (as discussed elsewhere in the thread), but there are other places
where this could be used.

Consider tree-switch-conversion.c: this contains various "gimple"
variables but they don't work on arbitrary gimple; they require code ==
GIMPLE_SWITCH:

For example:
/* Collect information about GIMPLE_SWITCH statement SWTCH into INFO.
*/

static void
collect_switch_conv_info (gimple swtch, struct switch_conv_info *info)
{...}

Right now we're expressing the code == GIMPLE_SWITCH invariant via
naming-conventions ("swtch") and runtime checking in the checked build
(covering documentation of intent and implementation respectively).

We could be doing this directly in the type system, and using the
compiler to check it.

> Generally I don't like complicating the type system without good reasons 
> (as in actually also making use of the complicated types).

I can post a followup patch that makes use of each of these, if it will
help.

>   The fewer 
> types the better IMO.

There's a reductio ad absurdum of that argument: reduce the number of
types to zero and use void* everywhere, replacing field lookups with
pointer arithmetic and casts [1].  Obviously this is a strawman, but
looking through tree(-core).h, gimple.h and rtl.h it feels to me all too
reminiscent of the current implementation, alas.

Hope this is constructive.
Dave

[1] or cons cells if you're that way inclined.

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-07  6:19         ` David Malcolm
@ 2013-11-07  7:08           ` Jeff Law
  2013-11-08 19:23             ` David Malcolm
  2013-11-07 14:57           ` Michael Matz
  1 sibling, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-07  7:08 UTC (permalink / raw)
  To: David Malcolm, Michael Matz; +Cc: Andrew MacLeod, gcc-patches

[ Just a note, of this reply is meant for Michael and other parts for 
David, hopefully the audience is clear from the context. ]

On 11/06/13 21:56, David Malcolm wrote:
> On Wed, 2013-11-06 at 16:32 +0100, Michael Matz wrote:
>> Hi,
>>
>> On Tue, 5 Nov 2013, David Malcolm wrote:
>>
>>> Here's a followup patch which ensures that every gimple code has its own
>>> subclass, by adding empty subclasses derived from the GSS_-based
>>> subclasses as appropriate (I don't bother for gimple codes that already
>>> have their own subclass due to having their own GSS layout).  I also
>>> copied the comments from gimple.def into gimple.h, so that Doxygen picks
>>> up on the descriptions and uses them to describe each subclass.
>>
>> I don't like that.  The empty classes are just useless, they imply a
>> structure that isn't really there, some of the separate gimple codes are
>> basically selectors of specific subtypes of a generic concept, without
>> additional data or methods; creating a type for those is confusing.
>
> A type system does more than just express memory layouts:
> * it permits the proof of absence of certain bugs
Right.  As you have probably surmised, this is the single biggest thing 
we get from this work in my mind.  We use the type system to ensure a 
certain class of bugs simply won't get through the compilation phase.

That's a significant and important change from where we are now.  Right 
now we have no way of knowing that at compile time.  Instead we rely 
upon an insane set of macros to check this kind of invariant at run 
time.  Note carefully just because we don't hit a checking failure 
doesn't mean the code is safe.  It just means we haven't found a set of 
preconditions necessary to trip the problem at runtime.  Obviously in 
some (many), where may be no such way to trigger the failure, but 
there's no way to prove it.

Don't get me wrong the checking macros, when they were introduced were a 
godsend.  But they're papering over a fundamental problems in GCC's 
internal representations.

I think it's hard to overestimate the value we get by moving this stuff 
into compile-time type checking.


> I can post a followup patch that makes use of each of these, if it will
> help.
I wouldn't mind seeing a small example proof of concept posted to help 
those who don't see where this is going understand the goal.  I would 
recommend against posting another large patch for inclusion at this time.

Jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 21:06           ` Andrew MacLeod
  2013-11-06 21:52             ` Jeff Law
@ 2013-11-07 10:29             ` Richard Biener
  2013-11-07 14:01               ` Joseph S. Myers
  2013-11-07 14:53               ` Andrew MacLeod
  2013-11-10 12:35             ` Richard Sandiford
  2 siblings, 2 replies; 116+ messages in thread
From: Richard Biener @ 2013-11-07 10:29 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches

On Wed, Nov 6, 2013 at 9:56 PM, Andrew MacLeod <amacleod@redhat.com> wrote:
> On 11/06/2013 06:31 AM, Richard Biener wrote:
>>
>> On Wed, Nov 6, 2013 at 12:02 PM, Bernd Schmidt <bernds@codesourcery.com>
>> wrote:
>>>
>>>
>>> Maybe we need to revisit it? As one of those who were not in favour of
>>> the C++ move, can I ask you guys to step back for a moment and think
>>> about - what do all of these changes buy us, exactly? Imagine the state
>>> at the end, where everything is converted and supposedly the temporary
>>> ugliness is gone, what have we gained over the code as it is now?
>>
>> as_a gains us less runtime checking and more static type checking
>> which is good.
>>
>>> I still think all this effort is misdirected and distracts us from
>>> making changes that improve gcc for its users.
>>
>> That I agree to.  Instead of fixing the less than optimal separation /
>> boundary
>> between frontends and the middle-end, or fixing several other
>> long-standing
>> issues with GCC we spend a lot of time refactoring things to be C++.
>> But that was kind of part of the decision (though I remember that we
>> mainly wanted to convert containters and isolated stuff, not gimple
>> or trees (I bet that'll be next)).
>>
>> Of course I don't see contributors of "changes that improve gcc for its
>> users"
>> now wasting their time with converting code to C++.  That conversion
>> may slow down those people, but only so much.  It'll get more interesting
>> with branch maintainance ...
>>
>>
> What does it buy us?  I won't comment on the merit of other changes, but I
> will reiterate what I'm doing.
>
> 1 - I think the code restructuring  to enable the changes I proposed is
> quite worthwhile.  Our includes are a mess and prototypes locations are all
> over the map. I think this is a worthwhile cleanup that I probably wouldn't
> be doing otherwise.

True.

> 2 - I really believe gimple needs a type system different from front end
> trees, that is my primary motivation.  I'm tired of jumping through hoops to
> do anything slightly different, and I got fed up with it.  With a separate
> type system for gimple, we can rid ourselves of all the stuff that isn't
> related to optimization and codegen...   Could we do this with trees?
> possibly, but if I'm going to go to the effort of converting the front end
> tree types into a new or reduced-type subset, I might as well put that
> effort into something that is more appropriate right from the start.

I'm not sure.  Especially the idea of wrapping everything in a
I'm-not-a-tree-well-but-I-really-still-am scares the hell out of me.
And I put that into the very same basket of things you now complain about.

> 3 - Trees are very polymorphic and as a result, its difficult to tell where
> types are being used.

It's a feature.  Now the type vs. object thing may be something to
change (historically the reason they are entangled is that things
like a vector and a list also were trees - which is a feature).

> By replacing those uses with an actual type, we'll get
> static type checking which is another improvement.   There is only one way
> to move the middle/back end off of types as trees that I can see.  Go
> through the source base and find all the places which use trees as types,
> and replace them with an actual type.  This can't be done all at once, its
> too big a job...  So I propose a plan which allows a new gimple type and
> current trees to coexist.  Once the conversion is complete we can easily
> implement a type system that has the features and traits we want.

Note that on 'gimple' there are no types ... the types are on the objects
'gimple' refers to and those are 'tree's.  So you'd need to change the
'tree's to have TREE_TYPE not be a 'tree'.  Or simply subclass
'tree' so you can distinguish a tree type from a tree non-type statically
(a bit awkward with the current union setup).

But maybe I'm confusing what you call 'type'.

> 4 - I realized that if I am going through the entire code base to find all
> the type locations, its very little extra work to also do the same for decls
> and expressions. Then we'll have static type checking for those as well.
>
> 5 - When done we will be significantly closer to having the ability to
> create a self contained IL that we can strictly define...  That alone seems
> a worthwhile goal to me.  The IL then becomes appropriate for streaming at
> any point in during compilation.  This means any front end or tool can
> easily generate or consume a gimple stream which opens up numerous
> opportunities...  That is pretty hard to enable today.

Have fun with dealing with our legacy frontends ;)  Or didn't you
actually mean "any point" during compilation? ... oh, you talk about
GIMPLE.  So no plans for Frontend ASTs aka GENERIC for our legacy
frontends?

> Im going to do the initial bits on a branch for the first couple of months,
> and during that time convert a number of files over to the new gimple
> interface.  Then we can look at it, measure it, comment on it, tweak it,
> whatever.  You can see exactly what we'll be getting into before we fully
> commit.

Before we fully commit we want to see the underlying object changes.
Because I still doubt this all will work out without seriously restructuring
the entanglement of our tree-based frontends and the middle-end
(say "fold").

That is, I still think you are starting this at the wrong end.  You first
need to solve the entanglement issue before you can seriously consider
making any real change to the data structures GIMPLE relies on.

>  I think it will be an improvement over what we have today and much
> easier to work with. If the consensus is that it bites, then we leave it on
> the branch, and what have we lost?  a few months of my time and we've gained
> some really useful knowledge.
>
> And no, if I can get trees out of gimple, I don't intend to ever touch them
> again! :-)

Well, I'm betting that you'll re-invent sth like 'tree' just don't
call it 'tree' ;)
You need to transparently refer to constants, SSA names and decls
(at least) as GIMPLE statement operands.  You probably will make
a "gimple statement operand" base class.  Well - that's a 'tree' ;)

Richard.


> Andrew
>

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

* Re: [patch]  Create gimple-expr..[ch]  ...  was Re: RFC: gimple.[ch] break apart
  2013-11-05 16:58 ` [patch] Create gimple-expr..[ch] ... was Re: RFC: gimple.[ch] break apart Andrew MacLeod
  2013-11-05 17:52   ` Jeff Law
@ 2013-11-07 10:58   ` Basile Starynkevitch
  2013-11-07 13:47     ` Andrew MacLeod
  1 sibling, 1 reply; 116+ messages in thread
From: Basile Starynkevitch @ 2013-11-07 10:58 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, Richard Biener, Jeff Law, Diego Novillo

On Tue, Nov 05, 2013 at 11:26:46AM -0500, Andrew MacLeod wrote:
> 
> I decided to name the new file gimple-expr.[ch] instead of
> gimple-decl....   This will eventually split into gimple-type.[ch],
> gimple-decl.[ch], and gimple-expr.[ch].  


Since we are adding *new* C++ files, can't we please name them *.cc 
for the implementation part, so at least create gimple-expr.h and 
gimple-expr.cc but not gimple-expr.c, please!

There are some reasons to keep existing *.c files containing C++ code
(IMHO the reasons are bad ones, and related to poor habits and to 
deficiencies in the version control system we have to use, 
but I really don't want to open that debate again).

But for **NEW** files which are definitely in C++, I don't understand 
why they should be named .c files; this is confusing for all (and, 
for instance, when compiling them with Clang we are getting -IMHO 
rightly- some warnings about the file naming).

If I remember well, there have been (in the discussion about naming C++ source 
files of GCC) a suggestion (and perhaps even a consensus), 
probably by Diego Novillo, to name *.cc our new files which are in C++.


Having old C++ files named *.c is already a big frustration 
(most editors are by default configured to handle them as C, not as C++, files
and most developers, notably newbies to GCC contributions, 
are expecting them to be C files not C++ ones). 

But IMHO having new source files inside GCC coded in C++ with a *.c file extension
is non-sense; such files should have a .cc (or maybe .cpp or .cxx) extension, 
not a .c extension.

Regards.
-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***

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

* Re: [patch]  Create gimple-expr..[ch]  ...  was Re: RFC: gimple.[ch] break apart
  2013-11-07 10:58   ` Basile Starynkevitch
@ 2013-11-07 13:47     ` Andrew MacLeod
  2013-11-07 18:13       ` Diego Novillo
  0 siblings, 1 reply; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-07 13:47 UTC (permalink / raw)
  To: Basile Starynkevitch; +Cc: gcc-patches, Richard Biener, Jeff Law, Diego Novillo

On 11/07/2013 05:36 AM, Basile Starynkevitch wrote:
> On Tue, Nov 05, 2013 at 11:26:46AM -0500, Andrew MacLeod wrote:
>> I decided to name the new file gimple-expr.[ch] instead of
>> gimple-decl....   This will eventually split into gimple-type.[ch],
>> gimple-decl.[ch], and gimple-expr.[ch].
>
> Since we are adding *new* C++ files, can't we please name them *.cc
> for the implementation part, so at least create gimple-expr.h and
> gimple-expr.cc but not gimple-expr.c, please!
Assuming we put this into stage 1 next year,  I would imagine we'd 
rename a number of things, including .cc, drop the tree-* from the 
tree-ssa-blah.[c]h files, etc etc.  There have been a few things people 
have suggested renaming... I think if we do renaming, they ought to be 
all at one time to minimize the pain.

At the moment, the new gimple-* files I'm creating are still C, so they 
are .c files...

Andrew

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-07 10:29             ` Richard Biener
@ 2013-11-07 14:01               ` Joseph S. Myers
  2013-11-07 14:42                 ` Richard Biener
  2013-11-07 14:53               ` Andrew MacLeod
  1 sibling, 1 reply; 116+ messages in thread
From: Joseph S. Myers @ 2013-11-07 14:01 UTC (permalink / raw)
  To: Richard Biener
  Cc: Andrew MacLeod, Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches

On Thu, 7 Nov 2013, Richard Biener wrote:

> Well, I'm betting that you'll re-invent sth like 'tree' just don't
> call it 'tree' ;)
> You need to transparently refer to constants, SSA names and decls
> (at least) as GIMPLE statement operands.  You probably will make
> a "gimple statement operand" base class.  Well - that's a 'tree' ;)

Uses of constants and decls in expressions are why it's not obvious that 
those get a static type different from expressions (or at least, they 
probably do need a common base class).  But my model of how "tree" should 
ideally be split up has expressions (maybe including decls) as a 
completely separate static type from types, and identifiers as yet another 
static type, none of those inheriting from a common base class "tree".

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-07 14:01               ` Joseph S. Myers
@ 2013-11-07 14:42                 ` Richard Biener
  0 siblings, 0 replies; 116+ messages in thread
From: Richard Biener @ 2013-11-07 14:42 UTC (permalink / raw)
  To: Joseph S. Myers
  Cc: Andrew MacLeod, Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches

On Thu, Nov 7, 2013 at 2:44 PM, Joseph S. Myers <joseph@codesourcery.com> wrote:
> On Thu, 7 Nov 2013, Richard Biener wrote:
>
>> Well, I'm betting that you'll re-invent sth like 'tree' just don't
>> call it 'tree' ;)
>> You need to transparently refer to constants, SSA names and decls
>> (at least) as GIMPLE statement operands.  You probably will make
>> a "gimple statement operand" base class.  Well - that's a 'tree' ;)
>
> Uses of constants and decls in expressions are why it's not obvious that
> those get a static type different from expressions (or at least, they
> probably do need a common base class).  But my model of how "tree" should
> ideally be split up has expressions (maybe including decls) as a
> completely separate static type from types, and identifiers as yet another
> static type, none of those inheriting from a common base class "tree".

Sure.  Also you make containers no longer trees (TREE_CHAIN
anyone, TREE_VEC, TREE_LIST ...).  Should be the first step
I think (already started some time ago with using VECs for some
pieces).

Richard.

> --
> Joseph S. Myers
> joseph@codesourcery.com

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-07 10:29             ` Richard Biener
  2013-11-07 14:01               ` Joseph S. Myers
@ 2013-11-07 14:53               ` Andrew MacLeod
  1 sibling, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-07 14:53 UTC (permalink / raw)
  To: Richard Biener; +Cc: Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches

On 11/07/2013 05:08 AM, Richard Biener wrote:
>
>> 2 - I really believe gimple needs a type system different from front end
>> trees, that is my primary motivation.  I'm tired of jumping through hoops to
>> do anything slightly different, and I got fed up with it.  With a separate
>> type system for gimple, we can rid ourselves of all the stuff that isn't
>> related to optimization and codegen...   Could we do this with trees?
>> possibly, but if I'm going to go to the effort of converting the front end
>> tree types into a new or reduced-type subset, I might as well put that
>> effort into something that is more appropriate right from the start.
> I'm not sure.  Especially the idea of wrapping everything in a
> I'm-not-a-tree-well-but-I-really-still-am scares the hell out of me.
> And I put that into the very same basket of things you now complain about.

Well, this first phase is a transitional one... If it were possible, I'd 
change them all at once to not use a tree... but I don't think that is 
feasible. There is too much to find and change, and the source base is 
constantly changing.  We can't just freeze the base for a year.   so 
until I can get them all changes, they have to act like trees and 
interact like trees, so we make them trees under the covers.   Short 
term pain and discomfort...

If it helps, during the transition you can view it as replacing trees 
with oddly named tree subclasses which provide static type checking 
instead of run time GIMPLE_CHECK() calls :-)



>> By replacing those uses with an actual type, we'll get
>> static type checking which is another improvement.   There is only one way
>> to move the middle/back end off of types as trees that I can see.  Go
>> through the source base and find all the places which use trees as types,
>> and replace them with an actual type.  This can't be done all at once, its
>> too big a job...  So I propose a plan which allows a new gimple type and
>> current trees to coexist.  Once the conversion is complete we can easily
>> implement a type system that has the features and traits we want.
> Note that on 'gimple' there are no types ... the types are on the objects
> 'gimple' refers to and those are 'tree's.  So you'd need to change the
> 'tree's to have TREE_TYPE not be a 'tree'.  Or simply subclass
> 'tree' so you can distinguish a tree type from a tree non-type statically
> (a bit awkward with the current union setup).
>
> But maybe I'm confusing what you call 'type'.

Im talking about changing the type gimple statements refer to, and also 
what decls and expressions will refer to...  making that the gimple_type.

  Today, thats a TREE_TYPE tree.  During the transition period this 
gimple_type is indeed a tree under the covers.. so that all the existing 
code can work even if it hasnt been converted yet.   Once everything is 
converted, then gimple_type has the tree removed from its declaration 
and we replace it with the bits we need/want... and it will no longer 
function as a tree..  gimplification will create these from the trees 
the front end created.



>> 4 - I realized that if I am going through the entire code base to find all
>> the type locations, its very little extra work to also do the same for decls
>> and expressions. Then we'll have static type checking for those as well.
>>
>> 5 - When done we will be significantly closer to having the ability to
>> create a self contained IL that we can strictly define...  That alone seems
>> a worthwhile goal to me.  The IL then becomes appropriate for streaming at
>> any point in during compilation.  This means any front end or tool can
>> easily generate or consume a gimple stream which opens up numerous
>> opportunities...  That is pretty hard to enable today.
> Have fun with dealing with our legacy frontends ;)  Or didn't you
> actually mean "any point" during compilation? ... oh, you talk about
> GIMPLE.  So no plans for Frontend ASTs aka GENERIC for our legacy
> frontends?
I meant any point where we are in gimple...  Thats the only point we 
really care about.  Once control is passed to the middle end.  No plans 
to touch GENERIC at all... in fact, GENERIC and 'tree' will become true 
synonyms when I'm done, because gimple wont have any trees in it 
anywhere.  And rtl will also refer to gimple nodes.   It just wont 
matter what warts are in trees.
>> Im going to do the initial bits on a branch for the first couple of months,
>> and during that time convert a number of files over to the new gimple
>> interface.  Then we can look at it, measure it, comment on it, tweak it,
>> whatever.  You can see exactly what we'll be getting into before we fully
>> commit.
> Before we fully commit we want to see the underlying object changes.
> Because I still doubt this all will work out without seriously restructuring
> the entanglement of our tree-based frontends and the middle-end
> (say "fold").
>
> That is, I still think you are starting this at the wrong end.  You first
> need to solve the entanglement issue before you can seriously consider
> making any real change to the data structures GIMPLE relies on.

That is part of the experiment.  RIght now I don't know for sure what 
the real issues will be. I learned a valuable lesson long time ago...  
measure a problem to determine the cause rather than assume you know 
where it is.  This process will show exactly where there are 
entanglements are that need to be dealt with.    It may be that by the 
time stage 1 rolls around, I will have identified a few other things 
that really need to be addressed first.  And then I'll  then work to 
address them.

Fold is indeed one of them, but that is one of the reasons why there is 
also a plan in motion (sort of) to reduce the folding in the front end 
to a bare minimum...   and either have its own minimal folder, or 
provide an interface through gimplification to a gimple folder to do 
what it needs.   This is all in the original document.

The operating theory is that  front ends can do whatever the do today, 
and the gimplification process will turn trees into whatever gimple 
object is needed:  expr, decl, type, whatever.   Today, gimplification 
only addresses turning tcc_statement trees into gimple statements.   
What I am proposing effectively does this for all the rest of the tree 
class nodes.



>>   I think it will be an improvement over what we have today and much
>> easier to work with. If the consensus is that it bites, then we leave it on
>> the branch, and what have we lost?  a few months of my time and we've gained
>> some really useful knowledge.
>>
>> And no, if I can get trees out of gimple, I don't intend to ever touch them
>> again! :-)
> Well, I'm betting that you'll re-invent sth like 'tree' just don't
> call it 'tree' ;)
> You need to transparently refer to constants, SSA names and decls
> (at least) as GIMPLE statement operands.  You probably will make
> a "gimple statement operand" base class.  Well - that's a 'tree' ;)
>
>
Certainly at the beginning when I have to mimic trees there will be a 
base gimple_operand of some sort  which is effectively a 'typed' 
node...  It's required for compatibility.  But once trees are no longer 
required, we are then free to change this.    The definition of a 
gimple_stmt can remove the operand array of 'like objects' (ie trees), 
and replace it with more context..

One possibility is that gimple_assign could be expanded to have multiple 
forms of statically typed operands inheriting from the gimple_assign 
class...   ie.
decl = const,
decl = decl op const      (or possibly just decl = gimple_2op_expr or 
some such thing.. i dont know what gimple_exprs will look like yet)
decl = decl
mem_expr = const
etc.
and whatever else is needed.  This will help define and enforce a formal 
definition of the gimple IL...

There are other options, but which one to use would be best determined 
once we have a handle on the other gimple objects and, more 
importantly,  the ability to change their behaviour.

  Andrew

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-07  6:19         ` David Malcolm
  2013-11-07  7:08           ` Jeff Law
@ 2013-11-07 14:57           ` Michael Matz
  1 sibling, 0 replies; 116+ messages in thread
From: Michael Matz @ 2013-11-07 14:57 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrew MacLeod, Jeff Law, gcc-patches

Hi,

On Wed, 6 Nov 2013, David Malcolm wrote:

> > I don't like that.  The empty classes are just useless, they imply a 
> > structure that isn't really there, some of the separate gimple codes 
> > are basically selectors of specific subtypes of a generic concept, 
> > without additional data or methods; creating a type for those is 
> > confusing.
> 
> A type system does more than just express memory layouts:

I know all that.  But there's a point on the scale from a void* type 
system to a different-type-for-everything system where the advantages of a 
more complex type system are anulled by the disadvantages of a more 
complex type system.  And I'm merely of the opinion that you crossed that 
point with this separation.

You know we could have a typesystem where every different natural number 
is a type (and with C++ we _really_ could do that).  Obviously that's also 
a reductio ad absurdum, but it demonstrates the point that there _are_ 
type systems with a too low complexity to expressiveness ratio.

> * it permits the proof of absence of certain bugs
> * it supports abstraction
> * it documents the intent of the code

Well, yes.  You can document code with other things than types, you can 
add abstractions via different means, and certain bugs can indeed only be 
ruled out by different static types.

In my mind types should abstract different larger concepts foremost (and 
not every little aspect of a concept).  Only _then_ should they be used 
for other effects like the above, and only if the disadvantages don't 
overshadow that.  Disadvantages being mostly simply more complexity: which 
types relate to others in which way; what are the methods you can do with 
that but not the other type; which are the members of the 100 types there 
are (and if a type system is too large to be used only by IDEs with code 
completion, then it's too complex); and of course also simply having to 
write more text when you can't use the same gimple variable for several 
statements.

> To give an example from the patch, the proposed gimple_statement_switch
> subclass of gimple_statement_with_ops adds no extra fields, but it adds
> the invariant that (assuming the ptr is non-NULL), that code ==
> GIMPLE_SWITCH, or, more intuitively, "it's a switch statement".
> 
> This means that if we have a gimple_statement_switch, that both a human
> reading the code and the compiler can "know" at compile-time that the
> code == GIMPLE_SWITCH. 

But a gimple switch is actually a special case of a gimple conditional 
jump (the normal GIMPLE_COND being another) which itself is a special 
case of a gimple control transfer (a thing causing one or multiple 
outgoing edges and ending a basic block).  That enlightens that your 
hierarchy might not actually be the best split of types, it's merely a 
formal translation of gimple codes into types.

And I question exactly that automatic introduction of types.  There's not 
enough human thought put into the hierarchy to warrant the change.  Types 
are a fundament and they shouldn't be introduced lightly.  As gimple codes 
are simply flat it doesn't matter so much that the inherent structure of 
gimple statements isn't reflected (although there _is_ some structure by 
having the with_ops and with_mem_ops codes be together).  But for a _type 
hierarchy_ I would pretty much require that real thought and insights are 
put into it.

> Consider tree-switch-conversion.c: this contains various "gimple"
> variables but they don't work on arbitrary gimple; they require code ==
> GIMPLE_SWITCH:
> ...
> We could be doing this directly in the type system, and using the
> compiler to check it.

Then please do that while introducing one new type.

> >   The fewer 
> > types the better IMO.
> 
> There's a reductio ad absurdum of that argument:

See above for my variant of that showing that it also goes into the other 
direction of more types.


Ciao,
Michael.
P.S.: And do away with the "_statement" part of the type, gimple_switch 
ought to be enough.

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

* Re: [patch] Create gimple-expr..[ch] ... was Re: RFC: gimple.[ch] break apart
  2013-11-07 13:47     ` Andrew MacLeod
@ 2013-11-07 18:13       ` Diego Novillo
  0 siblings, 0 replies; 116+ messages in thread
From: Diego Novillo @ 2013-11-07 18:13 UTC (permalink / raw)
  To: Andrew MacLeod
  Cc: Basile Starynkevitch, gcc-patches, Richard Biener, Jeff Law

On Thu, Nov 7, 2013 at 8:23 AM, Andrew MacLeod <amacleod@redhat.com> wrote:
> On 11/07/2013 05:36 AM, Basile Starynkevitch wrote:
>>
>> On Tue, Nov 05, 2013 at 11:26:46AM -0500, Andrew MacLeod wrote:
>>>
>>> I decided to name the new file gimple-expr.[ch] instead of
>>> gimple-decl....   This will eventually split into gimple-type.[ch],
>>> gimple-decl.[ch], and gimple-expr.[ch].
>>
>>
>> Since we are adding *new* C++ files, can't we please name them *.cc
>> for the implementation part, so at least create gimple-expr.h and
>> gimple-expr.cc but not gimple-expr.c, please!
>
> Assuming we put this into stage 1 next year,  I would imagine we'd rename a
> number of things, including .cc, drop the tree-* from the tree-ssa-blah.[c]h
> files, etc etc.  There have been a few things people have suggested
> renaming... I think if we do renaming, they ought to be all at one time to
> minimize the pain.
>
> At the moment, the new gimple-* files I'm creating are still C, so they are
> .c files...

Agreed. When we start shuffling files around seems a better time.
Doing both operations at once will be easier than going through two
phases of naming changes.


Diego.

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-06 16:53       ` Michael Matz
  2013-11-07  6:19         ` David Malcolm
@ 2013-11-08  0:07         ` Alec Teal
  2013-11-08 14:31           ` Michael Matz
  1 sibling, 1 reply; 116+ messages in thread
From: Alec Teal @ 2013-11-08  0:07 UTC (permalink / raw)
  To: Michael Matz; +Cc: David Malcolm, Andrew MacLeod, gcc-patches

Hello

On 06/11/13 15:32, Michael Matz wrote:
> Hi,
>
> On Tue, 5 Nov 2013, David Malcolm wrote:
>
>> Here's a followup patch which ensures that every gimple code has its own
>> subclass, by adding empty subclasses derived from the GSS_-based
>> subclasses as appropriate (I don't bother for gimple codes that already
>> have their own subclass due to having their own GSS layout).  I also
>> copied the comments from gimple.def into gimple.h, so that Doxygen picks
>> up on the descriptions and uses them to describe each subclass.
> I don't like that.  The empty classes are just useless, they imply a
> structure that isn't really there, some of the separate gimple codes are
> basically selectors of specific subtypes of a generic concept, without
> additional data or methods; creating a type for those is confusing.
>
> Generally I don't like complicating the type system without good reasons
> (as in actually also making use of the complicated types).  The fewer
> types the better IMO.
How would you do this? The types are different even if there is no 
actual difference, much like there are different gimple codes in the 
first place.
He is trying to create a bijection between what we did have and what we 
now have so nothing breaks.
>
>
> Ciao,
> Michael.

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-08  0:07         ` Alec Teal
@ 2013-11-08 14:31           ` Michael Matz
  0 siblings, 0 replies; 116+ messages in thread
From: Michael Matz @ 2013-11-08 14:31 UTC (permalink / raw)
  To: Alec Teal; +Cc: David Malcolm, Andrew MacLeod, gcc-patches

Hi,

On Thu, 7 Nov 2013, Alec Teal wrote:

> > > subclass, by adding empty subclasses derived from the GSS_-based
> > > subclasses as appropriate (I don't bother for gimple codes that already
> > > have their own subclass due to having their own GSS layout).  I also
> > > copied the comments from gimple.def into gimple.h, so that Doxygen picks
> > > up on the descriptions and uses them to describe each subclass.
> > I don't like that.  The empty classes are just useless, they imply a
> > structure that isn't really there, some of the separate gimple codes are
> > basically selectors of specific subtypes of a generic concept, without
> > additional data or methods; creating a type for those is confusing.
> > 
> > Generally I don't like complicating the type system without good reasons
> > (as in actually also making use of the complicated types).  The fewer
> > types the better IMO.
> How would you do this?

How would I do what?  Making use of new types?  Well, like the opportunity 
that David already identified in tree-switching, I'd introduce the new 
type together with a patch to that pass to make use of it.  Further I'd 
try to think about how that new type represents a concept, how that would 
be generalized, and how it would fit in a really designed type hierarchy 
of gimple statements.  Then I would try to think about interaction of 
those new types with others we already have, in particular containers 
(should those become specialized as well?  I would say no from my gut, but 
that question does need some pondering).

> The types are different even if there is no actual difference, much like 
> there are different gimple codes in the first place. He is trying to 
> create a bijection between what we did have and what we now have

Yes, I understood that, and that's IMO the wrong way to introduce new 
types.  It really deserves some more than "we have these dozen gimple 
codes, let's create a dozen new types".  So, while a bijection between 
codes and types is simple to create, I'm pretty sure that's not the best 
mapping.

> so nothing breaks.

Currently nothing is broken, so that's certainly not the reason to 
introduce new types.


Ciao,
Michael.

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-07  7:08           ` Jeff Law
@ 2013-11-08 19:23             ` David Malcolm
  2013-11-14  8:38               ` Jeff Law
  0 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-11-08 19:23 UTC (permalink / raw)
  To: Jeff Law; +Cc: Michael Matz, Andrew MacLeod, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4221 bytes --]

On Wed, 2013-11-06 at 22:32 -0700, Jeff Law wrote:
> [ Just a note, of this reply is meant for Michael and other parts for 
> David, hopefully the audience is clear from the context. ]
> 
> On 11/06/13 21:56, David Malcolm wrote:
> > On Wed, 2013-11-06 at 16:32 +0100, Michael Matz wrote:
> >> Hi,
> >>
> >> On Tue, 5 Nov 2013, David Malcolm wrote:
> >>
> >>> Here's a followup patch which ensures that every gimple code has its own
> >>> subclass, by adding empty subclasses derived from the GSS_-based
> >>> subclasses as appropriate (I don't bother for gimple codes that already
> >>> have their own subclass due to having their own GSS layout).  I also
> >>> copied the comments from gimple.def into gimple.h, so that Doxygen picks
> >>> up on the descriptions and uses them to describe each subclass.
> >>
> >> I don't like that.  The empty classes are just useless, they imply a
> >> structure that isn't really there, some of the separate gimple codes are
> >> basically selectors of specific subtypes of a generic concept, without
> >> additional data or methods; creating a type for those is confusing.
> >
> > A type system does more than just express memory layouts:
> > * it permits the proof of absence of certain bugs
> Right.  As you have probably surmised, this is the single biggest thing 
> we get from this work in my mind.  We use the type system to ensure a 
> certain class of bugs simply won't get through the compilation phase.
> 
> That's a significant and important change from where we are now.  Right 
> now we have no way of knowing that at compile time.  Instead we rely 
> upon an insane set of macros to check this kind of invariant at run 
> time.  Note carefully just because we don't hit a checking failure 
> doesn't mean the code is safe.  It just means we haven't found a set of 
> preconditions necessary to trip the problem at runtime.  Obviously in 
> some (many), where may be no such way to trigger the failure, but 
> there's no way to prove it.
> 
> Don't get me wrong the checking macros, when they were introduced were a 
> godsend.  But they're papering over a fundamental problems in GCC's 
> internal representations.
> 
> I think it's hard to overestimate the value we get by moving this stuff 
> into compile-time type checking.
> 
> 
> > I can post a followup patch that makes use of each of these, if it will
> > help.
> I wouldn't mind seeing a small example proof of concept posted to help 
> those who don't see where this is going understand the goal.  I would 
> recommend against posting another large patch for inclusion at this time.
Attached is a proof-of-concept patch which uses the
gimple_statement_switch subclass (as a "gimple_switch" typedef).  This
is one of the subclasses that the earlier patch added, which has no new
fields, but which carries the invariant that, if non-NULL,
   gimple_code (gs) == GIMPLE_SWITCH.

The patch adds compile-time type-checking for places where switch
statements are handled.  For example, in tree-vrp.c's switch_update:
 typedef struct {
-  gimple stmt;
+  gimple_switch stmt;
   tree vec;
 } switch_update;

we can capture the fact that the statements have code GIMPLE_SWITCH.

I was able to make 7 of the 9 gimple_switch_* accessors accept a
gimple_switch rather than a gimple, hence adding compile-time typesafety
for these.  We could do all of them, but doing the remaining two would
enlarge the patch (I did the ones where the site of the downcast already
has enclosing braces handy to scope the subclass pointer).

I kept the run-time checking in those accessors, though arguably they're
redundant.

I deliberately used a C style for the downcast from gimple to a more
specialized type, eschewing the dyn_cast<> template, though IMHO the
latter is a better style.   Perhaps a specialized dyncast method to
gimple would be more acceptable e.g.:

struct GTY((etc)) gimple statement_base {
   [...]

   gimple_switch is_switch () const
   {
	if (gimple_code (this) == GIMPLE_SWITCH)
	   return (gimple_switch)this;
        else
	   return NULL;
   }
};

allowing us to spell a dynamic cast like this:
   if (gimple_switch switch_stmt = stmt->is_switch ())
     {
	/* do typesafe stuff with switch_stmt */
     }



[-- Attachment #2: gimple-switch.patch --]
[-- Type: text/x-patch, Size: 30194 bytes --]

commit b9e2375b4250428cc20e83c9be9be80afbfcb388
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Thu Nov 7 21:32:15 2013 -0500

    Use gimple_switch in various places

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index fb05ce7..cc2d4d7 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2221,7 +2221,7 @@ expand_gimple_stmt_1 (gimple stmt)
     case GIMPLE_PREDICT:
       break;
     case GIMPLE_SWITCH:
-      expand_case (stmt);
+      expand_case ((gimple_switch)stmt);
       break;
     case GIMPLE_ASM:
       expand_asm_stmt (stmt);
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 5a5cfbb..a72ebb4 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -69,6 +69,9 @@ typedef struct gimple_stmt_iterator_d gimple_stmt_iterator;
 /* FWIW I'd rather simply have the class be called "gimple_call", and
    make the pointerness be explicit rather than implicit.  */
 typedef struct gimple_statement_call *gimple_call;
+typedef const struct gimple_statement_call *const_gimple_call;
+typedef struct gimple_statement_switch *gimple_switch;
+typedef const struct gimple_statement_switch *const_gimple_switch;
 union section;
 typedef union section section;
 struct gcc_options;
diff --git a/gcc/expr.h b/gcc/expr.h
index 56f504a..f5bed84 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -734,7 +734,7 @@ rtx get_personality_function (tree);
 /* In stmt.c */
 
 /* Expand a GIMPLE_SWITCH statement.  */
-extern void expand_case (gimple);
+extern void expand_case (gimple_switch);
 
 /* Like expand_case but special-case for SJLJ exception dispatching.  */
 extern void expand_sjlj_dispatch_table (rtx, vec<tree> );
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index b9bbdc7..690b43e 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -763,7 +763,7 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
    pp_gimple_stmt_1.  */
 
 static void
-dump_gimple_switch (pretty_printer *buffer, gimple gs, int spc, int flags)
+dump_gimple_switch (pretty_printer *buffer, gimple_switch gs, int spc, int flags)
 {
   unsigned int i;
 
@@ -2100,7 +2100,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
       break;
 
     case GIMPLE_SWITCH:
-      dump_gimple_switch (buffer, gs, spc, flags);
+      dump_gimple_switch (buffer, (gimple_switch)gs, spc, flags);
       break;
 
     case GIMPLE_TRY:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index a128582..f182d0e 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -822,13 +822,14 @@ gimple_build_resx (int region)
    NLABELS is the number of labels in the switch excluding the default.
    DEFAULT_LABEL is the default label for the switch statement.  */
 
-gimple
+gimple_switch
 gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
 {
   /* nlabels + 1 default label + 1 index.  */
   gcc_checking_assert (default_label);
-  gimple p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
-				    1 + 1 + nlabels);
+  gimple_switch p =
+    (gimple_switch)gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
+					  1 + 1 + nlabels);
   gimple_switch_set_index (p, index);
   gimple_switch_set_default_label (p, default_label);
   return p;
@@ -840,12 +841,12 @@ gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
    DEFAULT_LABEL is the default label
    ARGS is a vector of labels excluding the default.  */
 
-gimple
+gimple_switch
 gimple_build_switch (tree index, tree default_label, vec<tree> args)
 {
   unsigned i, nlabels = args.length ();
 
-  gimple p = gimple_build_switch_nlabels (nlabels, index, default_label);
+  gimple_switch p = gimple_build_switch_nlabels (nlabels, index, default_label);
 
   /* Copy the labels from the vector to the switch statement.  */
   for (i = 0; i < nlabels; i++)
diff --git a/gcc/gimple.h b/gcc/gimple.h
index cd9f89f..63827a6 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1538,8 +1538,8 @@ gimple_statement_try *gimple_build_try (gimple_seq, gimple_seq,
 gimple gimple_build_wce (gimple_seq);
 gimple gimple_build_resx (int);
 gimple gimple_build_eh_dispatch (int);
-gimple gimple_build_switch_nlabels (unsigned, tree, tree);
-gimple gimple_build_switch (tree, tree, vec<tree> );
+gimple_switch gimple_build_switch_nlabels (unsigned, tree, tree);
+gimple_switch gimple_build_switch (tree, tree, vec<tree> );
 gimple gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
 gimple gimple_build_omp_task (gimple_seq, tree, tree, tree, tree, tree, tree);
 gimple gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq);
@@ -4592,7 +4592,7 @@ gimple_eh_dispatch_set_region (gimple gs, int region)
 /* Return the number of labels associated with the switch statement GS.  */
 
 static inline unsigned
-gimple_switch_num_labels (const_gimple gs)
+gimple_switch_num_labels (const_gimple_switch gs)
 {
   unsigned num_ops;
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
@@ -4605,7 +4605,7 @@ gimple_switch_num_labels (const_gimple gs)
 /* Set NLABELS to be the number of labels for the switch statement GS.  */
 
 static inline void
-gimple_switch_set_num_labels (gimple g, unsigned nlabels)
+gimple_switch_set_num_labels (gimple_switch g, unsigned nlabels)
 {
   GIMPLE_CHECK (g, GIMPLE_SWITCH);
   gimple_set_num_ops (g, nlabels + 1);
@@ -4635,7 +4635,7 @@ gimple_switch_index_ptr (const_gimple gs)
 /* Set INDEX to be the index variable for switch statement GS.  */
 
 static inline void
-gimple_switch_set_index (gimple gs, tree index)
+gimple_switch_set_index (gimple_switch gs, tree index)
 {
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
   gcc_gimple_checking_assert (SSA_VAR_P (index) || CONSTANT_CLASS_P (index));
@@ -4647,7 +4647,7 @@ gimple_switch_set_index (gimple gs, tree index)
    labels in a switch statement.  */
 
 static inline tree
-gimple_switch_label (const_gimple gs, unsigned index)
+gimple_switch_label (const_gimple_switch gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
   gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 1);
@@ -4657,7 +4657,7 @@ gimple_switch_label (const_gimple gs, unsigned index)
 /* Set the label number INDEX to LABEL.  0 is always the default label.  */
 
 static inline void
-gimple_switch_set_label (gimple gs, unsigned index, tree label)
+gimple_switch_set_label (gimple_switch gs, unsigned index, tree label)
 {
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
   gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 1
@@ -4669,7 +4669,7 @@ gimple_switch_set_label (gimple gs, unsigned index, tree label)
 /* Return the default label for a switch statement.  */
 
 static inline tree
-gimple_switch_default_label (const_gimple gs)
+gimple_switch_default_label (const_gimple_switch gs)
 {
   tree label = gimple_switch_label (gs, 0);
   gcc_checking_assert (!CASE_LOW (label) && !CASE_HIGH (label));
@@ -4679,7 +4679,7 @@ gimple_switch_default_label (const_gimple gs)
 /* Set the default label for a switch statement.  */
 
 static inline void
-gimple_switch_set_default_label (gimple gs, tree label)
+gimple_switch_set_default_label (gimple_switch gs, tree label)
 {
   gcc_checking_assert (!CASE_LOW (label) && !CASE_HIGH (label));
   gimple_switch_set_label (gs, 0, label);
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 83bd479..8958f1f 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -1765,7 +1765,7 @@ set_switch_stmt_execution_predicate (struct ipa_node_params *info,
 				     struct inline_summary *summary,
 				     basic_block bb)
 {
-  gimple last;
+  gimple lastg;
   tree op;
   int index;
   struct agg_position_info aggpos;
@@ -1774,9 +1774,10 @@ set_switch_stmt_execution_predicate (struct ipa_node_params *info,
   size_t n;
   size_t case_idx;
 
-  last = last_stmt (bb);
-  if (!last || gimple_code (last) != GIMPLE_SWITCH)
+  lastg = last_stmt (bb);
+  if (!lastg || gimple_code (lastg) != GIMPLE_SWITCH)
     return;
+  gimple_switch last = (gimple_switch)lastg;
   op = gimple_switch_index (last);
   if (!unmodified_parm_or_parm_agg_item (info, last, op, &index, &aggpos))
     return;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 3b7882d..4ef1f4c 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -10324,10 +10324,11 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
 
     case GIMPLE_SWITCH:
       {
+	gimple_switch switch_stmt = (gimple_switch)stmt;
 	unsigned int i;
-	for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
+	for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
 	  {
-	    tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
+	    tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
 	    n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
 	    if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
 	      break;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index b3fd255..1d7298b 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -2010,7 +2010,7 @@ reset_out_edges_aux (basic_block bb)
    STMT. Record this information in the aux field of the edge.  */
 
 static inline void
-compute_cases_per_edge (gimple stmt)
+compute_cases_per_edge (gimple_switch stmt)
 {
   basic_block bb = gimple_bb (stmt);
   reset_out_edges_aux (bb);
@@ -2032,7 +2032,7 @@ compute_cases_per_edge (gimple stmt)
    Generate the code to test it and jump to the right place.  */
 
 void
-expand_case (gimple stmt)
+expand_case (gimple_switch stmt)
 {
   tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
   rtx default_label = NULL_RTX;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 8d82342..3cbb232 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -141,7 +141,7 @@ static void factor_computed_gotos (void);
 static void make_edges (void);
 static void assign_discriminators (void);
 static void make_cond_expr_edges (basic_block);
-static void make_gimple_switch_edges (basic_block);
+static void make_gimple_switch_edges (gimple_switch, basic_block);
 static void make_goto_expr_edges (basic_block);
 static void make_gimple_asm_edges (basic_block);
 static edge gimple_redirect_edge_and_branch (edge, basic_block);
@@ -161,8 +161,8 @@ static bool gimple_can_merge_blocks_p (basic_block, basic_block);
 static void remove_bb (basic_block);
 static edge find_taken_edge_computed_goto (basic_block, tree);
 static edge find_taken_edge_cond_expr (basic_block, tree);
-static edge find_taken_edge_switch_expr (basic_block, tree);
-static tree find_case_label_for_value (gimple, tree);
+static edge find_taken_edge_switch_expr (gimple_switch, basic_block, tree);
+static tree find_case_label_for_value (gimple_switch, tree);
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -644,7 +644,7 @@ make_edges (void)
 	      fallthru = false;
 	      break;
 	    case GIMPLE_SWITCH:
-	      make_gimple_switch_edges (bb);
+	      make_gimple_switch_edges ((gimple_switch)last, bb);
 	      fallthru = false;
 	      break;
 	    case GIMPLE_RESX:
@@ -892,7 +892,7 @@ end_recording_case_labels (void)
 	{
 	  gimple stmt = last_stmt (bb);
 	  if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
-	    group_case_labels_stmt (stmt);
+	    group_case_labels_stmt ((gimple_switch)stmt);
 	}
     }
   BITMAP_FREE (touched_switch_bbs);
@@ -904,7 +904,7 @@ end_recording_case_labels (void)
    Otherwise return NULL.  */
 
 static tree
-get_cases_for_edge (edge e, gimple t)
+get_cases_for_edge (edge e, gimple_switch t)
 {
   void **slot;
   size_t i, n;
@@ -943,9 +943,8 @@ get_cases_for_edge (edge e, gimple t)
 /* Create the edges for a GIMPLE_SWITCH starting at block BB.  */
 
 static void
-make_gimple_switch_edges (basic_block bb)
+make_gimple_switch_edges (gimple_switch entry, basic_block bb)
 {
-  gimple entry = last_stmt (bb);
   size_t i, n;
 
   n = gimple_switch_num_labels (entry);
@@ -1238,12 +1237,13 @@ cleanup_dead_labels (void)
 
 	case GIMPLE_SWITCH:
 	  {
-	    size_t i, n = gimple_switch_num_labels (stmt);
+	    gimple_switch switch_stmt = (gimple_switch)stmt;
+	    size_t i, n = gimple_switch_num_labels (switch_stmt);
 
 	    /* Replace all destination labels.  */
 	    for (i = 0; i < n; ++i)
 	      {
-		tree case_label = gimple_switch_label (stmt, i);
+		tree case_label = gimple_switch_label (switch_stmt, i);
 		label = CASE_LABEL (case_label);
 		new_label = main_block_label (label);
 		if (new_label != label)
@@ -1340,7 +1340,7 @@ cleanup_dead_labels (void)
    Eg. three separate entries 1: 2: 3: become one entry 1..3:  */
 
 void
-group_case_labels_stmt (gimple stmt)
+group_case_labels_stmt (gimple_switch stmt)
 {
   int old_size = gimple_switch_num_labels (stmt);
   int i, j, new_size = old_size;
@@ -1428,7 +1428,7 @@ group_case_labels (void)
     {
       gimple stmt = last_stmt (bb);
       if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
-	group_case_labels_stmt (stmt);
+	group_case_labels_stmt ((gimple_switch)stmt);
     }
 }
 
@@ -1895,7 +1895,7 @@ find_taken_edge (basic_block bb, tree val)
     return find_taken_edge_cond_expr (bb, val);
 
   if (gimple_code (stmt) == GIMPLE_SWITCH)
-    return find_taken_edge_switch_expr (bb, val);
+    return find_taken_edge_switch_expr ((gimple_switch)stmt, bb, val);
 
   if (computed_goto_p (stmt))
     {
@@ -1954,14 +1954,13 @@ find_taken_edge_cond_expr (basic_block bb, tree val)
    NULL if any edge may be taken.  */
 
 static edge
-find_taken_edge_switch_expr (basic_block bb, tree val)
+find_taken_edge_switch_expr (gimple_switch switch_stmt, basic_block bb,
+			     tree val)
 {
   basic_block dest_bb;
   edge e;
-  gimple switch_stmt;
   tree taken_case;
 
-  switch_stmt = last_stmt (bb);
   taken_case = find_case_label_for_value (switch_stmt, val);
   dest_bb = label_to_block (CASE_LABEL (taken_case));
 
@@ -1976,7 +1975,7 @@ find_taken_edge_switch_expr (basic_block bb, tree val)
    sorted: We can do a binary search for a case matching VAL.  */
 
 static tree
-find_case_label_for_value (gimple switch_stmt, tree val)
+find_case_label_for_value (gimple_switch switch_stmt, tree val)
 {
   size_t low, high, n = gimple_switch_num_labels (switch_stmt);
   tree default_case = gimple_switch_default_label (switch_stmt);
@@ -4089,7 +4088,7 @@ verify_gimple_goto (gimple stmt)
    is a problem, otherwise false.  */
 
 static bool
-verify_gimple_switch (gimple stmt)
+verify_gimple_switch (gimple_switch stmt)
 {
   unsigned int i, n;
   tree elt, prev_upper_bound = NULL_TREE;
@@ -4270,7 +4269,7 @@ verify_gimple_stmt (gimple stmt)
       return verify_gimple_goto (stmt);
 
     case GIMPLE_SWITCH:
-      return verify_gimple_switch (stmt);
+      return verify_gimple_switch ((gimple_switch)stmt);
 
     case GIMPLE_RETURN:
       return verify_gimple_return (stmt);
@@ -5000,26 +4999,27 @@ gimple_verify_flow_info (void)
 
 	case GIMPLE_SWITCH:
 	  {
+	    gimple_switch switch_stmt = (gimple_switch)stmt;
 	    tree prev;
 	    edge e;
 	    size_t i, n;
 
-	    n = gimple_switch_num_labels (stmt);
+	    n = gimple_switch_num_labels (switch_stmt);
 
 	    /* Mark all the destination basic blocks.  */
 	    for (i = 0; i < n; ++i)
 	      {
-		tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
+		tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
 		basic_block label_bb = label_to_block (lab);
 		gcc_assert (!label_bb->aux || label_bb->aux == (void *)1);
 		label_bb->aux = (void *)1;
 	      }
 
 	    /* Verify that the case labels are sorted.  */
-	    prev = gimple_switch_label (stmt, 0);
+	    prev = gimple_switch_label (switch_stmt, 0);
 	    for (i = 1; i < n; ++i)
 	      {
-		tree c = gimple_switch_label (stmt, i);
+		tree c = gimple_switch_label (switch_stmt, i);
 		if (!CASE_LOW (c))
 		  {
 		    error ("found default case not at the start of "
@@ -5065,7 +5065,7 @@ gimple_verify_flow_info (void)
 	    /* Check that we have all of them.  */
 	    for (i = 0; i < n; ++i)
 	      {
-		tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
+		tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
 		basic_block label_bb = label_to_block (lab);
 
 		if (label_bb->aux != (void *)2)
@@ -5253,8 +5253,9 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
 
     case GIMPLE_SWITCH:
       {
+	gimple_switch switch_stmt = (gimple_switch)stmt;
 	tree label = gimple_block_label (dest);
-        tree cases = get_cases_for_edge (e, stmt);
+        tree cases = get_cases_for_edge (e, switch_stmt);
 
 	/* If we have a list of cases associated with E, then use it
 	   as it's a lot faster than walking the entire case vector.  */
@@ -5275,7 +5276,7 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
 	       to move all the cases associated with E to E2.  */
 	    if (e2)
 	      {
-		tree cases2 = get_cases_for_edge (e2, stmt);
+		tree cases2 = get_cases_for_edge (e2, switch_stmt);
 
 		CASE_CHAIN (last) = CASE_CHAIN (cases2);
 		CASE_CHAIN (cases2) = first;
@@ -5284,11 +5285,11 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
 	  }
 	else
 	  {
-	    size_t i, n = gimple_switch_num_labels (stmt);
+	    size_t i, n = gimple_switch_num_labels (switch_stmt);
 
 	    for (i = 0; i < n; i++)
 	      {
-		tree elt = gimple_switch_label (stmt, i);
+		tree elt = gimple_switch_label (switch_stmt, i);
 		if (label_to_block (CASE_LABEL (elt)) == e->dest)
 		  CASE_LABEL (elt) = label;
 	      }
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index d6a5d8f..72e2637 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -33,7 +33,7 @@ extern basic_block label_to_block_fn (struct function *, tree);
 #define label_to_block(t) (label_to_block_fn (cfun, t))
 extern void make_abnormal_goto_edges (basic_block, bool);
 extern void cleanup_dead_labels (void);
-extern void group_case_labels_stmt (gimple);
+extern void group_case_labels_stmt (gimple_switch);
 extern void group_case_labels (void);
 extern void replace_uses_by (tree, tree);
 extern basic_block single_noncomplex_succ (basic_block bb);
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index c83229f..d62aa0a 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -704,7 +704,7 @@ maybe_record_in_goto_queue (struct leh_state *state, gimple stmt)
    of the labels will leave outer GIMPLE_TRY_FINALLY nodes. Verify this.  */
 
 static void
-verify_norecord_switch_expr (struct leh_state *state, gimple switch_expr)
+verify_norecord_switch_expr (struct leh_state *state, gimple_switch switch_expr)
 {
   struct leh_tf_state *tf = state->tf;
   size_t i, n;
@@ -2048,7 +2048,7 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
       break;
 
     case GIMPLE_SWITCH:
-      verify_norecord_switch_expr (state, stmt);
+      verify_norecord_switch_expr (state, (gimple_switch)stmt);
       break;
 
     case GIMPLE_TRY:
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index e4c80a7..bd74949 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3727,15 +3727,18 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
       break;
 
     case GIMPLE_SWITCH:
-      /* Take into account cost of the switch + guess 2 conditional jumps for
-         each case label.
-
-	 TODO: once the switch expansion logic is sufficiently separated, we can
-	 do better job on estimating cost of the switch.  */
-      if (weights->time_based)
-        cost = floor_log2 (gimple_switch_num_labels (stmt)) * 2;
-      else
-        cost = gimple_switch_num_labels (stmt) * 2;
+      {
+	gimple_switch switch_stmt = (gimple_switch)stmt;
+	/* Take into account cost of the switch + guess 2 conditional jumps for
+	   each case label.
+
+	   TODO: once the switch expansion logic is sufficiently separated, we can
+	   do better job on estimating cost of the switch.  */
+	if (weights->time_based)
+	  cost = floor_log2 (gimple_switch_num_labels (switch_stmt)) * 2;
+	else
+	  cost = gimple_switch_num_labels (switch_stmt) * 2;
+      }
       break;
 
     case GIMPLE_CALL:
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 353ce24..c0cd9ea 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -679,8 +679,9 @@ generate_loops_for_partition (struct loop *loop, partition_t partition,
 		}
 	      else if (gimple_code (stmt) == GIMPLE_SWITCH)
 		{
+		  gimple_switch switch_stmt = (gimple_switch)stmt;
 		  gimple_switch_set_index
-		      (stmt, CASE_LOW (gimple_switch_label (stmt, 1)));
+		      (switch_stmt, CASE_LOW (gimple_switch_label (switch_stmt, 1)));
 		  update_stmt (stmt);
 		}
 	      else
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 211bfcf..e563366 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1755,19 +1755,20 @@ record_edge_info (basic_block bb)
 
       if (gimple_code (stmt) == GIMPLE_SWITCH)
 	{
+	  gimple_switch switch_stmt = (gimple_switch)stmt;
 	  tree index = gimple_switch_index (stmt);
 
 	  if (TREE_CODE (index) == SSA_NAME)
 	    {
 	      int i;
-              int n_labels = gimple_switch_num_labels (stmt);
+              int n_labels = gimple_switch_num_labels (switch_stmt);
 	      tree *info = XCNEWVEC (tree, last_basic_block);
 	      edge e;
 	      edge_iterator ei;
 
 	      for (i = 0; i < n_labels; i++)
 		{
-		  tree label = gimple_switch_label (stmt, i);
+		  tree label = gimple_switch_label (switch_stmt, i);
 		  basic_block target_bb = label_to_block (CASE_LABEL (label));
 		  if (CASE_HIGH (label)
 		      || !CASE_LOW (label)
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 6ad45c9..116ab27 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1272,7 +1272,7 @@ simplify_not_neg_expr (gimple_stmt_iterator *gsi_p)
    have values outside the range of the new type.  */
 
 static void
-simplify_gimple_switch_label_vec (gimple stmt, tree index_type)
+simplify_gimple_switch_label_vec (gimple_switch stmt, tree index_type)
 {
   unsigned int branch_num = gimple_switch_num_labels (stmt);
   vec<tree> labels;
@@ -1345,7 +1345,7 @@ simplify_gimple_switch_label_vec (gimple stmt, tree index_type)
    the condition which we may be able to optimize better.  */
 
 static bool
-simplify_gimple_switch (gimple stmt)
+simplify_gimple_switch (gimple_switch stmt)
 {
   tree cond = gimple_switch_index (stmt);
   tree def, to, ti;
@@ -3502,7 +3502,7 @@ ssa_forward_propagate_and_combine (void)
 	      }
 
 	    case GIMPLE_SWITCH:
-	      changed = simplify_gimple_switch (stmt);
+	      changed = simplify_gimple_switch ((gimple_switch)stmt);
 	      break;
 
 	    case GIMPLE_COND:
diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c
index 71c1f5d..6a32b26 100644
--- a/gcc/tree-ssa-uncprop.c
+++ b/gcc/tree-ssa-uncprop.c
@@ -166,12 +166,13 @@ associate_equivalences_with_edges (void)
 	 target block creates an equivalence.  */
       else if (gimple_code (stmt) == GIMPLE_SWITCH)
 	{
-	  tree cond = gimple_switch_index (stmt);
+	  gimple_switch switch_stmt = (gimple_switch)stmt;
+	  tree cond = gimple_switch_index (switch_stmt);
 
 	  if (TREE_CODE (cond) == SSA_NAME
 	      && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
 	    {
-	      int i, n_labels = gimple_switch_num_labels (stmt);
+	      int i, n_labels = gimple_switch_num_labels (switch_stmt);
 	      tree *info = XCNEWVEC (tree, last_basic_block);
 
 	      /* Walk over the case label vector.  Record blocks
@@ -179,7 +180,7 @@ associate_equivalences_with_edges (void)
 		 a single value.  */
 	      for (i = 0; i < n_labels; i++)
 		{
-		  tree label = gimple_switch_label (stmt, i);
+		  tree label = gimple_switch_label (switch_stmt, i);
 		  basic_block bb = label_to_block (CASE_LABEL (label));
 
 		  if (CASE_HIGH (label)
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 46b9efe..4adb758 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -292,7 +292,7 @@ case_bit_test_cmp (const void *p1, const void *p2)
     node targets.  */
 
 static void
-emit_case_bit_tests (gimple swtch, tree index_expr,
+emit_case_bit_tests (gimple_switch swtch, tree index_expr,
 		     tree minval, tree range)
 {
   struct case_bit_test test[MAX_CASE_BIT_TESTS];
@@ -604,7 +604,7 @@ struct switch_conv_info
 /* Collect information about GIMPLE_SWITCH statement SWTCH into INFO.  */
 
 static void
-collect_switch_conv_info (gimple swtch, struct switch_conv_info *info)
+collect_switch_conv_info (gimple_switch swtch, struct switch_conv_info *info)
 {
   unsigned int branch_num = gimple_switch_num_labels (swtch);
   tree min_case, max_case;
@@ -848,7 +848,7 @@ gather_default_values (tree default_case, struct switch_conv_info *info)
    order of phi nodes.  SWTCH is the switch statement being converted.  */
 
 static void
-build_constructors (gimple swtch, struct switch_conv_info *info)
+build_constructors (gimple_switch swtch, struct switch_conv_info *info)
 {
   unsigned i, branch_num = gimple_switch_num_labels (swtch);
   tree pos = info->range_min;
@@ -940,7 +940,7 @@ constructor_contains_same_values_p (vec<constructor_elt, va_gc> *vec)
    all the constants.  */
 
 static tree
-array_value_type (gimple swtch, tree type, int num,
+array_value_type (gimple_switch swtch, tree type, int num,
 		  struct switch_conv_info *info)
 {
   unsigned int i, len = vec_safe_length (info->constructors[num]);
@@ -1017,7 +1017,7 @@ array_value_type (gimple swtch, tree type, int num,
    new array.  */
 
 static void
-build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi,
+build_one_array (gimple_switch swtch, int num, tree arr_index_type, gimple phi,
 		 tree tidx, struct switch_conv_info *info)
 {
   tree name, cst;
@@ -1083,7 +1083,7 @@ build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi,
    them.  */
 
 static void
-build_arrays (gimple swtch, struct switch_conv_info *info)
+build_arrays (gimple_switch swtch, struct switch_conv_info *info)
 {
   tree arr_index_type;
   tree tidx, sub, utype;
@@ -1204,7 +1204,7 @@ fix_phi_nodes (edge e1f, edge e2f, basic_block bbf,
 */
 
 static void
-gen_inbound_check (gimple swtch, struct switch_conv_info *info)
+gen_inbound_check (gimple_switch swtch, struct switch_conv_info *info)
 {
   tree label_decl1 = create_artificial_label (UNKNOWN_LOCATION);
   tree label_decl2 = create_artificial_label (UNKNOWN_LOCATION);
@@ -1324,7 +1324,7 @@ gen_inbound_check (gimple swtch, struct switch_conv_info *info)
    conversion failed.  */
 
 static const char *
-process_switch (gimple swtch)
+process_switch (gimple_switch swtch)
 {
   struct switch_conv_info info;
 
@@ -1429,7 +1429,7 @@ do_switchconv (void)
 	    putc ('\n', dump_file);
 	  }
 
-	failure_reason = process_switch (stmt);
+	failure_reason = process_switch ((gimple_switch)stmt);
 	if (! failure_reason)
 	  {
 	    if (dump_file)
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d3a07f3..bd470f9 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -158,7 +158,7 @@ static bool values_propagated;
 static int *vr_phi_edge_counts;
 
 typedef struct {
-  gimple stmt;
+  gimple_switch stmt;
   tree vec;
 } switch_update;
 
@@ -5668,7 +5668,7 @@ compare_case_labels (const void *p1, const void *p2)
    list of assertions for the corresponding operands.  */
 
 static bool
-find_switch_asserts (basic_block bb, gimple last)
+find_switch_asserts (basic_block bb, gimple_switch last)
 {
   bool need_assert;
   gimple_stmt_iterator bsi;
@@ -5839,7 +5839,7 @@ find_assert_locations_1 (basic_block bb, sbitmap live)
   if (last
       && gimple_code (last) == GIMPLE_SWITCH
       && !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
-    need_assert |= find_switch_asserts (bb, last);
+    need_assert |= find_switch_asserts (bb, (gimple_switch)last);
 
   /* Traverse all the statements in BB marking used names and looking
      for statements that may infer assertions for their used operands.  */
@@ -7176,7 +7176,7 @@ vrp_visit_cond_stmt (gimple stmt, edge *taken_edge_p)
    returned. */
 
 static bool
-find_case_label_index (gimple stmt, size_t start_idx, tree val, size_t *idx)
+find_case_label_index (gimple_switch stmt, size_t start_idx, tree val, size_t *idx)
 {
   size_t n = gimple_switch_num_labels (stmt);
   size_t low, high;
@@ -7226,7 +7226,7 @@ find_case_label_index (gimple stmt, size_t start_idx, tree val, size_t *idx)
    Returns true if the default label is not needed. */
 
 static bool
-find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
+find_case_label_range (gimple_switch stmt, tree min, tree max, size_t *min_idx,
 		       size_t *max_idx)
 {
   size_t i, j;
@@ -7282,7 +7282,7 @@ find_case_label_range (gimple stmt, tree min, tree max, size_t *min_idx,
    Returns true if the default label is not needed.  */
 
 static bool
-find_case_label_ranges (gimple stmt, value_range_t *vr, size_t *min_idx1,
+find_case_label_ranges (gimple_switch stmt, value_range_t *vr, size_t *min_idx1,
 			size_t *max_idx1, size_t *min_idx2,
 			size_t *max_idx2)
 {
@@ -7360,7 +7360,7 @@ find_case_label_ranges (gimple stmt, value_range_t *vr, size_t *min_idx1,
    SSA_PROP_VARYING.  */
 
 static enum ssa_prop_result
-vrp_visit_switch_stmt (gimple stmt, edge *taken_edge_p)
+vrp_visit_switch_stmt (gimple_switch stmt, edge *taken_edge_p)
 {
   tree op, val;
   value_range_t *vr;
@@ -7476,7 +7476,7 @@ vrp_visit_stmt (gimple stmt, edge *taken_edge_p, tree *output_p)
   else if (gimple_code (stmt) == GIMPLE_COND)
     return vrp_visit_cond_stmt (stmt, taken_edge_p);
   else if (gimple_code (stmt) == GIMPLE_SWITCH)
-    return vrp_visit_switch_stmt (stmt, taken_edge_p);
+    return vrp_visit_switch_stmt ((gimple_switch)stmt, taken_edge_p);
 
   /* All other statements produce nothing of interest for VRP, so mark
      their outputs varying and prevent further simulation.  */
@@ -8928,7 +8928,7 @@ simplify_cond_using_ranges (gimple stmt)
    argument.  */
 
 static bool
-simplify_switch_using_ranges (gimple stmt)
+simplify_switch_using_ranges (gimple_switch stmt)
 {
   tree op = gimple_switch_index (stmt);
   value_range_t *vr;
@@ -9234,7 +9234,7 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
   else if (gimple_code (stmt) == GIMPLE_COND)
     return simplify_cond_using_ranges (stmt);
   else if (gimple_code (stmt) == GIMPLE_SWITCH)
-    return simplify_switch_using_ranges (stmt);
+    return simplify_switch_using_ranges ((gimple_switch)stmt);
 
   return false;
 }

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-06 21:06           ` Andrew MacLeod
  2013-11-06 21:52             ` Jeff Law
  2013-11-07 10:29             ` Richard Biener
@ 2013-11-10 12:35             ` Richard Sandiford
  2013-11-10 15:27               ` Richard Biener
  2 siblings, 1 reply; 116+ messages in thread
From: Richard Sandiford @ 2013-11-10 12:35 UTC (permalink / raw)
  To: Andrew MacLeod
  Cc: Richard Biener, Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches

Andrew MacLeod <amacleod@redhat.com> writes:
> 2 - I really believe gimple needs a type system different from front end 
> trees, that is my primary motivation.  I'm tired of jumping through 
> hoops to do anything slightly different, and I got fed up with it.  With 
> a separate type system for gimple, we can rid ourselves of all the stuff 
> that isn't related to optimization and codegen...   Could we do this 
> with trees? possibly, but if I'm going to go to the effort of converting 
> the front end tree types into a new or reduced-type subset, I might as 
> well put that effort into something that is more appropriate right from 
> the start.

But what types specifically are you hoping to drop?  Would there still
be enough information for proper TBAA, for instance?

Having two different type representations just sounds like it's going
to lead to code duplication for common operations.

Plus I'd really not like to see targets have to deal with two different
representations of types.  Sometimes the things that the target
has to do only make sense "at the tree level" (e.g. providing the
definition of va_list).  Some are on the boundary, such as lowering
va_arg into gimple.  Some could potentially be used in both places,
e.g. the hook to determine the correct alignment for a vector.
(I can imagine we'd want to be able to call that at the tree level for
user-defined vectors passed to __alignof, say, but also at the gimple
level when vectorising.)  Others are called during expand, e.g. PROMOTE_MODE.

Thanks,
Richard

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-11-10 12:35             ` Richard Sandiford
@ 2013-11-10 15:27               ` Richard Biener
  0 siblings, 0 replies; 116+ messages in thread
From: Richard Biener @ 2013-11-10 15:27 UTC (permalink / raw)
  To: Richard Sandiford, Andrew MacLeod
  Cc: Bernd Schmidt, Jeff Law, David Malcolm, GCC Patches

Richard Sandiford <rdsandiford@googlemail.com> wrote:
>Andrew MacLeod <amacleod@redhat.com> writes:
>> 2 - I really believe gimple needs a type system different from front
>end 
>> trees, that is my primary motivation.  I'm tired of jumping through 
>> hoops to do anything slightly different, and I got fed up with it. 
>With 
>> a separate type system for gimple, we can rid ourselves of all the
>stuff 
>> that isn't related to optimization and codegen...   Could we do this 
>> with trees? possibly, but if I'm going to go to the effort of
>converting 
>> the front end tree types into a new or reduced-type subset, I might
>as 
>> well put that effort into something that is more appropriate right
>from 
>> the start.
>
>But what types specifically are you hoping to drop?  Would there still
>be enough information for proper TBAA, for instance?
>
>Having two different type representations just sounds like it's going
>to lead to code duplication for common operations.
>
>Plus I'd really not like to see targets have to deal with two different
>representations of types.  Sometimes the things that the target
>has to do only make sense "at the tree level" (e.g. providing the
>definition of va_list).  Some are on the boundary, such as lowering
>va_arg into gimple.  Some could potentially be used in both places,
>e.g. the hook to determine the correct alignment for a vector.
>(I can imagine we'd want to be able to call that at the tree level for
>user-defined vectors passed to __alignof, say, but also at the gimple
>level when vectorising.)  Others are called during expand, e.g.
>PROMOTE_MODE.

I can see that a change of the representation of types makes sense to better isolate frontend dependent things. In theory we have lang_type for that but frontend specific things are unfortunately not limited to that. That said, the idea of doing it on our own in gimple isn't the best - rather the existing tree representation should be changed and with it all affected frontends.

Even with trees not all things need to remain trees btw, types could get a non-tree structure. But then start at the root of the problem that trees are ubiquitous - remove the remaining tree container structures and its uses. In the past a lot of work has already been done here, but it's not yet complete.

Richard.


>Thanks,
>Richard


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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-08 19:23             ` David Malcolm
@ 2013-11-14  8:38               ` Jeff Law
  2013-11-14 15:06                 ` Michael Matz
  2013-11-14 18:32                 ` David Malcolm
  0 siblings, 2 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-14  8:38 UTC (permalink / raw)
  To: David Malcolm; +Cc: Michael Matz, Andrew MacLeod, gcc-patches

On 11/08/13 12:02, David Malcolm wrote:
>> I wouldn't mind seeing a small example proof of concept posted to help
>> those who don't see where this is going understand the goal.  I would
>> recommend against posting another large patch for inclusion at this time.
> Attached is a proof-of-concept patch which uses the
> gimple_statement_switch subclass (as a "gimple_switch" typedef).  This
> is one of the subclasses that the earlier patch added, which has no new
> fields, but which carries the invariant that, if non-NULL,
>     gimple_code (gs) == GIMPLE_SWITCH.
[ ... ]

Thanks.  It's pretty much what I expected.  Obviously for other codes 
there may be a lot more changes that you have to slog through, but I 
think this example shows the main concepts.

Presumably in this new world order, the various gimple statement types 
will continue to inherit from a base class.  That seems somewhat 
inevitable and implies a certain amount of downcasting (via whatever 
means we agree upon).  The worry, in my mind is how pervasive the 
downcasting will be and how much of it we can get rid of over time.

I may be wrong, but ISTM some of the downcasting is a result of not 
providing certain capabilities via (pure?) virtual methods.  For 
example, expand_gimple_stmt_1 seems ripe for implementing as virtual 
methods.   ISTM you could also have virtuals to build the statements, 
dump/pretty-print them, verify them, branch/edge redirection, 
estimations for inlining, etc.  ISTM that would eliminate a good chunk 
of the downcasting.

Just to be clear, I'm not asking you to make those changes, just for 
your thoughts on approaches to eliminate the downcasting based on what 
we've seen so far.

Thanks for pulling this together to help illustrate how some of this 
might look in practice.  I hope others take the time to look closely as 
this example and think about what it means in terms of how we would be 
writing code 6 months from now.


Jeff

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

* Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)
  2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
                     ` (8 preceding siblings ...)
  2013-11-05 21:33   ` Jeff Law
@ 2013-11-14  8:40   ` Jeff Law
  9 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-14  8:40 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
>
> The following series of patches convert it to a C++ hierarchy, using the
> existing structs, eliminating the union. The "gimple" typedef changes
> from being a
>    (union gimple_statement_d *)
> to being a:
>    (struct gimple_statement_base *)
>
> There are no virtual functions in the new code: the sizes of the various
> structs are unchanged.
Seems like a reasonable place to start (no virtuals).  As I mentioned in 
my earlier reply today, virtuals may be one way to cut down on the 
downcasting.  They have obvious downsides, but I think we now have some 
code samples to think about so we can sensibly evaluate downcasting vs 
adding virtual functions and how each affects the code we write.


>
> Again, as noted in the earlier patch series, the names of the structs
> are rather verbose.  I would prefer to also rename them all to eliminate
> the "_statement" component:
>    "gimple_statement_base" -> "gimple_base"
>    "gimple_statement_phi"  -> "gimple_phi"
>    "gimple_statement_omp"  -> "gimple_omp"
> etc, but I didn't do this to mimimize the patch size.  But if the core
> maintainers are up for that, I can redo the patch series with that
> change also, or do that as a followup.
If we do that, I think it'd be a followup -- it's a fair amount of churn 
with marginal benefit though, IMHO.

Jeff

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

* Re: [PATCH 6/6] Update gdb hooks to reflect changes to gimple types
  2013-10-31 16:46   ` [PATCH 6/6] Update gdb hooks to reflect changes to " David Malcolm
@ 2013-11-14  9:10     ` Jeff Law
  0 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-14  9:10 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
> gcc/
> 	* gdbhooks.py (GimplePrinter.to_string): Update lookup of
> 	code field to reflect inheritance, rather than embedding of
> 	the base gimple type.
Conditionally approved.  Obvious condition is the other 5 patches get 
approved.

Jeff


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

* Re: [PATCH 5/6] Port various places from union access to subclass access.
  2013-10-31 16:49   ` [PATCH 5/6] Port various places from union access to subclass access David Malcolm
@ 2013-11-14  9:23     ` Jeff Law
  2013-11-19  0:52       ` David Malcolm
  0 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-14  9:23 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
>
> diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
> index 4f31b83..2555dbe 100644
> --- a/gcc/gimple-streamer-in.c
> +++ b/gcc/gimple-streamer-in.c
> @@ -129,13 +129,14 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
>       case GIMPLE_ASM:
>         {
>   	/* FIXME lto.  Move most of this into a new gimple_asm_set_string().  */
> +	gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (stmt);
>   	tree str;
> -	stmt->gimple_asm.ni = streamer_read_uhwi (ib);
> -	stmt->gimple_asm.no = streamer_read_uhwi (ib);
> -	stmt->gimple_asm.nc = streamer_read_uhwi (ib);
> -	stmt->gimple_asm.nl = streamer_read_uhwi (ib);
> +	asm_stmt->ni = streamer_read_uhwi (ib);
> +	asm_stmt->no = streamer_read_uhwi (ib);
> +	asm_stmt->nc = streamer_read_uhwi (ib);
> +	asm_stmt->nl = streamer_read_uhwi (ib);
>   	str = streamer_read_string_cst (data_in, ib);
> -	stmt->gimple_asm.string = TREE_STRING_POINTER (str);
> +	asm_stmt->string = TREE_STRING_POINTER (str);
The in/out streaming seems like another natural fit for virtual 
functions in the long term.


>         }
>         /* Fallthru  */
>
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index 9b1337a..e9ef8e0 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -641,21 +641,22 @@ static inline gimple
>   gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
>                       unsigned nclobbers, unsigned nlabels)
>   {
> -  gimple p;
> +  gimple_statement_asm *p;
>     int size = strlen (string);
>
>     /* ASMs with labels cannot have outputs.  This should have been
>        enforced by the front end.  */
>     gcc_assert (nlabels == 0 || noutputs == 0);
>
> -  p = gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
> -			     ninputs + noutputs + nclobbers + nlabels);
> +  p = as_a <gimple_statement_asm> (
> +        gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
> +			       ninputs + noutputs + nclobbers + nlabels));
>
> -  p->gimple_asm.ni = ninputs;
> -  p->gimple_asm.no = noutputs;
> -  p->gimple_asm.nc = nclobbers;
> -  p->gimple_asm.nl = nlabels;
> -  p->gimple_asm.string = ggc_alloc_string (string, size);
> +  p->ni = ninputs;
> +  p->no = noutputs;
> +  p->nc = nclobbers;
> +  p->nl = nlabels;
> +  p->string = ggc_alloc_string (string, size);
As noted in a prior message, having build methods would eliminate this 
downcasting.  Not necessary for this patch, just wanted to point it out 
to anyone reading.  I won't point it out everywhere ;-)


So given the prior disussions around as_a, I'm not going to object to 
these as_a instances.  I see them as warts/markers that we have further 
work to do in terms of fleshing out the class and possibly refactoring 
code.

Conditionally OK.  Conditional on the other related patches going in and 
keeping it updated with Andrew's churn.  If/when the set goes in, post 
the final version you actually checkin -- no re-review is needed for 
this hunk so long as any changes are the obvious fixing of fallout from 
Andrew's work.

Jeff

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

* Re: [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types
  2013-10-31 16:27   ` [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types David Malcolm
@ 2013-11-14  9:41     ` Jeff Law
  2013-11-18 19:51       ` David Malcolm
  0 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-14  9:41 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
> 	* gimple.h (is_a_helper <const gimple_statement_with_ops>::test): New.
> 	(is_a_helper <gimple_statement_with_ops>::test): New.
> 	(is_a_helper <const gimple_statement_with_memory_ops>::test): New.
> 	(is_a_helper <gimple_statement_with_memory_ops>::test): New.
OK with the usual conditions.  Check with Andrew as to the location of 
these helpers since he's in the middle of ripping apart gimple.h.
jeff

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

* Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance
  2013-10-31 16:31   ` [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance David Malcolm
@ 2013-11-14  9:43     ` Jeff Law
  2013-11-18 22:17       ` [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance) David Malcolm
  0 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-14  9:43 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
> gcc/
>
> 	Patch autogenerated by refactor_gimple.py from
> 	https://github.com/davidmalcolm/gcc-refactoring-scripts
> 	revision 74cd3d5f06565c318749d0fb9f35b565dae28daa
[ ... ]
This is fine with the usual conditions.

  diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
> index e430050..ed0d6df 100644
> --- a/gcc/gimple-iterator.c
> +++ b/gcc/gimple-iterator.c
> @@ -67,7 +67,7 @@ update_bb_for_stmts (gimple_seq_node first, gimple_seq_node last,
>   {
>     gimple_seq_node n;
>
> -  for (n = first; n; n = n->gsbase.next)
> +  for (n = first; n; n = n->next)
So just a quite note.  If I'm reading this corectly, this should make 
things marginally easier in the debugger when looking at objects?  It 
drives me absolutely nuts having to figure out how to get through the 
base class to the fields I care about.

I didn't look at every hunk in this patch carefully.  Just spot checked 
thigns.


>   }
>
>   /* Set the nowait flag on OMP_RETURN statement S.  */
> @@ -1661,7 +1973,7 @@ static inline void
>   gimple_omp_return_set_nowait (gimple s)
>   {
>     GIMPLE_CHECK (s, GIMPLE_OMP_RETURN);
> -  s->gsbase.subcode |= GF_OMP_RETURN_NOWAIT;
> +  s->subcode |= GF_OMP_RETURN_NOWAIT;
So is there some reason the GIMPLE_CHECK was left in here rather than 
doing the downcasting?  This happens in other places.


>   }
>
>
> @@ -1681,8 +1993,9 @@ gimple_omp_return_nowait_p (const_gimple g)
>   static inline void
>   gimple_omp_return_set_lhs (gimple g, tree lhs)
>   {
> -  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
> -  g->gimple_omp_atomic_store.val = lhs;
> +  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> +    as_a <gimple_statement_omp_atomic_store> (g);
> +  omp_atomic_store_stmt->val = lhs;
Contrast to prior hunk.  This one, AFAICT elimates the GIMPLE_CHECK here 
and does it as part of the downcasting, right?

I wonder how far we have to go with this before GIMPLE_CHECK goes away :-)

>
> @@ -1723,7 +2038,7 @@ static inline void
>   gimple_omp_section_set_last (gimple g)
>   {
>     GIMPLE_CHECK (g, GIMPLE_OMP_SECTION);
> -  g->gsbase.subcode |= GF_OMP_SECTION_LAST;
> +  g->subcode |= GF_OMP_SECTION_LAST;
Another example of the GIMPLE_CHECK hanging around.  On purpose?

>   }
>
>
> @@ -1746,9 +2061,9 @@ gimple_omp_parallel_set_combined_p (gimple g, bool combined_p)
>   {
>     GIMPLE_CHECK (g, GIMPLE_OMP_PARALLEL);
>     if (combined_p)
> -    g->gsbase.subcode |= GF_OMP_PARALLEL_COMBINED;
> +    g->subcode |= GF_OMP_PARALLEL_COMBINED;
>     else
> -    g->gsbase.subcode &= ~GF_OMP_PARALLEL_COMBINED;
> +    g->subcode &= ~GF_OMP_PARALLEL_COMBINED;
Likewise.

>   }
>
>
> @@ -1771,7 +2086,7 @@ gimple_omp_atomic_set_need_value (gimple g)
>   {
>     if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
>       GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
> -  g->gsbase.subcode |= GF_OMP_ATOMIC_NEED_VALUE;
> +  g->subcode |= GF_OMP_ATOMIC_NEED_VALUE;
Likewise.


And so-on.

I don't see anything objectionable.  Just want to make sure the script 
and/or the by-hand stuff didn't miss some of the conversions.

Jeff



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

* Re: [PATCH 2/6] Hand-written port of various accessors within gimple.h
  2013-10-31 16:27   ` [PATCH 2/6] Hand-written port of various accessors within gimple.h David Malcolm
@ 2013-11-14  9:53     ` Jeff Law
  0 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-14  9:53 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
> 	* gimple.h (gimple_use_ops): Port from union to usage of
> 	dyn_cast.
> 	(gimple_set_use_ops): Port from union to usage of as_a.
> 	(gimple_set_vuse): Likewise.
> 	(gimple_set_vdef): Likewise.
> 	(gimple_call_internal_fn): Port from union to a static_cast,
> 	given that the type has already been asserted.
> 	(gimple_omp_body_ptr): Port from unchecked union usage to
> 	a static_cast.
> 	(gimple_omp_set_body): Likewise.
OK with usual conditions.

It's getting late and I just fired off my overnight regression tests. 
So I'll have to look at 1/6 tomorrow.

jeff

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-14  8:38               ` Jeff Law
@ 2013-11-14 15:06                 ` Michael Matz
  2013-11-14 18:32                 ` David Malcolm
  1 sibling, 0 replies; 116+ messages in thread
From: Michael Matz @ 2013-11-14 15:06 UTC (permalink / raw)
  To: Jeff Law; +Cc: David Malcolm, Andrew MacLeod, gcc-patches

Hi,

On Thu, 14 Nov 2013, Jeff Law wrote:

> Thanks.  It's pretty much what I expected.  Obviously for other codes 
> there may be a lot more changes that you have to slog through, but I 
> think this example shows the main concepts.
> 
> Presumably in this new world order, the various gimple statement types 
> will continue to inherit from a base class.  That seems somewhat 
> inevitable and implies a certain amount of downcasting (via whatever 
> means we agree upon). The worry, in my mind is how pervasive the 
> downcasting will be and how much of it we can get rid of over time.
> 
> I may be wrong, but ISTM some of the downcasting is a result of not 
> providing certain capabilities via (pure?) virtual methods.  For 
> example, expand_gimple_stmt_1 seems ripe for implementing as virtual 
> methods.

Please no.  A class with many methods hints at a bad design.  If we were 
to add virtual methods for every piece of the hundred passes that have to 
do different things per instruction code we'd arrive at exactly that.  
Even though most of these methods would be more related to the pass 
they're in they would actually have to be implemented in the gimple class 
(and their inherited ones).  I wouldn't want to see methods ala 
expand_me(), remove_me(), remove_me_for_predcom(), 
remove_me_for_some_other_pass(), optimize_me_for_{this,that,another}() and 
so on.

> ISTM you could also have virtuals to build the statements, 

Virtual to build things?  You mean constructors.

> dump/pretty-print them,

True.

> verify them,

Depends.  Part of them can be verified without context information, and 
that would perhaps be sensible in some virtual methods.  Part of the 
verification depends on context, other insns, the call graph, the CFG.  
Those should IMHO not be methods of gimple.

> branch/edge redirection, 

That seems to me more related to the cfg, not to statements.  Some 
statements need to be modified, true, but only very few subclasses (those 
that can transfer control).

> estimations for inlining,

Part of that (again the things you can determine with a statement 
alone, without much context, yes.

> etc.  ISTM that would eliminate a good chunk 
> of the downcasting.
> 
> Just to be clear, I'm not asking you to make those changes, just for 
> your thoughts on approaches to eliminate the downcasting based on what 
> we've seen so far.

Before adding a vtable pointer to gimple (or any other central, heavily 
used data structure) I'd go through great pain to avoid that.


Ciao,
Michael.

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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-14  8:38               ` Jeff Law
  2013-11-14 15:06                 ` Michael Matz
@ 2013-11-14 18:32                 ` David Malcolm
  2013-11-15  2:49                   ` Jeff Law
  1 sibling, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-11-14 18:32 UTC (permalink / raw)
  To: Jeff Law; +Cc: Michael Matz, Andrew MacLeod, gcc-patches

On Thu, 2013-11-14 at 00:13 -0700, Jeff Law wrote:
> On 11/08/13 12:02, David Malcolm wrote:
> >> I wouldn't mind seeing a small example proof of concept posted to help
> >> those who don't see where this is going understand the goal.  I would
> >> recommend against posting another large patch for inclusion at this time.
> > Attached is a proof-of-concept patch which uses the
> > gimple_statement_switch subclass (as a "gimple_switch" typedef).  This
> > is one of the subclasses that the earlier patch added, which has no new
> > fields, but which carries the invariant that, if non-NULL,
> >     gimple_code (gs) == GIMPLE_SWITCH.
> [ ... ]
> 
> Thanks.  It's pretty much what I expected.  Obviously for other codes 
> there may be a lot more changes that you have to slog through, but I 
> think this example shows the main concepts.
> 
> Presumably in this new world order, the various gimple statement types 
> will continue to inherit from a base class.  That seems somewhat 
> inevitable and implies a certain amount of downcasting (via whatever 
> means we agree upon).  The worry, in my mind is how pervasive the 
> downcasting will be and how much of it we can get rid of over time.
> 
> I may be wrong, but ISTM some of the downcasting is a result of not 
> providing certain capabilities via (pure?) virtual methods.  For 
> example, expand_gimple_stmt_1 seems ripe for implementing as virtual 
> methods.   ISTM you could also have virtuals to build the statements, 
> dump/pretty-print them, verify them, branch/edge redirection, 
> estimations for inlining, etc.  ISTM that would eliminate a good chunk 
> of the downcasting.

FWIW, I prefer the downcasts to adding virtual functions; what I've
tried to do is create a very direct mapping from the status quo,
introducing inheritance to gain the benefits listed earlier in the
thread, whilst only changing "surface syntax".

It seems to me that we're considering the general problem of type-safe
code dispatch: given a type hierarchy, and various sites that want to
vary behavior based on what types they see, how best to invoke the
appropriate code, ensuring that the code that's called "knows" that its
dealing with the appropriate subclass i.e. in a typesafe manner.

There are various idioms for doing this kind of dispatch in C++, a
non-exhaustive list is:

   (a) switches and if/then tests on the GIMPLE_CODE (stmt) - the status
quo, and what my proposed patch continues to do, albeit gaining some
compile-time typechecking using as_a<> for the switch and dyn_cast<> for
the if/then.  This is changing some surface syntax without making major
changes, and gains us compile-time typesafety and IMHO more readable
code, though clearly opinions vary here.   In my (brief) testing, (a)
has no significant effect on compiler performance.

   (b) adding virtual functions to gimple would be another way to handle
type-safe dispatch, but they carry costs:
      (i) they would implicitly add a vtable ptr to the top of every
gimple statement, increasing the memory consumption of the process
      (ii) it's my belief that a virtual function call is more expensive
than the kinds of switch/if+then branching that we're currently doing on
the code - though I don't have measurements to back this up
      (iii) what I call "link-time granularity". A vtable references
every method within it.  I'd love to have a libgimple.so, but to do so,
every vtable would need to be populated with a particular set of
operations at link time - where do we draw the line for "core" gimple
operations, the dispatches performed by every core pass?   The set of
operations will never be complete: some plugin may want to add a new set
of per-gimple-subclass behaviors for some custom gimple pass.

  (c) the "Visitor" design pattern [1] - rather than adding virtual
functions to gimple, instead add them to a visitor class e.g.:

     class gimple_visitor
     {
     public:
	/* Visit a statement.  This will dispatch to the appropriate
	   handler below, based on GIMPLE_CODE (stmt), encapsulating
	   the appropriate downcast within a big switch statement.  */
	void visit_stmt (gimple stmt);

     protected:
	/* Each gimple code gets its own handler.  This class
	   provides an empty implementation of each.  If we want
	   to force overrides, we could have an abstract_gimple_visitor
	   base class above this one that has all of these be pure
	   virtual.  */
	virtual void visit_cond (gimple_cond stmt) {}
	virtual void visit_switch (gimple_switch stmt) {}
	virtual void visit_assign (gimple_assign stmt) {}
	virtual void visit_phi (gimple_phi phi) {}
	/* etc */
     };

   Example of a subclass:

     class gimple_pretty_printer : public gimple_visitor
     {
     protected:
	/* Each of these implements the subclass-specific
           pretty-printing logic.  */
	void visit_cond (gimple_cond stmt);
	void visit_switch (gimple_switch stmt);
	void visit_assign (gimple_assign stmt);
	void visit_phi (gimple_phi phi);
	/* etc */
     };

   so that the dispatch can be written like this:
     gimple_pretty_printer pp;
     pp.visit_stmt (stmt);

   (the above isn't *exactly* the Visitor pattern from the Gang of Four
book, I'm doing things in the visitor in order avoiding adding vfuncs to
gimple).

   This approach avoids adding an implicit vtable field to the top of
gimple [(i) above], and keeps the vtables with the code using them
[(iii) above].

  However it still would mean (ii) changing from switch/if-then control
flow to vfunc calls, with unknown impact on performance.  I'd be nervous
about adding virtual functions anywhere where we're not already jumping
though function ptrs.

  [Aside: this approach also gives us a natural place to store state
relating to the dispatch (as fields of the visitor subclass), which may
help in removing global state from the compiler.  (Doesn't help with GTY
state though)]

  (d) The status quo, with the drawback of doing the type-checking
either at run-time (checked build) or not at all (release build).

We have 41 gimple codes (and adding new ones is a relatively rare
event), but many more dispatch sites, I think - a first estimate might
be:
  [gcc] $ grep -nH -e "gimple_code (" *.c | wc -l
  772

So we have (I think) a large number of sites that dispatch to code based
on a (relatively) small fixed set of types - this suggests to me the use
of the Visitor pattern: (c) above, but I think (a) is the conservative
approach that gives many benefits for relatively low risk, and gives us
an easy transition path to (c) if measurement establishes the lack of
significant performance impact.  Such a transition could be done
piecemeal.

> Just to be clear, I'm not asking you to make those changes, just for 
> your thoughts on approaches to eliminate the downcasting based on what 
> we've seen so far.

(nods).   Note that I don't regard the downcasting as inherently bad,
just one approach to the generic issue of typesafe dynamic code
dispatch.   Yes, in many OO textbooks, it's regarded as a code smell,
but then again "goto" has its uses :)

> Thanks for pulling this together to help illustrate how some of this 
> might look in practice.  I hope others take the time to look closely as 
> this example and think about what it means in terms of how we would be 
> writing code 6 months from now.

On the subject of "6 months from now", my dream is that we can have a
libgimple.so and a librtl.so (.a in the regular builds).   I've love to
build a pluggable static analyzer on top of the gimple code - so I'm
trying to think of how we can structure the gimple code in such a way
that it's reusable in a modular way.

FWIW, I don't like the implicit "pointerness" of types within my
proposed patch, I'd rather have, say, the "gimple_switch" type be the
underlying _struct_, and spell out "gimple_switch *" to make it clear
that the latter is a pointer.

Doing so would make the is-a.h API somewhat less clunky, so that one
could write:

   if (gimple_switch *swtch = dyn_cast<gimple_switch> (stmt))
     {
	// do switchy stuff on swtch.
     }

rather than:

   if (gimple_switch swtch = dyn_cast<gimple_statement_switch> (stmt))
     {
	// do switchy stuff on swtch.
     }

Another tweak to the patch series could be to only introduce the leaf
subclasses one at a time, each time making use of the new subclass.  For
example, the "gimple_switch" subclass would be added at the same time as
a patch that makes use of it to improve compile-time typesafety, so each
patch would contain its own justification, as it were (applying the
YAGNI principle).

Sorry for the long email; thanks for reading to the end.
Dave

[1] see the Gang of Four "Design Pattens" book, or e.g.
http://en.wikipedia.org/wiki/Visitor_pattern


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

* Re: [PATCH 1/6] Convert gimple types from a union to C++ inheritance
  2013-10-31 16:27   ` [PATCH 1/6] Convert gimple types from a union to C++ inheritance David Malcolm
@ 2013-11-14 23:00     ` Jeff Law
  2013-11-19  0:22       ` David Malcolm
  0 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-14 23:00 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Andrew MacLeod

On 10/31/13 10:26, David Malcolm wrote:
> 	* Makefile.in (GIMPLE_H): Add dep on is-a.h.
Not asking you, but I'd like to hope many of the *_H things in 
Makefile.in should be going away...



>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index cc88fb8..7fbb533 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -887,7 +887,7 @@ BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) \
>   	cfg-flags.def cfghooks.h
>   GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
>   	$(GGC_H) $(BASIC_BLOCK_H) $(TREE_H) tree-ssa-operands.h \
> -	tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H)
> +	tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H) is-a.h
>   GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
>   RECOG_H = recog.h
>   EMIT_RTL_H = emit-rtl.h
Ugh.  OK I guess.  I hate all these _H thingies.  Ideally they'll go 
away at some point.  I think their biggest use now is for 
PLUGIN_HEADERS.  But that's not an issue for this patch to go forward.



> diff --git a/gcc/ggc.h b/gcc/ggc.h
> index b31bc80..bb8f939 100644
> --- a/gcc/ggc.h
> +++ b/gcc/ggc.h
> @@ -269,10 +269,10 @@ ggc_alloc_cleared_tree_node_stat (size_t s MEM_STAT_DECL)
>     return (union tree_node *) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
>   }
>
> -static inline union gimple_statement_d *
> -ggc_alloc_cleared_gimple_statement_d_stat (size_t s MEM_STAT_DECL)
> +static inline struct gimple_statement_base *
> +ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL)
>   {
> -  return (union gimple_statement_d *)
> +  return (struct gimple_statement_base *)
>       ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
>   }
Didn't I see something in the last 48hrs indicating that we don't need 
"static inline" anymore, just "inline"?  If so, can you drop the static 
here since you're changing it already.


With that, this, IMO is OK and a definite step forward.

Given the contention over this, please give other maintainers 24hrs to 
object before installing the set.

jeff


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

* Re: [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3))
  2013-11-14 18:32                 ` David Malcolm
@ 2013-11-15  2:49                   ` Jeff Law
  0 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-15  2:49 UTC (permalink / raw)
  To: David Malcolm; +Cc: Michael Matz, Andrew MacLeod, gcc-patches

On 11/14/13 10:49, David Malcolm wrote:
>
> FWIW, I prefer the downcasts to adding virtual functions; what I've
> tried to do is create a very direct mapping from the status quo,
> introducing inheritance to gain the benefits listed earlier in the
> thread, whilst only changing "surface syntax".
I understand (and I probably encouraged you to stay close as close to 
the status quo as possible while still moving this stuff forward ;-)


>
> It seems to me that we're considering the general problem of type-safe
> code dispatch: given a type hierarchy, and various sites that want to
> vary behavior based on what types they see, how best to invoke the
> appropriate code, ensuring that the code that's called "knows" that its
> dealing with the appropriate subclass i.e. in a typesafe manner.
Right.  Certainly in my quick browsing, this is primarily a dispatch 
problem.  I think Andrew had one in his Cauldron slide deck as well.

>
> There are various idioms for doing this kind of dispatch in C++, a
> non-exhaustive list is:
>
>     (a) switches and if/then tests on the GIMPLE_CODE (stmt) - the status
> quo,
Right.  And probably appropriate for now.  But I do want us to think 
about better ways to handle this.

>
>     (b) adding virtual functions to gimple would be another way to handle
> type-safe dispatch, but they carry costs:
>        (i) they would implicitly add a vtable ptr to the top of every
> gimple statement, increasing the memory consumption of the process
Thats my biggest concern.

>        (ii) it's my belief that a virtual function call is more expensive
> than the kinds of switch/if+then branching that we're currently doing on
> the code - though I don't have measurements to back this up
The virtual call is probably more expensive, but probably not as much as 
you might think as the switch likely compiles down to a multi-way branch 
which is on-par with an indirect call.


>
>    (c) the "Visitor" design pattern [1] - rather than adding virtual
> functions to gimple, instead add them to a visitor class e.g.:
Basically this just puts the vtable in a different class.  But doesn't 
the wrapping visitor need to know about the underlying details of the 
gimple statement class?   If we're trying to encapsulate things better, 
doesn't a visitor break the encapsulation?

>
>     (the above isn't *exactly* the Visitor pattern from the Gang of Four
> book, I'm doing things in the visitor in order avoiding adding vfuncs to
> gimple).
Right.  My mental model when I wrote my last message as a visit method 
which dispatched to the statement specific bits, but with the method as 
a part of the gimple base class.

>
>     This approach avoids adding an implicit vtable field to the top of
> gimple [(i) above], and keeps the vtables with the code using them
> [(iii) above].
Right.

>
>    However it still would mean (ii) changing from switch/if-then control
> flow to vfunc calls, with unknown impact on performance.  I'd be nervous
> about adding virtual functions anywhere where we're not already jumping
> though function ptrs.
As noted above, jumping through a function pointer probably isn't much 
different performance-wise than a multi-way branch.

Anyway, just wanted to get the conversation around this started as 
cleaning this stuff up is a natural follow-on at some point.

>
> (nods).   Note that I don't regard the downcasting as inherently bad,
> just one approach to the generic issue of typesafe dynamic code
> dispatch.   Yes, in many OO textbooks, it's regarded as a code smell,
> but then again "goto" has its uses :)
Again, my opinions come from working on large codes which did a lot of 
downcasting (and sadly upcasting too) and it was a major PITA to get 
sorted out.

Thanks,
jeff

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

* Re: [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types
  2013-11-14  9:41     ` Jeff Law
@ 2013-11-18 19:51       ` David Malcolm
  2013-11-18 20:10         ` Andrew MacLeod
  2013-11-18 20:15         ` Jeff Law
  0 siblings, 2 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-18 19:51 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Andrew MacLeod

On Thu, 2013-11-14 at 00:37 -0700, Jeff Law wrote:
> On 10/31/13 10:26, David Malcolm wrote:
> > 	* gimple.h (is_a_helper <const gimple_statement_with_ops>::test): New.
> > 	(is_a_helper <gimple_statement_with_ops>::test): New.
> > 	(is_a_helper <const gimple_statement_with_memory_ops>::test): New.
> > 	(is_a_helper <gimple_statement_with_memory_ops>::test): New.
> OK with the usual conditions.  Check with Andrew as to the location of 
> these helpers since he's in the middle of ripping apart gimple.h.

The helpers become used in accessors such as gimple_use_ops,
gimple_vuse, gimple_vdef etc as of the automated patch (patch 3 in the
series [1]), so presumably the helpers need to be in the same file as
those accessors.  The accessors are currently in gimple.h, and hence I
also put the helpers within gimple.h (earlier within the header).

Andrew, do you plan to move the accessor functions out of gimple.h?  If
so, where should the is_a_helper fns land?

Dave

[1] hence these patches need to be committed at the same time, whether
than means a single "revision" or not; I split them up conceptually for
ease of review.

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

* Re: [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types
  2013-11-18 19:51       ` David Malcolm
@ 2013-11-18 20:10         ` Andrew MacLeod
  2013-11-18 20:15         ` Jeff Law
  1 sibling, 0 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-18 20:10 UTC (permalink / raw)
  To: David Malcolm; +Cc: Jeff Law, gcc-patches

On 11/18/2013 01:54 PM, David Malcolm wrote:
> On Thu, 2013-11-14 at 00:37 -0700, Jeff Law wrote:
>> On 10/31/13 10:26, David Malcolm wrote:
>>> 	* gimple.h (is_a_helper <const gimple_statement_with_ops>::test): New.
>>> 	(is_a_helper <gimple_statement_with_ops>::test): New.
>>> 	(is_a_helper <const gimple_statement_with_memory_ops>::test): New.
>>> 	(is_a_helper <gimple_statement_with_memory_ops>::test): New.
>> OK with the usual conditions.  Check with Andrew as to the location of
>> these helpers since he's in the middle of ripping apart gimple.h.
> The helpers become used in accessors such as gimple_use_ops,
> gimple_vuse, gimple_vdef etc as of the automated patch (patch 3 in the
> series [1]), so presumably the helpers need to be in the same file as
> those accessors.  The accessors are currently in gimple.h, and hence I
> also put the helpers within gimple.h (earlier within the header).
>
> Andrew, do you plan to move the accessor functions out of gimple.h?  If
> so, where should the is_a_helper fns land?
>
Not currently. They are a component of the gimple statement, and 
gimple.[ch] is now just the statement and related accessors.  Since your 
changes are just for gimple-stmt, in theory everything should go there.

Andrew


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

* Re: [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types
  2013-11-18 19:51       ` David Malcolm
  2013-11-18 20:10         ` Andrew MacLeod
@ 2013-11-18 20:15         ` Jeff Law
  1 sibling, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-18 20:15 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Andrew MacLeod

On 11/18/13 11:54, David Malcolm wrote:
> On Thu, 2013-11-14 at 00:37 -0700, Jeff Law wrote:
>> On 10/31/13 10:26, David Malcolm wrote:
>>> 	* gimple.h (is_a_helper <const gimple_statement_with_ops>::test): New.
>>> 	(is_a_helper <gimple_statement_with_ops>::test): New.
>>> 	(is_a_helper <const gimple_statement_with_memory_ops>::test): New.
>>> 	(is_a_helper <gimple_statement_with_memory_ops>::test): New.
>> OK with the usual conditions.  Check with Andrew as to the location of
>> these helpers since he's in the middle of ripping apart gimple.h.
>
> The helpers become used in accessors such as gimple_use_ops,
> gimple_vuse, gimple_vdef etc as of the automated patch (patch 3 in the
> series [1]), so presumably the helpers need to be in the same file as
> those accessors.  The accessors are currently in gimple.h, and hence I
> also put the helpers within gimple.h (earlier within the header).
>
> Andrew, do you plan to move the accessor functions out of gimple.h?  If
> so, where should the is_a_helper fns land?
>
> Dave
>
> [1] hence these patches need to be committed at the same time, whether
> than means a single "revision" or not; I split them up conceptually for
> ease of review.
I'd say single commit since they are dependent upon each other.

jeff

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

* [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-14  9:43     ` Jeff Law
@ 2013-11-18 22:17       ` David Malcolm
  2013-11-19  8:49         ` Jeff Law
  2013-11-22  0:27         ` Jakub Jelinek
  0 siblings, 2 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-18 22:17 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Andrew MacLeod

[-- Attachment #1: Type: text/plain, Size: 6622 bytes --]

On Thu, 2013-11-14 at 00:48 -0700, Jeff Law wrote:
> On 10/31/13 10:26, David Malcolm wrote:
> > gcc/
> >
> > 	Patch autogenerated by refactor_gimple.py from
> > 	https://github.com/davidmalcolm/gcc-refactoring-scripts
> > 	revision 74cd3d5f06565c318749d0fb9f35b565dae28daa
> [ ... ]
> This is fine with the usual conditions.

This patch has bitrotten somewhat against trunk due to the
reorganization of gimple.h and related headers.

I regenerated it and am bootstrapping now.  I glanced over it and
nothing major seems to have changed; just changes due to the movement of
code between files.   Am attaching the changed patch.

>   diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
> > index e430050..ed0d6df 100644
> > --- a/gcc/gimple-iterator.c
> > +++ b/gcc/gimple-iterator.c
> > @@ -67,7 +67,7 @@ update_bb_for_stmts (gimple_seq_node first, gimple_seq_node last,
> >   {
> >     gimple_seq_node n;
> >
> > -  for (n = first; n; n = n->gsbase.next)
> > +  for (n = first; n; n = n->next)
> So just a quite note.  If I'm reading this corectly, this should make 
> things marginally easier in the debugger when looking at objects?  It 
> drives me absolutely nuts having to figure out how to get through the 
> base class to the fields I care about.

I think so, yes, though you'll have to cast it to the appropriate
subclass by hand; rather than the status quo of getting multiple
screenfuls of text, you'll just get the gimple_statement_base fields:

(gdb) p stmt
$9 = <gimple_assign 0x7ffff0450000>
(gdb) p *(gimple_statement_with_memory_ops*)stmt
$10 = {<gimple_statement_with_memory_ops_base> =
{<gimple_statement_with_ops_base> = {<gimple_statement_base> = {code =
GIMPLE_ASSIGN, no_warning = 0, 
        visited = 0, nontemporal_move = 0, plf = 1, modified = 0,
has_volatile_ops = 0, subcode = 67, uid = 0, location = 2147483648,
num_ops = 3, bb = 
    <basic_block 0x7ffff042a1a0 (2)>, next = <gimple 0x0>, prev =
<gimple_assign 0x7ffff0450000>}, use_ops = 0x7ffff0452008}, vdef = <tree
0x0>, vuse = 
    <tree 0x0>}, op = {0x7ffff030acf0}}

This would clearly be nicer with the followup of having an (empty)
subclass for assignments, so that one could do:
(gdb) p *(gimple_statement_assign*)stmt

We may be able to automate printing the appropriate subclass in
gdbhooks.py


> I didn't look at every hunk in this patch carefully.  Just spot checked 
> thigns.
> 
> 
> >   }
> >
> >   /* Set the nowait flag on OMP_RETURN statement S.  */
> > @@ -1661,7 +1973,7 @@ static inline void
> >   gimple_omp_return_set_nowait (gimple s)
> >   {
> >     GIMPLE_CHECK (s, GIMPLE_OMP_RETURN);
> > -  s->gsbase.subcode |= GF_OMP_RETURN_NOWAIT;
> > +  s->subcode |= GF_OMP_RETURN_NOWAIT;
> So is there some reason the GIMPLE_CHECK was left in here rather than 
> doing the downcasting?  This happens in other places.

The script isn't particularly smart, and here it's only removing the
"->gsbase." part.  It doesn't automatically remove GIMPLE_CHECK uses: it
only introduces a downcast if it needs to, and given that this accessor
only pokes at base class things it didn't.  Hence the existing
typechecking is preserved.

I want to convert accessors like this into taking a subclass ptr, hence
it could eventually become:
  gimple_omp_return_set_nowait (gimple_omp_return *s)
(there are only two uses of it in the tree) and at that point, the
GIMPLE_CHECK can be removed (with the type-checking enforced at compile
time).


> > @@ -1681,8 +1993,9 @@ gimple_omp_return_nowait_p (const_gimple g)
> >   static inline void
> >   gimple_omp_return_set_lhs (gimple g, tree lhs)
> >   {
> > -  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
> > -  g->gimple_omp_atomic_store.val = lhs;
> > +  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
> > +    as_a <gimple_statement_omp_atomic_store> (g);
> > +  omp_atomic_store_stmt->val = lhs;
> Contrast to prior hunk.  This one, AFAICT elimates the GIMPLE_CHECK here 
> and does it as part of the downcasting, right?

Yes: this accessor make use of fields of the subclass: specifically the
val within the omp_atomic_store, and hence needs to do the checked
downcast ("as_a").  Given that as_a performs equivalent runtime checking
to GIMPLE_CHECK, I opted for the script to remove the GIMPLE_CHECK in
such cases.


> I wonder how far we have to go with this before GIMPLE_CHECK goes away :-)
> 
> >
> > @@ -1723,7 +2038,7 @@ static inline void
> >   gimple_omp_section_set_last (gimple g)
> >   {
> >     GIMPLE_CHECK (g, GIMPLE_OMP_SECTION);
> > -  g->gsbase.subcode |= GF_OMP_SECTION_LAST;
> > +  g->subcode |= GF_OMP_SECTION_LAST;
> Another example of the GIMPLE_CHECK hanging around.  On purpose?

Again, given that we only poke at "subcode", no as_a is needed, and
hence the script keeps the GIMPLE_CHECK.

FWIW, this particular accessor is only used in one place
(omp-low.c:lower_omp_sections).

> >
> > @@ -1746,9 +2061,9 @@ gimple_omp_parallel_set_combined_p (gimple g, bool combined_p)
> >   {
> >     GIMPLE_CHECK (g, GIMPLE_OMP_PARALLEL);
> >     if (combined_p)
> > -    g->gsbase.subcode |= GF_OMP_PARALLEL_COMBINED;
> > +    g->subcode |= GF_OMP_PARALLEL_COMBINED;
> >     else
> > -    g->gsbase.subcode &= ~GF_OMP_PARALLEL_COMBINED;
> > +    g->subcode &= ~GF_OMP_PARALLEL_COMBINED;
> Likewise.
...and again, this one only pokes at "subcode", which is in the base
class.  Likewise, this accessor is only used in one place
(omp-low.c:lower_omp_taskreg), and could be changed in a followup to
accept a gimple_omp_parallel *, dropping the GIMPLE_CHECK.


> > @@ -1771,7 +2086,7 @@ gimple_omp_atomic_set_need_value (gimple g)
> >   {
> >     if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
> >       GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
> > -  g->gsbase.subcode |= GF_OMP_ATOMIC_NEED_VALUE;
> > +  g->subcode |= GF_OMP_ATOMIC_NEED_VALUE;
> Likewise.
...likewise this only looks at subcode and hence doesn't need a
downcast.  It's used in 2 places, both within gimplify_omp_atomic, both
of which can trivially be converted to work on subclass ptrs (the
statements in question come directly from
gimple_build_omp_atomice_{load|store} calls).

> And so-on.
> 
> I don't see anything objectionable.  Just want to make sure the script 
> and/or the by-hand stuff didn't miss some of the conversions.

Thanks.   I'm attaching the regenerated patch.  As noted above, I
believe that the only changes are due to functions moving between source
files; specifically the move of the following from gimple.h to
gimple-iterator.h (quoting the ChangeLog):
	* gimple-iterator.h (gsi_one_before_end_p): Likewise.
	(gsi_next): Likewise.
	(gsi_prev): Likewise.


OK for trunk?

[-- Attachment #2: 0003-Automated-part-of-conversion-of-gimple-types-to-use-.patch --]
[-- Type: text/x-patch, Size: 121671 bytes --]

From fe6d5759f00da73ed2d1f62e520bc7ba3f6669c6 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 18 Nov 2013 11:53:57 -0500
Subject: [PATCH 3/6] Automated part of conversion of gimple types to use C++
 inheritance

gcc/

	Patch autogenerated by refactor_gimple.py from
	https://github.com/davidmalcolm/gcc-refactoring-scripts
	revision 05fc808c61bd8ddd2372f29b79ceb2491360d298

	* gimple-iterator.c (update_bb_for_stmts): Update for conversion of
	gimple types to a true class hierarchy.
	(update_call_edge_frequencies): Likewise.
	(gsi_insert_seq_nodes_before): Likewise.
	(gsi_insert_seq_nodes_after): Likewise.
	(gsi_split_seq_after): Likewise.
	(gsi_set_stmt): Likewise.
	(gsi_split_seq_before): Likewise.
	(gsi_remove): Likewise.
	* gimple-iterator.h (gsi_one_before_end_p): Likewise.
	(gsi_next): Likewise.
	(gsi_prev): Likewise.
	* gimple-pretty-print.c (dump_gimple_debug): Likewise.
	* gimple-ssa.h (gimple_vuse_op): Likewise.
	(gimple_vdef_op): Likewise.
	* gimple-streamer-in.c (input_gimple_stmt): Likewise.
	* gimple-streamer-out.c (output_gimple_stmt): Likewise.
	* gimple.c (gimple_set_code): Likewise.
	(gimple_alloc_stat): Likewise.
	(gimple_set_subcode): Likewise.
	(gimple_build_call_internal_1): Likewise.
	(gimple_check_failed): Likewise.
	(gimple_call_flags): Likewise.
	(gimple_set_bb): Likewise.
	* gimple.h (is_a_helper <gimple_statement_asm> (gimple)): New.
	(is_a_helper <gimple_statement_bind> (gimple)): Likewise.
	(is_a_helper <gimple_statement_call> (gimple)): Likewise.
	(is_a_helper <gimple_statement_catch> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_ctrl> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_else> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_filter> (gimple)): Likewise.
	(is_a_helper <gimple_statement_eh_mnt> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_atomic_load> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_atomic_store> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_continue> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_critical> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_for> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_parallel> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_sections> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_single> (gimple)): Likewise.
	(is_a_helper <gimple_statement_omp_task> (gimple)): Likewise.
	(is_a_helper <gimple_statement_phi> (gimple)): Likewise.
	(is_a_helper <gimple_statement_transaction> (gimple)): Likewise.
	(is_a_helper <gimple_statement_try> (gimple)): Likewise.
	(is_a_helper <gimple_statement_wce> (gimple)): Likewise.
	(is_a_helper <const gimple_statement_asm> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_bind> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_call> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_catch> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_eh_ctrl> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_eh_filter> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_atomic_load> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_atomic_store>
	(const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_omp_continue> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_critical> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_for> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_parallel> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_sections> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_single> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_omp_task> (const_gimple)):
	Likewise.
	(is_a_helper <const gimple_statement_phi> (const_gimple)): Likewise.
	(is_a_helper <const gimple_statement_transaction> (const_gimple)):
	Likewise.
	(gimple_seq_last): Update for conversion of gimple types to a true
	class hierarchy.
	(gimple_seq_set_last): Likewise.
	(gimple_code): Likewise.
	(gimple_bb): Likewise.
	(gimple_block): Likewise.
	(gimple_set_block): Likewise.
	(gimple_location): Likewise.
	(gimple_location_ptr): Likewise.
	(gimple_set_location): Likewise.
	(gimple_no_warning_p): Likewise.
	(gimple_set_no_warning): Likewise.
	(gimple_set_visited): Likewise.
	(gimple_visited_p): Likewise.
	(gimple_set_plf): Likewise.
	(gimple_plf): Likewise.
	(gimple_set_uid): Likewise.
	(gimple_uid): Likewise.
	(gimple_init_singleton): Likewise.
	(gimple_modified_p): Likewise.
	(gimple_set_modified): Likewise.
	(gimple_expr_code): Likewise.
	(gimple_has_volatile_ops): Likewise.
	(gimple_set_has_volatile_ops): Likewise.
	(gimple_omp_subcode): Likewise.
	(gimple_omp_set_subcode): Likewise.
	(gimple_omp_return_set_nowait): Likewise.
	(gimple_omp_section_set_last): Likewise.
	(gimple_omp_parallel_set_combined_p): Likewise.
	(gimple_omp_atomic_set_need_value): Likewise.
	(gimple_omp_atomic_set_seq_cst): Likewise.
	(gimple_num_ops): Likewise.
	(gimple_set_num_ops): Likewise.
	(gimple_assign_nontemporal_move_p): Likewise.
	(gimple_assign_set_nontemporal_move): Likewise.
	(gimple_assign_rhs_code): Likewise.
	(gimple_assign_set_rhs_code): Likewise.
	(gimple_call_internal_p): Likewise.
	(gimple_call_with_bounds_p): Likewise.
	(gimple_call_set_with_bounds): Likewise.
	(gimple_call_set_tail): Likewise.
	(gimple_call_tail_p): Likewise.
	(gimple_call_set_return_slot_opt): Likewise.
	(gimple_call_return_slot_opt_p): Likewise.
	(gimple_call_set_from_thunk): Likewise.
	(gimple_call_from_thunk_p): Likewise.
	(gimple_call_set_va_arg_pack): Likewise.
	(gimple_call_va_arg_pack_p): Likewise.
	(gimple_call_set_nothrow): Likewise.
	(gimple_call_set_alloca_for_var): Likewise.
	(gimple_call_alloca_for_var_p): Likewise.
	(gimple_call_copy_flags): Likewise.
	(gimple_cond_code): Likewise.
	(gimple_cond_set_code): Likewise.
	(gimple_cond_make_false): Likewise.
	(gimple_cond_make_true): Likewise.
	(gimple_asm_volatile_p): Likewise.
	(gimple_asm_set_volatile): Likewise.
	(gimple_asm_set_input): Likewise.
	(gimple_asm_input_p): Likewise.
	(gimple_try_kind): Likewise.
	(gimple_try_set_kind): Likewise.
	(gimple_try_catch_is_cleanup): Likewise.
	(gimple_try_set_catch_is_cleanup): Likewise.
	(gimple_wce_cleanup_eh_only): Likewise.
	(gimple_wce_set_cleanup_eh_only): Likewise.
	(gimple_debug_bind_p): Likewise.
	(gimple_debug_source_bind_p): Likewise.
	(gimple_omp_for_set_kind): Likewise.
	(gimple_omp_for_set_combined_p): Likewise.
	(gimple_omp_for_set_combined_into_p): Likewise.
	(gimple_omp_target_set_kind): Likewise.
	(gimple_transaction_subcode): Likewise.
	(gimple_transaction_set_subcode): Likewise.
	(gimple_predict_predictor): Likewise.
	(gimple_predict_set_predictor): Likewise.
	(gimple_predict_outcome): Likewise.
	(gimple_predict_set_outcome): Likewise.
	(gimple_transaction_set_label): Likewise.
	(gimple_transaction_set_body): Likewise.
	(gimple_transaction_label_ptr): Likewise.
	(gimple_transaction_label): Likewise.
	(gimple_transaction_body_ptr): Likewise.
	(gimple_omp_continue_set_control_use): Likewise.
	(gimple_omp_continue_control_use_ptr): Likewise.
	(gimple_omp_continue_control_use): Likewise.
	(gimple_omp_continue_set_control_def): Likewise.
	(gimple_omp_continue_control_def_ptr): Likewise.
	(gimple_omp_continue_control_def): Likewise.
	(gimple_omp_atomic_load_rhs_ptr): Likewise.
	(gimple_omp_atomic_load_rhs): Likewise.
	(gimple_omp_atomic_load_set_rhs): Likewise.
	(gimple_omp_atomic_load_lhs_ptr): Likewise.
	(gimple_omp_atomic_load_lhs): Likewise.
	(gimple_omp_atomic_load_set_lhs): Likewise.
	(gimple_omp_atomic_store_val_ptr): Likewise.
	(gimple_omp_atomic_store_val): Likewise.
	(gimple_omp_atomic_store_set_val): Likewise.
	(gimple_omp_for_cond): Likewise.
	(gimple_omp_for_set_cond): Likewise.
	(gimple_omp_sections_set_control): Likewise.
	(gimple_omp_sections_control_ptr): Likewise.
	(gimple_omp_sections_control): Likewise.
	(gimple_omp_sections_set_clauses): Likewise.
	(gimple_omp_sections_clauses_ptr): Likewise.
	(gimple_omp_sections_clauses): Likewise.
	(gimple_omp_teams_set_clauses): Likewise.
	(gimple_omp_teams_clauses_ptr): Likewise.
	(gimple_omp_teams_clauses): Likewise.
	(gimple_omp_target_set_data_arg): Likewise.
	(gimple_omp_target_data_arg_ptr): Likewise.
	(gimple_omp_target_data_arg): Likewise.
	(gimple_omp_target_set_child_fn): Likewise.
	(gimple_omp_target_child_fn_ptr): Likewise.
	(gimple_omp_target_child_fn): Likewise.
	(gimple_omp_target_set_clauses): Likewise.
	(gimple_omp_target_clauses_ptr): Likewise.
	(gimple_omp_target_clauses): Likewise.
	(gimple_omp_single_set_clauses): Likewise.
	(gimple_omp_single_clauses_ptr): Likewise.
	(gimple_omp_single_clauses): Likewise.
	(gimple_omp_task_set_arg_align): Likewise.
	(gimple_omp_task_arg_align_ptr): Likewise.
	(gimple_omp_task_arg_align): Likewise.
	(gimple_omp_task_set_arg_size): Likewise.
	(gimple_omp_task_arg_size_ptr): Likewise.
	(gimple_omp_task_arg_size): Likewise.
	(gimple_omp_task_set_copy_fn): Likewise.
	(gimple_omp_task_copy_fn_ptr): Likewise.
	(gimple_omp_task_copy_fn): Likewise.
	(gimple_omp_task_set_data_arg): Likewise.
	(gimple_omp_task_data_arg_ptr): Likewise.
	(gimple_omp_task_data_arg): Likewise.
	(gimple_omp_task_set_child_fn): Likewise.
	(gimple_omp_task_child_fn_ptr): Likewise.
	(gimple_omp_task_child_fn): Likewise.
	(gimple_omp_task_set_clauses): Likewise.
	(gimple_omp_task_clauses_ptr): Likewise.
	(gimple_omp_task_clauses): Likewise.
	(gimple_omp_parallel_set_data_arg): Likewise.
	(gimple_omp_parallel_data_arg_ptr): Likewise.
	(gimple_omp_parallel_data_arg): Likewise.
	(gimple_omp_parallel_set_child_fn): Likewise.
	(gimple_omp_parallel_child_fn_ptr): Likewise.
	(gimple_omp_parallel_child_fn): Likewise.
	(gimple_omp_parallel_set_clauses): Likewise.
	(gimple_omp_parallel_clauses_ptr): Likewise.
	(gimple_omp_parallel_clauses): Likewise.
	(gimple_omp_for_set_pre_body): Likewise.
	(gimple_omp_for_pre_body_ptr): Likewise.
	(gimple_omp_for_set_incr): Likewise.
	(gimple_omp_for_incr_ptr): Likewise.
	(gimple_omp_for_incr): Likewise.
	(gimple_omp_for_set_final): Likewise.
	(gimple_omp_for_final_ptr): Likewise.
	(gimple_omp_for_final): Likewise.
	(gimple_omp_for_set_initial): Likewise.
	(gimple_omp_for_initial_ptr): Likewise.
	(gimple_omp_for_initial): Likewise.
	(gimple_omp_for_set_index): Likewise.
	(gimple_omp_for_index_ptr): Likewise.
	(gimple_omp_for_index): Likewise.
	(gimple_omp_for_collapse): Likewise.
	(gimple_omp_for_set_clauses): Likewise.
	(gimple_omp_for_clauses_ptr): Likewise.
	(gimple_omp_for_clauses): Likewise.
	(gimple_omp_critical_set_name): Likewise.
	(gimple_omp_critical_name_ptr): Likewise.
	(gimple_omp_critical_name): Likewise.
	(gimple_eh_dispatch_set_region): Likewise.
	(gimple_eh_dispatch_region): Likewise.
	(gimple_resx_set_region): Likewise.
	(gimple_resx_region): Likewise.
	(gimple_phi_set_arg): Likewise.
	(gimple_phi_arg): Likewise.
	(gimple_phi_set_result): Likewise.
	(gimple_phi_result_ptr): Likewise.
	(gimple_phi_result): Likewise.
	(gimple_phi_num_args): Likewise.
	(gimple_phi_capacity): Likewise.
	(gimple_wce_set_cleanup): Likewise.
	(gimple_wce_cleanup_ptr): Likewise.
	(gimple_try_set_cleanup): Likewise.
	(gimple_try_set_eval): Likewise.
	(gimple_try_cleanup_ptr): Likewise.
	(gimple_try_eval_ptr): Likewise.
	(gimple_eh_else_set_e_body): Likewise.
	(gimple_eh_else_set_n_body): Likewise.
	(gimple_eh_else_e_body_ptr): Likewise.
	(gimple_eh_else_n_body_ptr): Likewise.
	(gimple_eh_must_not_throw_set_fndecl): Likewise.
	(gimple_eh_must_not_throw_fndecl): Likewise.
	(gimple_eh_filter_set_failure): Likewise.
	(gimple_eh_filter_set_types): Likewise.
	(gimple_eh_filter_failure_ptr): Likewise.
	(gimple_eh_filter_types_ptr): Likewise.
	(gimple_eh_filter_types): Likewise.
	(gimple_catch_set_handler): Likewise.
	(gimple_catch_set_types): Likewise.
	(gimple_catch_handler_ptr): Likewise.
	(gimple_catch_types_ptr): Likewise.
	(gimple_catch_types): Likewise.
	(gimple_asm_string): Likewise.
	(gimple_asm_set_label_op): Likewise.
	(gimple_asm_label_op): Likewise.
	(gimple_asm_set_clobber_op): Likewise.
	(gimple_asm_clobber_op): Likewise.
	(gimple_asm_set_output_op): Likewise.
	(gimple_asm_output_op_ptr): Likewise.
	(gimple_asm_output_op): Likewise.
	(gimple_asm_set_input_op): Likewise.
	(gimple_asm_input_op_ptr): Likewise.
	(gimple_asm_input_op): Likewise.
	(gimple_asm_nlabels): Likewise.
	(gimple_asm_nclobbers): Likewise.
	(gimple_asm_noutputs): Likewise.
	(gimple_asm_ninputs): Likewise.
	(gimple_bind_set_block): Likewise.
	(gimple_bind_block): Likewise.
	(gimple_bind_add_seq): Likewise.
	(gimple_bind_add_stmt): Likewise.
	(gimple_bind_set_body): Likewise.
	(gimple_bind_body_ptr): Likewise.
	(gimple_bind_append_vars): Likewise.
	(gimple_bind_set_vars): Likewise.
	(gimple_bind_vars): Likewise.
	(gimple_call_clobber_set): Likewise.
	(gimple_call_use_set): Likewise.
	(gimple_call_set_internal_fn): Likewise.
	(gimple_call_set_fntype): Likewise.
	(gimple_call_fntype): Likewise.
	(gimple_omp_return_lhs_ptr): Likewise.
	(gimple_omp_return_lhs): Likewise.
	(gimple_omp_return_set_lhs): Likewise.
	(gimple_omp_taskreg_set_data_arg): Likewise.
	(gimple_omp_taskreg_data_arg_ptr): Likewise.
	(gimple_omp_taskreg_data_arg): Likewise.
	(gimple_omp_taskreg_set_child_fn): Likewise.
	(gimple_omp_taskreg_child_fn_ptr): Likewise.
	(gimple_omp_taskreg_child_fn): Likewise.
	(gimple_omp_taskreg_set_clauses): Likewise.
	(gimple_omp_taskreg_clauses_ptr): Likewise.
	(gimple_omp_taskreg_clauses): Likewise.
	(gimple_vuse): Likewise.
	(gimple_vdef): Likewise.
	(gimple_vuse_ptr): Likewise.
	(gimple_vdef_ptr): Likewise.
	* tree-inline.c (copy_debug_stmt): Likewise.
	* tree-phinodes.c (make_phi_node): Likewise.
---
 gcc/gimple-iterator.c     |   72 +--
 gcc/gimple-iterator.h     |    8 +-
 gcc/gimple-pretty-print.c |    2 +-
 gcc/gimple-ssa.h          |   16 +-
 gcc/gimple-streamer-in.c  |    8 +-
 gcc/gimple-streamer-out.c |    2 +-
 gcc/gimple.c              |   16 +-
 gcc/gimple.h              | 1367 ++++++++++++++++++++++++++++++---------------
 gcc/tree-inline.c         |    2 +-
 gcc/tree-phinodes.c       |    2 +-
 10 files changed, 968 insertions(+), 527 deletions(-)

diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
index b945389..557bf35 100644
--- a/gcc/gimple-iterator.c
+++ b/gcc/gimple-iterator.c
@@ -68,7 +68,7 @@ update_bb_for_stmts (gimple_seq_node first, gimple_seq_node last,
 {
   gimple_seq_node n;
 
-  for (n = first; n; n = n->gsbase.next)
+  for (n = first; n; n = n->next)
     {
       gimple_set_bb (n, bb);
       if (n == last)
@@ -86,7 +86,7 @@ update_call_edge_frequencies (gimple_seq_node first, basic_block bb)
   int bb_freq = 0;
   gimple_seq_node n;
 
-  for (n = first; n ; n = n->gsbase.next)
+  for (n = first; n ; n = n->next)
     if (is_gimple_call (n))
       {
 	struct cgraph_edge *e;
@@ -124,7 +124,7 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
   basic_block bb;
   gimple_seq_node cur = i->ptr;
 
-  gcc_assert (!cur || cur->gsbase.prev);
+  gcc_assert (!cur || cur->prev);
 
   if ((bb = gsi_bb (*i)) != NULL)
     update_bb_for_stmts (first, last, bb);
@@ -132,13 +132,13 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
   /* Link SEQ before CUR in the sequence.  */
   if (cur)
     {
-      first->gsbase.prev = cur->gsbase.prev;
-      if (first->gsbase.prev->gsbase.next)
-	first->gsbase.prev->gsbase.next = first;
+      first->prev = cur->prev;
+      if (first->prev->next)
+	first->prev->next = first;
       else
 	gimple_seq_set_first (i->seq, first);
-      last->gsbase.next = cur;
-      cur->gsbase.prev = last;
+      last->next = cur;
+      cur->prev = last;
     }
   else
     {
@@ -149,11 +149,11 @@ gsi_insert_seq_nodes_before (gimple_stmt_iterator *i,
 	 labels, so it returns an iterator after the end of the block, and
 	 we need to insert before it; it might be cleaner to add a flag to the
 	 iterator saying whether we are at the start or end of the list).  */
-      last->gsbase.next = NULL;
+      last->next = NULL;
       if (itlast)
 	{
-	  first->gsbase.prev = itlast;
-	  itlast->gsbase.next = first;
+	  first->prev = itlast;
+	  itlast->next = first;
 	}
       else
 	gimple_seq_set_first (i->seq, first);
@@ -242,7 +242,7 @@ gsi_insert_seq_nodes_after (gimple_stmt_iterator *i,
   basic_block bb;
   gimple_seq_node cur = i->ptr;
 
-  gcc_assert (!cur || cur->gsbase.prev);
+  gcc_assert (!cur || cur->prev);
 
   /* If the iterator is inside a basic block, we need to update the
      basic block information for all the nodes between FIRST and LAST.  */
@@ -252,20 +252,20 @@ gsi_insert_seq_nodes_after (gimple_stmt_iterator *i,
   /* Link SEQ after CUR.  */
   if (cur)
     {
-      last->gsbase.next = cur->gsbase.next;
-      if (last->gsbase.next)
+      last->next = cur->next;
+      if (last->next)
 	{
-	  last->gsbase.next->gsbase.prev = last;
+	  last->next->prev = last;
 	}
       else
 	gimple_seq_set_last (i->seq, last);
-      first->gsbase.prev = cur;
-      cur->gsbase.next = first;
+      first->prev = cur;
+      cur->next = first;
     }
   else
     {
       gcc_assert (!gimple_seq_last (*i->seq));
-      last->gsbase.next = NULL;
+      last->next = NULL;
       gimple_seq_set_first (i->seq, first);
       gimple_seq_set_last (i->seq, last);
     }
@@ -347,15 +347,15 @@ gsi_split_seq_after (gimple_stmt_iterator i)
   cur = i.ptr;
 
   /* How can we possibly split after the end, or before the beginning?  */
-  gcc_assert (cur && cur->gsbase.next);
-  next = cur->gsbase.next;
+  gcc_assert (cur && cur->next);
+  next = cur->next;
 
   pold_seq = i.seq;
 
   gimple_seq_set_first (&new_seq, next);
   gimple_seq_set_last (&new_seq, gimple_seq_last (*pold_seq));
   gimple_seq_set_last (pold_seq, cur);
-  cur->gsbase.next = NULL;
+  cur->next = NULL;
 
   return new_seq;
 }
@@ -371,17 +371,17 @@ gsi_set_stmt (gimple_stmt_iterator *gsi, gimple stmt)
   gimple orig_stmt = gsi_stmt (*gsi);
   gimple prev, next;
 
-  stmt->gsbase.next = next = orig_stmt->gsbase.next;
-  stmt->gsbase.prev = prev = orig_stmt->gsbase.prev;
+  stmt->next = next = orig_stmt->next;
+  stmt->prev = prev = orig_stmt->prev;
   /* Note how we don't clear next/prev of orig_stmt.  This is so that
      copies of *GSI our callers might still hold (to orig_stmt)
      can be advanced as if they too were replaced.  */
-  if (prev->gsbase.next)
-    prev->gsbase.next = stmt;
+  if (prev->next)
+    prev->next = stmt;
   else
     gimple_seq_set_first (gsi->seq, stmt);
   if (next)
-    next->gsbase.prev = stmt;
+    next->prev = stmt;
   else
     gimple_seq_set_last (gsi->seq, stmt);
 
@@ -402,10 +402,10 @@ gsi_split_seq_before (gimple_stmt_iterator *i, gimple_seq *pnew_seq)
 
   /* How can we possibly split after the end?  */
   gcc_assert (cur);
-  prev = cur->gsbase.prev;
+  prev = cur->prev;
 
   old_seq = *i->seq;
-  if (!prev->gsbase.next)
+  if (!prev->next)
     *i->seq = NULL;
   i->seq = pnew_seq;
 
@@ -415,8 +415,8 @@ gsi_split_seq_before (gimple_stmt_iterator *i, gimple_seq *pnew_seq)
 
   /* Cut OLD_SEQ before I.  */
   gimple_seq_set_last (&old_seq, prev);
-  if (prev->gsbase.next)
-    prev->gsbase.next = NULL;
+  if (prev->next)
+    prev->next = NULL;
 }
 
 
@@ -576,20 +576,20 @@ gsi_remove (gimple_stmt_iterator *i, bool remove_permanently)
 
   /* Update the iterator and re-wire the links in I->SEQ.  */
   cur = i->ptr;
-  next = cur->gsbase.next;
-  prev = cur->gsbase.prev;
+  next = cur->next;
+  prev = cur->prev;
   /* See gsi_set_stmt for why we don't reset prev/next of STMT.  */
 
   if (next)
     /* Cur is not last.  */
-    next->gsbase.prev = prev;
-  else if (prev->gsbase.next)
+    next->prev = prev;
+  else if (prev->next)
     /* Cur is last but not first.  */
     gimple_seq_set_last (i->seq, prev);
 
-  if (prev->gsbase.next)
+  if (prev->next)
     /* Cur is not first.  */
-    prev->gsbase.next = next;
+    prev->next = next;
   else
     /* Cur is first.  */
     *i->seq = next;
diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h
index 24045f5..11b1276 100644
--- a/gcc/gimple-iterator.h
+++ b/gcc/gimple-iterator.h
@@ -168,7 +168,7 @@ gsi_end_p (gimple_stmt_iterator i)
 static inline bool
 gsi_one_before_end_p (gimple_stmt_iterator i)
 {
-  return i.ptr != NULL && i.ptr->gsbase.next == NULL;
+  return i.ptr != NULL && i.ptr->next == NULL;
 }
 
 /* Advance the iterator to the next gimple statement.  */
@@ -176,7 +176,7 @@ gsi_one_before_end_p (gimple_stmt_iterator i)
 static inline void
 gsi_next (gimple_stmt_iterator *i)
 {
-  i->ptr = i->ptr->gsbase.next;
+  i->ptr = i->ptr->next;
 }
 
 /* Advance the iterator to the previous gimple statement.  */
@@ -184,8 +184,8 @@ gsi_next (gimple_stmt_iterator *i)
 static inline void
 gsi_prev (gimple_stmt_iterator *i)
 {
-  gimple prev = i->ptr->gsbase.prev;
-  if (prev->gsbase.next)
+  gimple prev = i->ptr->prev;
+  if (prev->next)
     i->ptr = prev;
   else
     i->ptr = NULL;
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 711bc75..b14f317 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1072,7 +1072,7 @@ dump_gimple_eh_dispatch (pretty_printer *buffer, gimple gs, int spc, int flags)
 static void
 dump_gimple_debug (pretty_printer *buffer, gimple gs, int spc, int flags)
 {
-  switch (gs->gsbase.subcode)
+  switch (gs->subcode)
     {
     case GIMPLE_DEBUG_BIND:
       if (flags & TDF_RAW)
diff --git a/gcc/gimple-ssa.h b/gcc/gimple-ssa.h
index 23aa099..50b48bb 100644
--- a/gcc/gimple-ssa.h
+++ b/gcc/gimple-ssa.h
@@ -108,11 +108,13 @@ static inline use_operand_p
 gimple_vuse_op (const_gimple g)
 {
   struct use_optype_d *ops;
-  if (!gimple_has_mem_ops (g))
+  const gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <const gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_USE_OPERAND_P;
-  ops = g->gsops.opbase.use_ops;
+  ops = mem_ops_stmt->use_ops;
   if (ops
-      && USE_OP_PTR (ops)->use == &g->gsmembase.vuse)
+      && USE_OP_PTR (ops)->use == &mem_ops_stmt->vuse)
     return USE_OP_PTR (ops);
   return NULL_USE_OPERAND_P;
 }
@@ -122,10 +124,12 @@ gimple_vuse_op (const_gimple g)
 static inline def_operand_p
 gimple_vdef_op (gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_DEF_OPERAND_P;
-  if (g->gsmembase.vdef)
-    return &g->gsmembase.vdef;
+  if (mem_ops_stmt->vdef)
+    return &mem_ops_stmt->vdef;
   return NULL_DEF_OPERAND_P;
 }
 
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index 6f8f51a..7fb07d1 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -99,12 +99,12 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
   bp = streamer_read_bitpack (ib);
   num_ops = bp_unpack_var_len_unsigned (&bp);
   stmt = gimple_alloc (code, num_ops);
-  stmt->gsbase.no_warning = bp_unpack_value (&bp, 1);
+  stmt->no_warning = bp_unpack_value (&bp, 1);
   if (is_gimple_assign (stmt))
-    stmt->gsbase.nontemporal_move = bp_unpack_value (&bp, 1);
-  stmt->gsbase.has_volatile_ops = bp_unpack_value (&bp, 1);
+    stmt->nontemporal_move = bp_unpack_value (&bp, 1);
+  stmt->has_volatile_ops = bp_unpack_value (&bp, 1);
   has_hist = bp_unpack_value (&bp, 1);
-  stmt->gsbase.subcode = bp_unpack_var_len_unsigned (&bp);
+  stmt->subcode = bp_unpack_var_len_unsigned (&bp);
 
   /* Read location information.  */
   gimple_set_location (stmt, stream_input_location (&bp, data_in));
diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index 4d0664f..0d6b6a6 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -78,7 +78,7 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
   bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
   hist = gimple_histogram_value (cfun, stmt);
   bp_pack_value (&bp, hist != NULL, 1);
-  bp_pack_var_len_unsigned (&bp, stmt->gsbase.subcode);
+  bp_pack_var_len_unsigned (&bp, stmt->subcode);
 
   /* Emit location information for the statement.  */
   stream_output_location (ob, &bp, LOCATION_LOCUS (gimple_location (stmt)));
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 1c88b00..758660f 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -93,7 +93,7 @@ static const char * const gimple_alloc_kind_names[] = {
 static inline void
 gimple_set_code (gimple g, enum gimple_code code)
 {
-  g->gsbase.code = code;
+  g->code = code;
 }
 
 /* Return the number of bytes needed to hold a GIMPLE statement with
@@ -131,7 +131,7 @@ gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
 
   /* Do not call gimple_set_modified here as it has other side
      effects and this tuple is still not completely built.  */
-  stmt->gsbase.modified = 1;
+  stmt->modified = 1;
   gimple_init_singleton (stmt);
 
   return stmt;
@@ -145,7 +145,7 @@ gimple_set_subcode (gimple g, unsigned subcode)
   /* We only have 16 bits for the RHS code.  Assert that we are not
      overflowing it.  */
   gcc_assert (subcode < (1 << 16));
-  g->gsbase.subcode = subcode;
+  g->subcode = subcode;
 }
 
 
@@ -280,7 +280,7 @@ static inline gimple
 gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
 {
   gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
-  s->gsbase.subcode |= GF_CALL_INTERNAL;
+  s->subcode |= GF_CALL_INTERNAL;
   gimple_call_set_internal_fn (s, fn);
   gimple_call_reset_alias_info (s);
   return s;
@@ -1111,8 +1111,8 @@ gimple_check_failed (const_gimple gs, const char *file, int line,
       		  gimple_code_name[code],
 		  get_tree_code_name (subcode),
 		  gimple_code_name[gimple_code (gs)],
-		  gs->gsbase.subcode > 0
-		    ? get_tree_code_name ((enum tree_code) gs->gsbase.subcode)
+		  gs->subcode > 0
+		    ? get_tree_code_name ((enum tree_code) gs->subcode)
 		    : "",
 		  function, trim_filename (file), line);
 }
@@ -1306,7 +1306,7 @@ gimple_call_flags (const_gimple stmt)
   else
     flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
 
-  if (stmt->gsbase.subcode & GF_CALL_NOTHROW)
+  if (stmt->subcode & GF_CALL_NOTHROW)
     flags |= ECF_NOTHROW;
 
   return flags;
@@ -1447,7 +1447,7 @@ gimple_assign_unary_nop_p (gimple gs)
 void
 gimple_set_bb (gimple stmt, basic_block bb)
 {
-  stmt->gsbase.bb = bb;
+  stmt->bb = bb;
 
   /* If the statement is a label, add the label to block-to-labels map
      so that we can speed up edge creation for GIMPLE_GOTOs.  */
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 65c24ee..ed94343 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -707,6 +707,310 @@ enum gimple_statement_structure_enum {
 };
 #undef DEFGSSTRUCT
 
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_asm>::test (gimple gs)
+{
+  return gs->code == GIMPLE_ASM;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_bind>::test (gimple gs)
+{
+  return gs->code == GIMPLE_BIND;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_call>::test (gimple gs)
+{
+  return gs->code == GIMPLE_CALL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_catch>::test (gimple gs)
+{
+  return gs->code == GIMPLE_CATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_ctrl>::test (gimple gs)
+{
+  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_else>::test (gimple gs)
+{
+  return gs->code == GIMPLE_EH_ELSE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_filter>::test (gimple gs)
+{
+  return gs->code == GIMPLE_EH_FILTER;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_eh_mnt>::test (gimple gs)
+{
+  return gs->code == GIMPLE_EH_MUST_NOT_THROW;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_atomic_load>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_ATOMIC_LOAD;
+}
+
+template <>
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_continue>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CONTINUE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_critical>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CRITICAL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_for>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_FOR;
+}
+
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_sections>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_SECTIONS;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_single>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_omp_task>::test (gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TASK;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_phi>::test (gimple gs)
+{
+  return gs->code == GIMPLE_PHI;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_transaction>::test (gimple gs)
+{
+  return gs->code == GIMPLE_TRANSACTION;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_try>::test (gimple gs)
+{
+  return gs->code == GIMPLE_TRY;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <gimple_statement_wce>::test (gimple gs)
+{
+  return gs->code == GIMPLE_WITH_CLEANUP_EXPR;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_asm>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_ASM;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_bind>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_BIND;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_call>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_CALL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_catch>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_CATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_eh_ctrl>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_eh_filter>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_EH_FILTER;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_atomic_load>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_ATOMIC_LOAD;
+}
+
+template <>
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_continue>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CONTINUE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_critical>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_CRITICAL;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_for>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_FOR;
+}
+
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_sections>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_SECTIONS;
+}
+
+template <>
+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;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_omp_task>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_OMP_TASK;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_phi>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_PHI;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const gimple_statement_transaction>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_TRANSACTION;
+}
+
 /* Offset in bytes to the location of the operand vector.
    Zero if there is no operand vector for this tuple structure.  */
 extern size_t const gimple_ops_offset_[];
@@ -880,7 +1184,7 @@ gimple_seq_first_stmt (gimple_seq s)
 static inline gimple_seq_node
 gimple_seq_last (gimple_seq s)
 {
-  return s ? s->gsbase.prev : NULL;
+  return s ? s->prev : NULL;
 }
 
 
@@ -899,7 +1203,7 @@ gimple_seq_last_stmt (gimple_seq s)
 static inline void
 gimple_seq_set_last (gimple_seq *ps, gimple_seq_node last)
 {
-  (*ps)->gsbase.prev = last;
+  (*ps)->prev = last;
 }
 
 
@@ -960,7 +1264,7 @@ set_bb_seq (basic_block bb, gimple_seq seq)
 static inline enum gimple_code
 gimple_code (const_gimple g)
 {
-  return g->gsbase.code;
+  return g->code;
 }
 
 
@@ -1023,7 +1327,7 @@ gimple_has_substatements (gimple g)
 static inline basic_block
 gimple_bb (const_gimple g)
 {
-  return g->gsbase.bb;
+  return g->bb;
 }
 
 
@@ -1032,7 +1336,7 @@ gimple_bb (const_gimple g)
 static inline tree
 gimple_block (const_gimple g)
 {
-  return LOCATION_BLOCK (g->gsbase.location);
+  return LOCATION_BLOCK (g->location);
 }
 
 
@@ -1042,10 +1346,10 @@ static inline void
 gimple_set_block (gimple g, tree block)
 {
   if (block)
-    g->gsbase.location =
-	COMBINE_LOCATION_DATA (line_table, g->gsbase.location, block);
+    g->location =
+	COMBINE_LOCATION_DATA (line_table, g->location, block);
   else
-    g->gsbase.location = LOCATION_LOCUS (g->gsbase.location);
+    g->location = LOCATION_LOCUS (g->location);
 }
 
 
@@ -1054,7 +1358,7 @@ gimple_set_block (gimple g, tree block)
 static inline location_t
 gimple_location (const_gimple g)
 {
-  return g->gsbase.location;
+  return g->location;
 }
 
 /* Return pointer to location information for statement G.  */
@@ -1062,7 +1366,7 @@ gimple_location (const_gimple g)
 static inline const location_t *
 gimple_location_ptr (const_gimple g)
 {
-  return &g->gsbase.location;
+  return &g->location;
 }
 
 
@@ -1071,7 +1375,7 @@ gimple_location_ptr (const_gimple g)
 static inline void
 gimple_set_location (gimple g, location_t location)
 {
-  g->gsbase.location = location;
+  g->location = location;
 }
 
 
@@ -1116,7 +1420,7 @@ gimple_seq_singleton_p (gimple_seq seq)
 static inline bool
 gimple_no_warning_p (const_gimple stmt)
 {
-  return stmt->gsbase.no_warning;
+  return stmt->no_warning;
 }
 
 /* Set the no_warning flag of STMT to NO_WARNING.  */
@@ -1124,7 +1428,7 @@ gimple_no_warning_p (const_gimple stmt)
 static inline void
 gimple_set_no_warning (gimple stmt, bool no_warning)
 {
-  stmt->gsbase.no_warning = (unsigned) no_warning;
+  stmt->no_warning = (unsigned) no_warning;
 }
 
 /* Set the visited status on statement STMT to VISITED_P.  */
@@ -1132,7 +1436,7 @@ gimple_set_no_warning (gimple stmt, bool no_warning)
 static inline void
 gimple_set_visited (gimple stmt, bool visited_p)
 {
-  stmt->gsbase.visited = (unsigned) visited_p;
+  stmt->visited = (unsigned) visited_p;
 }
 
 
@@ -1141,7 +1445,7 @@ gimple_set_visited (gimple stmt, bool visited_p)
 static inline bool
 gimple_visited_p (gimple stmt)
 {
-  return stmt->gsbase.visited;
+  return stmt->visited;
 }
 
 
@@ -1151,9 +1455,9 @@ static inline void
 gimple_set_plf (gimple stmt, enum plf_mask plf, bool val_p)
 {
   if (val_p)
-    stmt->gsbase.plf |= (unsigned int) plf;
+    stmt->plf |= (unsigned int) plf;
   else
-    stmt->gsbase.plf &= ~((unsigned int) plf);
+    stmt->plf &= ~((unsigned int) plf);
 }
 
 
@@ -1162,7 +1466,7 @@ gimple_set_plf (gimple stmt, enum plf_mask plf, bool val_p)
 static inline unsigned int
 gimple_plf (gimple stmt, enum plf_mask plf)
 {
-  return stmt->gsbase.plf & ((unsigned int) plf);
+  return stmt->plf & ((unsigned int) plf);
 }
 
 
@@ -1171,7 +1475,7 @@ gimple_plf (gimple stmt, enum plf_mask plf)
 static inline void
 gimple_set_uid (gimple g, unsigned uid)
 {
-  g->gsbase.uid = uid;
+  g->uid = uid;
 }
 
 
@@ -1180,7 +1484,7 @@ gimple_set_uid (gimple g, unsigned uid)
 static inline unsigned
 gimple_uid (const_gimple g)
 {
-  return g->gsbase.uid;
+  return g->uid;
 }
 
 
@@ -1189,8 +1493,8 @@ gimple_uid (const_gimple g)
 static inline void
 gimple_init_singleton (gimple g)
 {
-  g->gsbase.next = NULL;
-  g->gsbase.prev = g;
+  g->next = NULL;
+  g->prev = g;
 }
 
 
@@ -1241,9 +1545,11 @@ gimple_set_use_ops (gimple g, struct use_optype_d *use)
 static inline tree
 gimple_vuse (const_gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  const gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <const gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_TREE;
-  return g->gsmembase.vuse;
+  return mem_ops_stmt->vuse;
 }
 
 /* Return the single VDEF operand of the statement G.  */
@@ -1251,9 +1557,11 @@ gimple_vuse (const_gimple g)
 static inline tree
 gimple_vdef (const_gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  const gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <const gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL_TREE;
-  return g->gsmembase.vdef;
+  return mem_ops_stmt->vdef;
 }
 
 /* Return the single VUSE operand of the statement G.  */
@@ -1261,9 +1569,11 @@ gimple_vdef (const_gimple g)
 static inline tree *
 gimple_vuse_ptr (gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL;
-  return &g->gsmembase.vuse;
+  return &mem_ops_stmt->vuse;
 }
 
 /* Return the single VDEF operand of the statement G.  */
@@ -1271,9 +1581,11 @@ gimple_vuse_ptr (gimple g)
 static inline tree *
 gimple_vdef_ptr (gimple g)
 {
-  if (!gimple_has_mem_ops (g))
+  gimple_statement_with_memory_ops *mem_ops_stmt =
+     dyn_cast <gimple_statement_with_memory_ops> (g);
+  if (!mem_ops_stmt)
     return NULL;
-  return &g->gsmembase.vdef;
+  return &mem_ops_stmt->vdef;
 }
 
 /* Set the single VUSE operand of the statement G.  */
@@ -1303,7 +1615,7 @@ gimple_set_vdef (gimple g, tree vdef)
 static inline bool
 gimple_modified_p (const_gimple g)
 {
-  return (gimple_has_ops (g)) ? (bool) g->gsbase.modified : false;
+  return (gimple_has_ops (g)) ? (bool) g->modified : false;
 }
 
 
@@ -1314,7 +1626,7 @@ static inline void
 gimple_set_modified (gimple s, bool modifiedp)
 {
   if (gimple_has_ops (s))
-    s->gsbase.modified = (unsigned) modifiedp;
+    s->modified = (unsigned) modifiedp;
 }
 
 
@@ -1329,7 +1641,7 @@ gimple_expr_code (const_gimple stmt)
 {
   enum gimple_code code = gimple_code (stmt);
   if (code == GIMPLE_ASSIGN || code == GIMPLE_COND)
-    return (enum tree_code) stmt->gsbase.subcode;
+    return (enum tree_code) stmt->subcode;
   else
     {
       gcc_gimple_checking_assert (code == GIMPLE_CALL);
@@ -1344,7 +1656,7 @@ static inline bool
 gimple_has_volatile_ops (const_gimple stmt)
 {
   if (gimple_has_mem_ops (stmt))
-    return stmt->gsbase.has_volatile_ops;
+    return stmt->has_volatile_ops;
   else
     return false;
 }
@@ -1356,7 +1668,7 @@ static inline void
 gimple_set_has_volatile_ops (gimple stmt, bool volatilep)
 {
   if (gimple_has_mem_ops (stmt))
-    stmt->gsbase.has_volatile_ops = (unsigned) volatilep;
+    stmt->has_volatile_ops = (unsigned) volatilep;
 }
 
 /* Return true if STMT is in a transaction.  */
@@ -1383,7 +1695,7 @@ gimple_omp_subcode (const_gimple s)
 {
   gcc_gimple_checking_assert (gimple_code (s) >= GIMPLE_OMP_ATOMIC_LOAD
 	      && gimple_code (s) <= GIMPLE_OMP_TEAMS);
-  return s->gsbase.subcode;
+  return s->subcode;
 }
 
 /* Set the subcode for OMP statement S to SUBCODE.  */
@@ -1394,7 +1706,7 @@ gimple_omp_set_subcode (gimple s, unsigned int subcode)
   /* We only have 16 bits for the subcode.  Assert that we are not
      overflowing it.  */
   gcc_gimple_checking_assert (subcode < (1 << 16));
-  s->gsbase.subcode = subcode;
+  s->subcode = subcode;
 }
 
 /* Set the nowait flag on OMP_RETURN statement S.  */
@@ -1403,7 +1715,7 @@ static inline void
 gimple_omp_return_set_nowait (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_OMP_RETURN);
-  s->gsbase.subcode |= GF_OMP_RETURN_NOWAIT;
+  s->subcode |= GF_OMP_RETURN_NOWAIT;
 }
 
 
@@ -1423,8 +1735,9 @@ gimple_omp_return_nowait_p (const_gimple g)
 static inline void
 gimple_omp_return_set_lhs (gimple g, tree lhs)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
-  g->gimple_omp_atomic_store.val = lhs;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  omp_atomic_store_stmt->val = lhs;
 }
 
 
@@ -1433,8 +1746,9 @@ gimple_omp_return_set_lhs (gimple g, tree lhs)
 static inline tree
 gimple_omp_return_lhs (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
-  return g->gimple_omp_atomic_store.val;
+  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;
 }
 
 
@@ -1443,8 +1757,9 @@ gimple_omp_return_lhs (const_gimple g)
 static inline tree *
 gimple_omp_return_lhs_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_RETURN);
-  return &g->gimple_omp_atomic_store.val;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  return &omp_atomic_store_stmt->val;
 }
 
 
@@ -1465,7 +1780,7 @@ static inline void
 gimple_omp_section_set_last (gimple g)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_SECTION);
-  g->gsbase.subcode |= GF_OMP_SECTION_LAST;
+  g->subcode |= GF_OMP_SECTION_LAST;
 }
 
 
@@ -1488,9 +1803,9 @@ gimple_omp_parallel_set_combined_p (gimple g, bool combined_p)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_PARALLEL);
   if (combined_p)
-    g->gsbase.subcode |= GF_OMP_PARALLEL_COMBINED;
+    g->subcode |= GF_OMP_PARALLEL_COMBINED;
   else
-    g->gsbase.subcode &= ~GF_OMP_PARALLEL_COMBINED;
+    g->subcode &= ~GF_OMP_PARALLEL_COMBINED;
 }
 
 
@@ -1513,7 +1828,7 @@ gimple_omp_atomic_set_need_value (gimple g)
 {
   if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
     GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  g->gsbase.subcode |= GF_OMP_ATOMIC_NEED_VALUE;
+  g->subcode |= GF_OMP_ATOMIC_NEED_VALUE;
 }
 
 
@@ -1536,7 +1851,7 @@ gimple_omp_atomic_set_seq_cst (gimple g)
 {
   if (gimple_code (g) != GIMPLE_OMP_ATOMIC_LOAD)
     GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  g->gsbase.subcode |= GF_OMP_ATOMIC_SEQ_CST;
+  g->subcode |= GF_OMP_ATOMIC_SEQ_CST;
 }
 
 
@@ -1545,7 +1860,7 @@ gimple_omp_atomic_set_seq_cst (gimple g)
 static inline unsigned
 gimple_num_ops (const_gimple gs)
 {
-  return gs->gsbase.num_ops;
+  return gs->num_ops;
 }
 
 
@@ -1554,7 +1869,7 @@ gimple_num_ops (const_gimple gs)
 static inline void
 gimple_set_num_ops (gimple gs, unsigned num_ops)
 {
-  gs->gsbase.num_ops = num_ops;
+  gs->num_ops = num_ops;
 }
 
 
@@ -1785,7 +2100,7 @@ static inline bool
 gimple_assign_nontemporal_move_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gs->gsbase.nontemporal_move;
+  return gs->nontemporal_move;
 }
 
 /* Sets nontemporal move flag of GS to NONTEMPORAL.  */
@@ -1794,7 +2109,7 @@ static inline void
 gimple_assign_set_nontemporal_move (gimple gs, bool nontemporal)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  gs->gsbase.nontemporal_move = nontemporal;
+  gs->nontemporal_move = nontemporal;
 }
 
 
@@ -1808,7 +2123,7 @@ gimple_assign_rhs_code (const_gimple gs)
   enum tree_code code;
   GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
 
-  code = (enum tree_code) gs->gsbase.subcode;
+  code = (enum tree_code) gs->subcode;
   /* While we initially set subcode to the TREE_CODE of the rhs for
      GIMPLE_SINGLE_RHS assigns we do not update that subcode to stay
      in sync when we rewrite stmts into SSA form or do SSA propagations.  */
@@ -1826,7 +2141,7 @@ static inline void
 gimple_assign_set_rhs_code (gimple s, enum tree_code code)
 {
   GIMPLE_CHECK (s, GIMPLE_ASSIGN);
-  s->gsbase.subcode = code;
+  s->subcode = code;
 }
 
 
@@ -1951,7 +2266,7 @@ static inline bool
 gimple_call_internal_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
-  return (gs->gsbase.subcode & GF_CALL_INTERNAL) != 0;
+  return (gs->subcode & GF_CALL_INTERNAL) != 0;
 }
 
 
@@ -1962,7 +2277,7 @@ static inline bool
 gimple_call_with_bounds_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
-  return (gs->gsbase.subcode & GF_CALL_WITH_BOUNDS) != 0;
+  return (gs->subcode & GF_CALL_WITH_BOUNDS) != 0;
 }
 
 
@@ -1974,9 +2289,9 @@ gimple_call_set_with_bounds (gimple gs, bool with_bounds)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
   if (with_bounds)
-    gs->gsbase.subcode |= GF_CALL_WITH_BOUNDS;
+    gs->subcode |= GF_CALL_WITH_BOUNDS;
   else
-    gs->gsbase.subcode &= ~GF_CALL_WITH_BOUNDS;
+    gs->subcode &= ~GF_CALL_WITH_BOUNDS;
 }
 
 
@@ -1995,10 +2310,11 @@ gimple_call_internal_fn (const_gimple gs)
 static inline tree
 gimple_call_fntype (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  const gimple_statement_call *call_stmt =
+    as_a <const gimple_statement_call> (gs);
   if (gimple_call_internal_p (gs))
     return NULL_TREE;
-  return gs->gimple_call.u.fntype;
+  return call_stmt->u.fntype;
 }
 
 /* Set the type of the function called by GS to FNTYPE.  */
@@ -2006,9 +2322,9 @@ gimple_call_fntype (const_gimple gs)
 static inline void
 gimple_call_set_fntype (gimple gs, tree fntype)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (gs);
   gcc_gimple_checking_assert (!gimple_call_internal_p (gs));
-  gs->gimple_call.u.fntype = fntype;
+  call_stmt->u.fntype = fntype;
 }
 
 
@@ -2060,9 +2376,9 @@ gimple_call_set_fndecl (gimple gs, tree decl)
 static inline void
 gimple_call_set_internal_fn (gimple gs, enum internal_fn fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CALL);
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (gs);
   gcc_gimple_checking_assert (gimple_call_internal_p (gs));
-  gs->gimple_call.u.internal_fn = fn;
+  call_stmt->u.internal_fn = fn;
 }
 
 
@@ -2175,9 +2491,9 @@ gimple_call_set_tail (gimple s, bool tail_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (tail_p)
-    s->gsbase.subcode |= GF_CALL_TAILCALL;
+    s->subcode |= GF_CALL_TAILCALL;
   else
-    s->gsbase.subcode &= ~GF_CALL_TAILCALL;
+    s->subcode &= ~GF_CALL_TAILCALL;
 }
 
 
@@ -2187,7 +2503,7 @@ static inline bool
 gimple_call_tail_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_TAILCALL) != 0;
+  return (s->subcode & GF_CALL_TAILCALL) != 0;
 }
 
 
@@ -2200,9 +2516,9 @@ gimple_call_set_return_slot_opt (gimple s, bool return_slot_opt_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (return_slot_opt_p)
-    s->gsbase.subcode |= GF_CALL_RETURN_SLOT_OPT;
+    s->subcode |= GF_CALL_RETURN_SLOT_OPT;
   else
-    s->gsbase.subcode &= ~GF_CALL_RETURN_SLOT_OPT;
+    s->subcode &= ~GF_CALL_RETURN_SLOT_OPT;
 }
 
 
@@ -2212,7 +2528,7 @@ static inline bool
 gimple_call_return_slot_opt_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_RETURN_SLOT_OPT) != 0;
+  return (s->subcode & GF_CALL_RETURN_SLOT_OPT) != 0;
 }
 
 
@@ -2224,9 +2540,9 @@ gimple_call_set_from_thunk (gimple s, bool from_thunk_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (from_thunk_p)
-    s->gsbase.subcode |= GF_CALL_FROM_THUNK;
+    s->subcode |= GF_CALL_FROM_THUNK;
   else
-    s->gsbase.subcode &= ~GF_CALL_FROM_THUNK;
+    s->subcode &= ~GF_CALL_FROM_THUNK;
 }
 
 
@@ -2236,7 +2552,7 @@ static inline bool
 gimple_call_from_thunk_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_FROM_THUNK) != 0;
+  return (s->subcode & GF_CALL_FROM_THUNK) != 0;
 }
 
 
@@ -2248,9 +2564,9 @@ gimple_call_set_va_arg_pack (gimple s, bool pass_arg_pack_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (pass_arg_pack_p)
-    s->gsbase.subcode |= GF_CALL_VA_ARG_PACK;
+    s->subcode |= GF_CALL_VA_ARG_PACK;
   else
-    s->gsbase.subcode &= ~GF_CALL_VA_ARG_PACK;
+    s->subcode &= ~GF_CALL_VA_ARG_PACK;
 }
 
 
@@ -2261,7 +2577,7 @@ static inline bool
 gimple_call_va_arg_pack_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_VA_ARG_PACK) != 0;
+  return (s->subcode & GF_CALL_VA_ARG_PACK) != 0;
 }
 
 
@@ -2283,9 +2599,9 @@ gimple_call_set_nothrow (gimple s, bool nothrow_p)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (nothrow_p)
-    s->gsbase.subcode |= GF_CALL_NOTHROW;
+    s->subcode |= GF_CALL_NOTHROW;
   else
-    s->gsbase.subcode &= ~GF_CALL_NOTHROW;
+    s->subcode &= ~GF_CALL_NOTHROW;
 }
 
 /* Return true if S is a nothrow call.  */
@@ -2307,9 +2623,9 @@ gimple_call_set_alloca_for_var (gimple s, bool for_var)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
   if (for_var)
-    s->gsbase.subcode |= GF_CALL_ALLOCA_FOR_VAR;
+    s->subcode |= GF_CALL_ALLOCA_FOR_VAR;
   else
-    s->gsbase.subcode &= ~GF_CALL_ALLOCA_FOR_VAR;
+    s->subcode &= ~GF_CALL_ALLOCA_FOR_VAR;
 }
 
 /* Return true of S is a call to builtin_alloca emitted for VLA objects.  */
@@ -2318,7 +2634,7 @@ static inline bool
 gimple_call_alloca_for_var_p (gimple s)
 {
   GIMPLE_CHECK (s, GIMPLE_CALL);
-  return (s->gsbase.subcode & GF_CALL_ALLOCA_FOR_VAR) != 0;
+  return (s->subcode & GF_CALL_ALLOCA_FOR_VAR) != 0;
 }
 
 /* Copy all the GF_CALL_* flags from ORIG_CALL to DEST_CALL.  */
@@ -2328,7 +2644,7 @@ gimple_call_copy_flags (gimple dest_call, gimple orig_call)
 {
   GIMPLE_CHECK (dest_call, GIMPLE_CALL);
   GIMPLE_CHECK (orig_call, GIMPLE_CALL);
-  dest_call->gsbase.subcode = orig_call->gsbase.subcode;
+  dest_call->subcode = orig_call->subcode;
 }
 
 
@@ -2338,8 +2654,8 @@ gimple_call_copy_flags (gimple dest_call, gimple orig_call)
 static inline struct pt_solution *
 gimple_call_use_set (gimple call)
 {
-  GIMPLE_CHECK (call, GIMPLE_CALL);
-  return &call->gimple_call.call_used;
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (call);
+  return &call_stmt->call_used;
 }
 
 
@@ -2349,8 +2665,8 @@ gimple_call_use_set (gimple call)
 static inline struct pt_solution *
 gimple_call_clobber_set (gimple call)
 {
-  GIMPLE_CHECK (call, GIMPLE_CALL);
-  return &call->gimple_call.call_clobbered;
+  gimple_statement_call *call_stmt = as_a <gimple_statement_call> (call);
+  return &call_stmt->call_clobbered;
 }
 
 
@@ -2372,7 +2688,7 @@ static inline enum tree_code
 gimple_cond_code (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_COND);
-  return (enum tree_code) gs->gsbase.subcode;
+  return (enum tree_code) gs->subcode;
 }
 
 
@@ -2382,7 +2698,7 @@ static inline void
 gimple_cond_set_code (gimple gs, enum tree_code code)
 {
   GIMPLE_CHECK (gs, GIMPLE_COND);
-  gs->gsbase.subcode = code;
+  gs->subcode = code;
 }
 
 
@@ -2498,7 +2814,7 @@ gimple_cond_make_false (gimple gs)
 {
   gimple_cond_set_lhs (gs, boolean_true_node);
   gimple_cond_set_rhs (gs, boolean_false_node);
-  gs->gsbase.subcode = EQ_EXPR;
+  gs->subcode = EQ_EXPR;
 }
 
 
@@ -2509,7 +2825,7 @@ gimple_cond_make_true (gimple gs)
 {
   gimple_cond_set_lhs (gs, boolean_true_node);
   gimple_cond_set_rhs (gs, boolean_true_node);
-  gs->gsbase.subcode = EQ_EXPR;
+  gs->subcode = EQ_EXPR;
 }
 
 /* Check if conditional statemente GS is of the form 'if (1 == 1)',
@@ -2618,8 +2934,9 @@ gimple_goto_set_dest (gimple gs, tree dest)
 static inline tree
 gimple_bind_vars (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  return gs->gimple_bind.vars;
+  const gimple_statement_bind *bind_stmt =
+    as_a <const gimple_statement_bind> (gs);
+  return bind_stmt->vars;
 }
 
 
@@ -2629,8 +2946,8 @@ gimple_bind_vars (const_gimple gs)
 static inline void
 gimple_bind_set_vars (gimple gs, tree vars)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gs->gimple_bind.vars = vars;
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  bind_stmt->vars = vars;
 }
 
 
@@ -2640,16 +2957,16 @@ gimple_bind_set_vars (gimple gs, tree vars)
 static inline void
 gimple_bind_append_vars (gimple gs, tree vars)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gs->gimple_bind.vars = chainon (gs->gimple_bind.vars, vars);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  bind_stmt->vars = chainon (bind_stmt->vars, vars);
 }
 
 
 static inline gimple_seq *
 gimple_bind_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  return &gs->gimple_bind.body;
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  return &bind_stmt->body;
 }
 
 /* Return the GIMPLE sequence contained in the GIMPLE_BIND statement GS.  */
@@ -2667,8 +2984,8 @@ gimple_bind_body (gimple gs)
 static inline void
 gimple_bind_set_body (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gs->gimple_bind.body = seq;
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  bind_stmt->body = seq;
 }
 
 
@@ -2677,8 +2994,8 @@ gimple_bind_set_body (gimple gs, gimple_seq seq)
 static inline void
 gimple_bind_add_stmt (gimple gs, gimple stmt)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gimple_seq_add_stmt (&gs->gimple_bind.body, stmt);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  gimple_seq_add_stmt (&bind_stmt->body, stmt);
 }
 
 
@@ -2687,8 +3004,8 @@ gimple_bind_add_stmt (gimple gs, gimple stmt)
 static inline void
 gimple_bind_add_seq (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  gimple_seq_add_seq (&gs->gimple_bind.body, seq);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
+  gimple_seq_add_seq (&bind_stmt->body, seq);
 }
 
 
@@ -2698,8 +3015,9 @@ gimple_bind_add_seq (gimple gs, gimple_seq seq)
 static inline tree
 gimple_bind_block (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
-  return gs->gimple_bind.block;
+  const gimple_statement_bind *bind_stmt =
+    as_a <const gimple_statement_bind> (gs);
+  return bind_stmt->block;
 }
 
 
@@ -2709,10 +3027,10 @@ gimple_bind_block (const_gimple gs)
 static inline void
 gimple_bind_set_block (gimple gs, tree block)
 {
-  GIMPLE_CHECK (gs, GIMPLE_BIND);
+  gimple_statement_bind *bind_stmt = as_a <gimple_statement_bind> (gs);
   gcc_gimple_checking_assert (block == NULL_TREE
 			      || TREE_CODE (block) == BLOCK);
-  gs->gimple_bind.block = block;
+  bind_stmt->block = block;
 }
 
 
@@ -2721,8 +3039,9 @@ gimple_bind_set_block (gimple gs, tree block)
 static inline unsigned
 gimple_asm_ninputs (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.ni;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->ni;
 }
 
 
@@ -2731,8 +3050,9 @@ gimple_asm_ninputs (const_gimple gs)
 static inline unsigned
 gimple_asm_noutputs (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.no;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->no;
 }
 
 
@@ -2741,8 +3061,9 @@ gimple_asm_noutputs (const_gimple gs)
 static inline unsigned
 gimple_asm_nclobbers (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.nc;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->nc;
 }
 
 /* Return the number of label operands for GIMPLE_ASM GS.  */
@@ -2750,8 +3071,9 @@ gimple_asm_nclobbers (const_gimple gs)
 static inline unsigned
 gimple_asm_nlabels (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.nl;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->nl;
 }
 
 /* Return input operand INDEX of GIMPLE_ASM GS.  */
@@ -2759,9 +3081,10 @@ gimple_asm_nlabels (const_gimple gs)
 static inline tree
 gimple_asm_input_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.ni);
-  return gimple_op (gs, index + gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->ni);
+  return gimple_op (gs, index + asm_stmt->no);
 }
 
 /* Return a pointer to input operand INDEX of GIMPLE_ASM GS.  */
@@ -2769,9 +3092,10 @@ gimple_asm_input_op (const_gimple gs, unsigned index)
 static inline tree *
 gimple_asm_input_op_ptr (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.ni);
-  return gimple_op_ptr (gs, index + gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->ni);
+  return gimple_op_ptr (gs, index + asm_stmt->no);
 }
 
 
@@ -2780,10 +3104,10 @@ gimple_asm_input_op_ptr (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_input_op (gimple gs, unsigned index, tree in_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.ni
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->ni
 			      && TREE_CODE (in_op) == TREE_LIST);
-  gimple_set_op (gs, index + gs->gimple_asm.no, in_op);
+  gimple_set_op (gs, index + asm_stmt->no, in_op);
 }
 
 
@@ -2792,8 +3116,9 @@ gimple_asm_set_input_op (gimple gs, unsigned index, tree in_op)
 static inline tree
 gimple_asm_output_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->no);
   return gimple_op (gs, index);
 }
 
@@ -2802,8 +3127,9 @@ gimple_asm_output_op (const_gimple gs, unsigned index)
 static inline tree *
 gimple_asm_output_op_ptr (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->no);
   return gimple_op_ptr (gs, index);
 }
 
@@ -2813,8 +3139,8 @@ gimple_asm_output_op_ptr (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_output_op (gimple gs, unsigned index, tree out_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.no
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->no
 			      && TREE_CODE (out_op) == TREE_LIST);
   gimple_set_op (gs, index, out_op);
 }
@@ -2825,9 +3151,10 @@ gimple_asm_set_output_op (gimple gs, unsigned index, tree out_op)
 static inline tree
 gimple_asm_clobber_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nc);
-  return gimple_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.no);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nc);
+  return gimple_op (gs, index + asm_stmt->ni + asm_stmt->no);
 }
 
 
@@ -2836,10 +3163,10 @@ gimple_asm_clobber_op (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_clobber_op (gimple gs, unsigned index, tree clobber_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nc
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nc
 			      && TREE_CODE (clobber_op) == TREE_LIST);
-  gimple_set_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.no, clobber_op);
+  gimple_set_op (gs, index + asm_stmt->ni + asm_stmt->no, clobber_op);
 }
 
 /* Return label operand INDEX of GIMPLE_ASM GS.  */
@@ -2847,9 +3174,10 @@ gimple_asm_set_clobber_op (gimple gs, unsigned index, tree clobber_op)
 static inline tree
 gimple_asm_label_op (const_gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nl);
-  return gimple_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.nc);
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nl);
+  return gimple_op (gs, index + asm_stmt->ni + asm_stmt->nc);
 }
 
 /* Set LABEL_OP to be label operand INDEX in GIMPLE_ASM GS.  */
@@ -2857,10 +3185,10 @@ gimple_asm_label_op (const_gimple gs, unsigned index)
 static inline void
 gimple_asm_set_label_op (gimple gs, unsigned index, tree label_op)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  gcc_gimple_checking_assert (index < gs->gimple_asm.nl
+  gimple_statement_asm *asm_stmt = as_a <gimple_statement_asm> (gs);
+  gcc_gimple_checking_assert (index < asm_stmt->nl
 			      && TREE_CODE (label_op) == TREE_LIST);
-  gimple_set_op (gs, index + gs->gimple_asm.ni + gs->gimple_asm.nc, label_op);
+  gimple_set_op (gs, index + asm_stmt->ni + asm_stmt->nc, label_op);
 }
 
 /* Return the string representing the assembly instruction in
@@ -2869,8 +3197,9 @@ gimple_asm_set_label_op (gimple gs, unsigned index, tree label_op)
 static inline const char *
 gimple_asm_string (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return gs->gimple_asm.string;
+  const gimple_statement_asm *asm_stmt =
+    as_a <const gimple_statement_asm> (gs);
+  return asm_stmt->string;
 }
 
 
@@ -2880,7 +3209,7 @@ static inline bool
 gimple_asm_volatile_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return (gs->gsbase.subcode & GF_ASM_VOLATILE) != 0;
+  return (gs->subcode & GF_ASM_VOLATILE) != 0;
 }
 
 
@@ -2891,9 +3220,9 @@ gimple_asm_set_volatile (gimple gs, bool volatile_p)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   if (volatile_p)
-    gs->gsbase.subcode |= GF_ASM_VOLATILE;
+    gs->subcode |= GF_ASM_VOLATILE;
   else
-    gs->gsbase.subcode &= ~GF_ASM_VOLATILE;
+    gs->subcode &= ~GF_ASM_VOLATILE;
 }
 
 
@@ -2904,9 +3233,9 @@ gimple_asm_set_input (gimple gs, bool input_p)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   if (input_p)
-    gs->gsbase.subcode |= GF_ASM_INPUT;
+    gs->subcode |= GF_ASM_INPUT;
   else
-    gs->gsbase.subcode &= ~GF_ASM_INPUT;
+    gs->subcode &= ~GF_ASM_INPUT;
 }
 
 
@@ -2916,7 +3245,7 @@ static inline bool
 gimple_asm_input_p (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
-  return (gs->gsbase.subcode & GF_ASM_INPUT) != 0;
+  return (gs->subcode & GF_ASM_INPUT) != 0;
 }
 
 
@@ -2925,8 +3254,9 @@ gimple_asm_input_p (const_gimple gs)
 static inline tree
 gimple_catch_types (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  return gs->gimple_catch.types;
+  const gimple_statement_catch *catch_stmt =
+    as_a <const gimple_statement_catch> (gs);
+  return catch_stmt->types;
 }
 
 
@@ -2935,8 +3265,8 @@ gimple_catch_types (const_gimple gs)
 static inline tree *
 gimple_catch_types_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  return &gs->gimple_catch.types;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  return &catch_stmt->types;
 }
 
 
@@ -2946,8 +3276,8 @@ gimple_catch_types_ptr (gimple gs)
 static inline gimple_seq *
 gimple_catch_handler_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  return &gs->gimple_catch.handler;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  return &catch_stmt->handler;
 }
 
 
@@ -2966,8 +3296,8 @@ gimple_catch_handler (gimple gs)
 static inline void
 gimple_catch_set_types (gimple gs, tree t)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  gs->gimple_catch.types = t;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  catch_stmt->types = t;
 }
 
 
@@ -2976,8 +3306,8 @@ gimple_catch_set_types (gimple gs, tree t)
 static inline void
 gimple_catch_set_handler (gimple gs, gimple_seq handler)
 {
-  GIMPLE_CHECK (gs, GIMPLE_CATCH);
-  gs->gimple_catch.handler = handler;
+  gimple_statement_catch *catch_stmt = as_a <gimple_statement_catch> (gs);
+  catch_stmt->handler = handler;
 }
 
 
@@ -2986,8 +3316,9 @@ gimple_catch_set_handler (gimple gs, gimple_seq handler)
 static inline tree
 gimple_eh_filter_types (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  return gs->gimple_eh_filter.types;
+  const gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <const gimple_statement_eh_filter> (gs);
+  return eh_filter_stmt->types;
 }
 
 
@@ -2997,8 +3328,9 @@ gimple_eh_filter_types (const_gimple gs)
 static inline tree *
 gimple_eh_filter_types_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  return &gs->gimple_eh_filter.types;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  return &eh_filter_stmt->types;
 }
 
 
@@ -3008,8 +3340,9 @@ gimple_eh_filter_types_ptr (gimple gs)
 static inline gimple_seq *
 gimple_eh_filter_failure_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  return &gs->gimple_eh_filter.failure;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  return &eh_filter_stmt->failure;
 }
 
 
@@ -3028,8 +3361,9 @@ gimple_eh_filter_failure (gimple gs)
 static inline void
 gimple_eh_filter_set_types (gimple gs, tree types)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  gs->gimple_eh_filter.types = types;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  eh_filter_stmt->types = types;
 }
 
 
@@ -3039,8 +3373,9 @@ gimple_eh_filter_set_types (gimple gs, tree types)
 static inline void
 gimple_eh_filter_set_failure (gimple gs, gimple_seq failure)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_FILTER);
-  gs->gimple_eh_filter.failure = failure;
+  gimple_statement_eh_filter *eh_filter_stmt =
+    as_a <gimple_statement_eh_filter> (gs);
+  eh_filter_stmt->failure = failure;
 }
 
 /* Get the function decl to be called by the MUST_NOT_THROW region.  */
@@ -3048,8 +3383,8 @@ gimple_eh_filter_set_failure (gimple gs, gimple_seq failure)
 static inline tree
 gimple_eh_must_not_throw_fndecl (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_MUST_NOT_THROW);
-  return gs->gimple_eh_mnt.fndecl;
+  gimple_statement_eh_mnt *eh_mnt_stmt = as_a <gimple_statement_eh_mnt> (gs);
+  return eh_mnt_stmt->fndecl;
 }
 
 /* Set the function decl to be called by GS to DECL.  */
@@ -3057,8 +3392,8 @@ gimple_eh_must_not_throw_fndecl (gimple gs)
 static inline void
 gimple_eh_must_not_throw_set_fndecl (gimple gs, tree decl)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_MUST_NOT_THROW);
-  gs->gimple_eh_mnt.fndecl = decl;
+  gimple_statement_eh_mnt *eh_mnt_stmt = as_a <gimple_statement_eh_mnt> (gs);
+  eh_mnt_stmt->fndecl = decl;
 }
 
 /* GIMPLE_EH_ELSE accessors.  */
@@ -3066,8 +3401,9 @@ gimple_eh_must_not_throw_set_fndecl (gimple gs, tree decl)
 static inline gimple_seq *
 gimple_eh_else_n_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  return &gs->gimple_eh_else.n_body;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  return &eh_else_stmt->n_body;
 }
 
 static inline gimple_seq
@@ -3079,8 +3415,9 @@ gimple_eh_else_n_body (gimple gs)
 static inline gimple_seq *
 gimple_eh_else_e_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  return &gs->gimple_eh_else.e_body;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  return &eh_else_stmt->e_body;
 }
 
 static inline gimple_seq
@@ -3092,15 +3429,17 @@ gimple_eh_else_e_body (gimple gs)
 static inline void
 gimple_eh_else_set_n_body (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  gs->gimple_eh_else.n_body = seq;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  eh_else_stmt->n_body = seq;
 }
 
 static inline void
 gimple_eh_else_set_e_body (gimple gs, gimple_seq seq)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
-  gs->gimple_eh_else.e_body = seq;
+  gimple_statement_eh_else *eh_else_stmt =
+    as_a <gimple_statement_eh_else> (gs);
+  eh_else_stmt->e_body = seq;
 }
 
 /* GIMPLE_TRY accessors. */
@@ -3112,7 +3451,7 @@ static inline enum gimple_try_flags
 gimple_try_kind (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return (enum gimple_try_flags) (gs->gsbase.subcode & GIMPLE_TRY_KIND);
+  return (enum gimple_try_flags) (gs->subcode & GIMPLE_TRY_KIND);
 }
 
 
@@ -3125,7 +3464,7 @@ gimple_try_set_kind (gimple gs, enum gimple_try_flags kind)
   gcc_gimple_checking_assert (kind == GIMPLE_TRY_CATCH
 			      || kind == GIMPLE_TRY_FINALLY);
   if (gimple_try_kind (gs) != kind)
-    gs->gsbase.subcode = (unsigned int) kind;
+    gs->subcode = (unsigned int) kind;
 }
 
 
@@ -3135,7 +3474,7 @@ static inline bool
 gimple_try_catch_is_cleanup (const_gimple gs)
 {
   gcc_gimple_checking_assert (gimple_try_kind (gs) == GIMPLE_TRY_CATCH);
-  return (gs->gsbase.subcode & GIMPLE_TRY_CATCH_IS_CLEANUP) != 0;
+  return (gs->subcode & GIMPLE_TRY_CATCH_IS_CLEANUP) != 0;
 }
 
 
@@ -3145,8 +3484,8 @@ gimple_try_catch_is_cleanup (const_gimple gs)
 static inline gimple_seq *
 gimple_try_eval_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return &gs->gimple_try.eval;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  return &try_stmt->eval;
 }
 
 
@@ -3165,8 +3504,8 @@ gimple_try_eval (gimple gs)
 static inline gimple_seq *
 gimple_try_cleanup_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  return &gs->gimple_try.cleanup;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  return &try_stmt->cleanup;
 }
 
 
@@ -3187,9 +3526,9 @@ gimple_try_set_catch_is_cleanup (gimple g, bool catch_is_cleanup)
 {
   gcc_gimple_checking_assert (gimple_try_kind (g) == GIMPLE_TRY_CATCH);
   if (catch_is_cleanup)
-    g->gsbase.subcode |= GIMPLE_TRY_CATCH_IS_CLEANUP;
+    g->subcode |= GIMPLE_TRY_CATCH_IS_CLEANUP;
   else
-    g->gsbase.subcode &= ~GIMPLE_TRY_CATCH_IS_CLEANUP;
+    g->subcode &= ~GIMPLE_TRY_CATCH_IS_CLEANUP;
 }
 
 
@@ -3199,8 +3538,8 @@ gimple_try_set_catch_is_cleanup (gimple g, bool catch_is_cleanup)
 static inline void
 gimple_try_set_eval (gimple gs, gimple_seq eval)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  gs->gimple_try.eval = eval;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  try_stmt->eval = eval;
 }
 
 
@@ -3210,8 +3549,8 @@ gimple_try_set_eval (gimple gs, gimple_seq eval)
 static inline void
 gimple_try_set_cleanup (gimple gs, gimple_seq cleanup)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRY);
-  gs->gimple_try.cleanup = cleanup;
+  gimple_statement_try *try_stmt = as_a <gimple_statement_try> (gs);
+  try_stmt->cleanup = cleanup;
 }
 
 
@@ -3220,8 +3559,8 @@ gimple_try_set_cleanup (gimple gs, gimple_seq cleanup)
 static inline gimple_seq *
 gimple_wce_cleanup_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  return &gs->gimple_wce.cleanup;
+  gimple_statement_wce *wce_stmt = as_a <gimple_statement_wce> (gs);
+  return &wce_stmt->cleanup;
 }
 
 
@@ -3239,8 +3578,8 @@ gimple_wce_cleanup (gimple gs)
 static inline void
 gimple_wce_set_cleanup (gimple gs, gimple_seq cleanup)
 {
-  GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  gs->gimple_wce.cleanup = cleanup;
+  gimple_statement_wce *wce_stmt = as_a <gimple_statement_wce> (gs);
+  wce_stmt->cleanup = cleanup;
 }
 
 
@@ -3250,7 +3589,7 @@ static inline bool
 gimple_wce_cleanup_eh_only (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  return gs->gsbase.subcode != 0;
+  return gs->subcode != 0;
 }
 
 
@@ -3260,7 +3599,7 @@ static inline void
 gimple_wce_set_cleanup_eh_only (gimple gs, bool eh_only_p)
 {
   GIMPLE_CHECK (gs, GIMPLE_WITH_CLEANUP_EXPR);
-  gs->gsbase.subcode = (unsigned int) eh_only_p;
+  gs->subcode = (unsigned int) eh_only_p;
 }
 
 
@@ -3269,8 +3608,9 @@ gimple_wce_set_cleanup_eh_only (gimple gs, bool eh_only_p)
 static inline unsigned
 gimple_phi_capacity (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return gs->gimple_phi.capacity;
+  const gimple_statement_phi *phi_stmt =
+    as_a <const gimple_statement_phi> (gs);
+  return phi_stmt->capacity;
 }
 
 
@@ -3281,8 +3621,9 @@ gimple_phi_capacity (const_gimple gs)
 static inline unsigned
 gimple_phi_num_args (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return gs->gimple_phi.nargs;
+  const gimple_statement_phi *phi_stmt =
+    as_a <const gimple_statement_phi> (gs);
+  return phi_stmt->nargs;
 }
 
 
@@ -3291,8 +3632,9 @@ gimple_phi_num_args (const_gimple gs)
 static inline tree
 gimple_phi_result (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return gs->gimple_phi.result;
+  const gimple_statement_phi *phi_stmt =
+    as_a <const gimple_statement_phi> (gs);
+  return phi_stmt->result;
 }
 
 /* Return a pointer to the SSA name created by GIMPLE_PHI GS.  */
@@ -3300,8 +3642,8 @@ gimple_phi_result (const_gimple gs)
 static inline tree *
 gimple_phi_result_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  return &gs->gimple_phi.result;
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  return &phi_stmt->result;
 }
 
 /* Set RESULT to be the SSA name created by GIMPLE_PHI GS.  */
@@ -3309,8 +3651,8 @@ gimple_phi_result_ptr (gimple gs)
 static inline void
 gimple_phi_set_result (gimple gs, tree result)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  gs->gimple_phi.result = result;
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  phi_stmt->result = result;
   if (result && TREE_CODE (result) == SSA_NAME)
     SSA_NAME_DEF_STMT (result) = gs;
 }
@@ -3322,9 +3664,9 @@ gimple_phi_set_result (gimple gs, tree result)
 static inline struct phi_arg_d *
 gimple_phi_arg (gimple gs, unsigned index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  gcc_gimple_checking_assert (index <= gs->gimple_phi.capacity);
-  return &(gs->gimple_phi.args[index]);
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  gcc_gimple_checking_assert (index <= phi_stmt->capacity);
+  return &(phi_stmt->args[index]);
 }
 
 /* Set PHIARG to be the argument corresponding to incoming edge INDEX
@@ -3333,9 +3675,9 @@ gimple_phi_arg (gimple gs, unsigned index)
 static inline void
 gimple_phi_set_arg (gimple gs, unsigned index, struct phi_arg_d * phiarg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_PHI);
-  gcc_gimple_checking_assert (index <= gs->gimple_phi.nargs);
-  gs->gimple_phi.args[index] = *phiarg;
+  gimple_statement_phi *phi_stmt = as_a <gimple_statement_phi> (gs);
+  gcc_gimple_checking_assert (index <= phi_stmt->nargs);
+  phi_stmt->args[index] = *phiarg;
 }
 
 /* Return the PHI nodes for basic block BB, or NULL if there are no
@@ -3420,8 +3762,9 @@ gimple_phi_arg_has_location (gimple gs, size_t i)
 static inline int
 gimple_resx_region (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_RESX);
-  return gs->gimple_eh_ctrl.region;
+  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <const gimple_statement_eh_ctrl> (gs);
+  return eh_ctrl_stmt->region;
 }
 
 /* Set REGION to be the region number for GIMPLE_RESX GS.  */
@@ -3429,8 +3772,9 @@ gimple_resx_region (const_gimple gs)
 static inline void
 gimple_resx_set_region (gimple gs, int region)
 {
-  GIMPLE_CHECK (gs, GIMPLE_RESX);
-  gs->gimple_eh_ctrl.region = region;
+  gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <gimple_statement_eh_ctrl> (gs);
+  eh_ctrl_stmt->region = region;
 }
 
 /* Return the region number for GIMPLE_EH_DISPATCH GS.  */
@@ -3438,8 +3782,9 @@ gimple_resx_set_region (gimple gs, int region)
 static inline int
 gimple_eh_dispatch_region (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_DISPATCH);
-  return gs->gimple_eh_ctrl.region;
+  const gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <const gimple_statement_eh_ctrl> (gs);
+  return eh_ctrl_stmt->region;
 }
 
 /* Set REGION to be the region number for GIMPLE_EH_DISPATCH GS.  */
@@ -3447,8 +3792,9 @@ gimple_eh_dispatch_region (const_gimple gs)
 static inline void
 gimple_eh_dispatch_set_region (gimple gs, int region)
 {
-  GIMPLE_CHECK (gs, GIMPLE_EH_DISPATCH);
-  gs->gimple_eh_ctrl.region = region;
+  gimple_statement_eh_ctrl *eh_ctrl_stmt =
+    as_a <gimple_statement_eh_ctrl> (gs);
+  eh_ctrl_stmt->region = region;
 }
 
 /* Return the number of labels associated with the switch statement GS.  */
@@ -3561,7 +3907,7 @@ static inline bool
 gimple_debug_bind_p (const_gimple s)
 {
   if (is_gimple_debug (s))
-    return s->gsbase.subcode == GIMPLE_DEBUG_BIND;
+    return s->subcode == GIMPLE_DEBUG_BIND;
 
   return false;
 }
@@ -3653,7 +3999,7 @@ static inline bool
 gimple_debug_source_bind_p (const_gimple s)
 {
   if (is_gimple_debug (s))
-    return s->gsbase.subcode == GIMPLE_DEBUG_SOURCE_BIND;
+    return s->subcode == GIMPLE_DEBUG_SOURCE_BIND;
 
   return false;
 }
@@ -3758,8 +4104,9 @@ gimple_omp_set_body (gimple gs, gimple_seq body)
 static inline tree
 gimple_omp_critical_name (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_CRITICAL);
-  return gs->gimple_omp_critical.name;
+  const gimple_statement_omp_critical *omp_critical_stmt =
+    as_a <const gimple_statement_omp_critical> (gs);
+  return omp_critical_stmt->name;
 }
 
 
@@ -3768,8 +4115,9 @@ gimple_omp_critical_name (const_gimple gs)
 static inline tree *
 gimple_omp_critical_name_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_CRITICAL);
-  return &gs->gimple_omp_critical.name;
+  gimple_statement_omp_critical *omp_critical_stmt =
+    as_a <gimple_statement_omp_critical> (gs);
+  return &omp_critical_stmt->name;
 }
 
 
@@ -3778,8 +4126,9 @@ gimple_omp_critical_name_ptr (gimple gs)
 static inline void
 gimple_omp_critical_set_name (gimple gs, tree name)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_CRITICAL);
-  gs->gimple_omp_critical.name = name;
+  gimple_statement_omp_critical *omp_critical_stmt =
+    as_a <gimple_statement_omp_critical> (gs);
+  omp_critical_stmt->name = name;
 }
 
 
@@ -3799,7 +4148,7 @@ static inline void
 gimple_omp_for_set_kind (gimple g, int kind)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
-  g->gsbase.subcode = (g->gsbase.subcode & ~GF_OMP_FOR_KIND_MASK)
+  g->subcode = (g->subcode & ~GF_OMP_FOR_KIND_MASK)
 		      | (kind & GF_OMP_FOR_KIND_MASK);
 }
 
@@ -3823,9 +4172,9 @@ gimple_omp_for_set_combined_p (gimple g, bool combined_p)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
   if (combined_p)
-    g->gsbase.subcode |= GF_OMP_FOR_COMBINED;
+    g->subcode |= GF_OMP_FOR_COMBINED;
   else
-    g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED;
+    g->subcode &= ~GF_OMP_FOR_COMBINED;
 }
 
 
@@ -3848,9 +4197,9 @@ gimple_omp_for_set_combined_into_p (gimple g, bool combined_p)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_FOR);
   if (combined_p)
-    g->gsbase.subcode |= GF_OMP_FOR_COMBINED_INTO;
+    g->subcode |= GF_OMP_FOR_COMBINED_INTO;
   else
-    g->gsbase.subcode &= ~GF_OMP_FOR_COMBINED_INTO;
+    g->subcode &= ~GF_OMP_FOR_COMBINED_INTO;
 }
 
 
@@ -3859,8 +4208,9 @@ gimple_omp_for_set_combined_into_p (gimple g, bool combined_p)
 static inline tree
 gimple_omp_for_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return gs->gimple_omp_for.clauses;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  return omp_for_stmt->clauses;
 }
 
 
@@ -3869,8 +4219,9 @@ gimple_omp_for_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_for_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return &gs->gimple_omp_for.clauses;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  return &omp_for_stmt->clauses;
 }
 
 
@@ -3879,8 +4230,9 @@ gimple_omp_for_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_for_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gs->gimple_omp_for.clauses = clauses;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  omp_for_stmt->clauses = clauses;
 }
 
 
@@ -3889,8 +4241,9 @@ gimple_omp_for_set_clauses (gimple gs, tree clauses)
 static inline size_t
 gimple_omp_for_collapse (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return gs->gimple_omp_for.collapse;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  return omp_for_stmt->collapse;
 }
 
 
@@ -3899,9 +4252,10 @@ gimple_omp_for_collapse (gimple gs)
 static inline tree
 gimple_omp_for_index (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].index;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].index;
 }
 
 
@@ -3910,9 +4264,10 @@ gimple_omp_for_index (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_index_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].index;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].index;
 }
 
 
@@ -3921,9 +4276,10 @@ gimple_omp_for_index_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_index (gimple gs, size_t i, tree index)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].index = index;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].index = index;
 }
 
 
@@ -3932,9 +4288,10 @@ gimple_omp_for_set_index (gimple gs, size_t i, tree index)
 static inline tree
 gimple_omp_for_initial (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].initial;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].initial;
 }
 
 
@@ -3943,9 +4300,10 @@ gimple_omp_for_initial (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_initial_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].initial;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].initial;
 }
 
 
@@ -3954,9 +4312,10 @@ gimple_omp_for_initial_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_initial (gimple gs, size_t i, tree initial)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].initial = initial;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].initial = initial;
 }
 
 
@@ -3965,9 +4324,10 @@ gimple_omp_for_set_initial (gimple gs, size_t i, tree initial)
 static inline tree
 gimple_omp_for_final (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].final;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].final;
 }
 
 
@@ -3976,9 +4336,10 @@ gimple_omp_for_final (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_final_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].final;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].final;
 }
 
 
@@ -3987,9 +4348,10 @@ gimple_omp_for_final_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_final (gimple gs, size_t i, tree final)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].final = final;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].final = final;
 }
 
 
@@ -3998,9 +4360,10 @@ gimple_omp_for_set_final (gimple gs, size_t i, tree final)
 static inline tree
 gimple_omp_for_incr (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].incr;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].incr;
 }
 
 
@@ -4009,9 +4372,10 @@ gimple_omp_for_incr (const_gimple gs, size_t i)
 static inline tree *
 gimple_omp_for_incr_ptr (gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return &gs->gimple_omp_for.iter[i].incr;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return &omp_for_stmt->iter[i].incr;
 }
 
 
@@ -4020,9 +4384,10 @@ gimple_omp_for_incr_ptr (gimple gs, size_t i)
 static inline void
 gimple_omp_for_set_incr (gimple gs, size_t i, tree incr)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].incr = incr;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].incr = incr;
 }
 
 
@@ -4032,8 +4397,9 @@ gimple_omp_for_set_incr (gimple gs, size_t i, tree incr)
 static inline gimple_seq *
 gimple_omp_for_pre_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  return &gs->gimple_omp_for.pre_body;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  return &omp_for_stmt->pre_body;
 }
 
 
@@ -4053,8 +4419,9 @@ gimple_omp_for_pre_body (gimple gs)
 static inline void
 gimple_omp_for_set_pre_body (gimple gs, gimple_seq pre_body)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gs->gimple_omp_for.pre_body = pre_body;
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
+  omp_for_stmt->pre_body = pre_body;
 }
 
 
@@ -4063,8 +4430,9 @@ gimple_omp_for_set_pre_body (gimple gs, gimple_seq pre_body)
 static inline tree
 gimple_omp_parallel_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->clauses;
 }
 
 
@@ -4073,8 +4441,9 @@ gimple_omp_parallel_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_parallel_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->clauses;
 }
 
 
@@ -4084,8 +4453,9 @@ gimple_omp_parallel_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_parallel_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->clauses = clauses;
 }
 
 
@@ -4094,8 +4464,9 @@ gimple_omp_parallel_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_parallel_child_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4104,8 +4475,9 @@ gimple_omp_parallel_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_parallel_child_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->child_fn;
 }
 
 
@@ -4114,8 +4486,9 @@ gimple_omp_parallel_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_parallel_set_child_fn (gimple gs, tree child_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->child_fn = child_fn;
 }
 
 
@@ -4125,8 +4498,9 @@ gimple_omp_parallel_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_parallel_data_arg (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->data_arg;
 }
 
 
@@ -4135,8 +4509,9 @@ gimple_omp_parallel_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_parallel_data_arg_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->data_arg;
 }
 
 
@@ -4145,8 +4520,9 @@ gimple_omp_parallel_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_parallel_set_data_arg (gimple gs, tree data_arg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_PARALLEL);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->data_arg = data_arg;
 }
 
 
@@ -4155,8 +4531,9 @@ gimple_omp_parallel_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_task_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->clauses;
 }
 
 
@@ -4165,8 +4542,9 @@ gimple_omp_task_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_task_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->clauses;
 }
 
 
@@ -4176,8 +4554,9 @@ gimple_omp_task_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->clauses = clauses;
 }
 
 
@@ -4186,8 +4565,9 @@ gimple_omp_task_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_task_child_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4196,8 +4576,9 @@ gimple_omp_task_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_task_child_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->child_fn;
 }
 
 
@@ -4206,8 +4587,9 @@ gimple_omp_task_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_child_fn (gimple gs, tree child_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->child_fn = child_fn;
 }
 
 
@@ -4217,8 +4599,9 @@ gimple_omp_task_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_task_data_arg (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->data_arg;
 }
 
 
@@ -4227,8 +4610,9 @@ gimple_omp_task_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_task_data_arg_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->data_arg;
 }
 
 
@@ -4237,8 +4621,9 @@ gimple_omp_task_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->data_arg = data_arg;
 }
 
 
@@ -4247,9 +4632,9 @@ gimple_omp_task_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_taskreg_clauses (const_gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->clauses;
 }
 
 
@@ -4258,9 +4643,9 @@ gimple_omp_taskreg_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_clauses_ptr (gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->clauses;
 }
 
 
@@ -4270,9 +4655,9 @@ gimple_omp_taskreg_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->clauses = clauses;
 }
 
 
@@ -4281,9 +4666,9 @@ gimple_omp_taskreg_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_taskreg_child_fn (const_gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4292,9 +4677,9 @@ gimple_omp_taskreg_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_child_fn_ptr (gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->child_fn;
 }
 
 
@@ -4303,9 +4688,9 @@ gimple_omp_taskreg_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->child_fn = child_fn;
 }
 
 
@@ -4315,9 +4700,9 @@ gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_taskreg_data_arg (const_gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->data_arg;
 }
 
 
@@ -4326,9 +4711,9 @@ gimple_omp_taskreg_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_taskreg_data_arg_ptr (gimple gs)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->data_arg;
 }
 
 
@@ -4337,9 +4722,9 @@ gimple_omp_taskreg_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
 {
-  if (gimple_code (gs) != GIMPLE_OMP_PARALLEL)
-    GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->data_arg = data_arg;
 }
 
 
@@ -4348,8 +4733,9 @@ gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_task_copy_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_task.copy_fn;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->copy_fn;
 }
 
 /* Return a pointer to the copy function used to hold the body of
@@ -4358,8 +4744,9 @@ gimple_omp_task_copy_fn (const_gimple gs)
 static inline tree *
 gimple_omp_task_copy_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_task.copy_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->copy_fn;
 }
 
 
@@ -4368,8 +4755,9 @@ gimple_omp_task_copy_fn_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_copy_fn (gimple gs, tree copy_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_task.copy_fn = copy_fn;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->copy_fn = copy_fn;
 }
 
 
@@ -4378,8 +4766,9 @@ gimple_omp_task_set_copy_fn (gimple gs, tree copy_fn)
 static inline tree
 gimple_omp_task_arg_size (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_task.arg_size;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->arg_size;
 }
 
 
@@ -4388,8 +4777,9 @@ gimple_omp_task_arg_size (const_gimple gs)
 static inline tree *
 gimple_omp_task_arg_size_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_task.arg_size;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->arg_size;
 }
 
 
@@ -4398,8 +4788,9 @@ gimple_omp_task_arg_size_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_arg_size (gimple gs, tree arg_size)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_task.arg_size = arg_size;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->arg_size = arg_size;
 }
 
 
@@ -4408,8 +4799,9 @@ gimple_omp_task_set_arg_size (gimple gs, tree arg_size)
 static inline tree
 gimple_omp_task_arg_align (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return gs->gimple_omp_task.arg_align;
+  const gimple_statement_omp_task *omp_task_stmt =
+    as_a <const gimple_statement_omp_task> (gs);
+  return omp_task_stmt->arg_align;
 }
 
 
@@ -4418,8 +4810,9 @@ gimple_omp_task_arg_align (const_gimple gs)
 static inline tree *
 gimple_omp_task_arg_align_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  return &gs->gimple_omp_task.arg_align;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  return &omp_task_stmt->arg_align;
 }
 
 
@@ -4428,8 +4821,9 @@ gimple_omp_task_arg_align_ptr (gimple gs)
 static inline void
 gimple_omp_task_set_arg_align (gimple gs, tree arg_align)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TASK);
-  gs->gimple_omp_task.arg_align = arg_align;
+  gimple_statement_omp_task *omp_task_stmt =
+    as_a <gimple_statement_omp_task> (gs);
+  omp_task_stmt->arg_align = arg_align;
 }
 
 
@@ -4438,8 +4832,9 @@ gimple_omp_task_set_arg_align (gimple gs, tree arg_align)
 static inline tree
 gimple_omp_single_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SINGLE);
-  return gs->gimple_omp_single.clauses;
+  const gimple_statement_omp_single *omp_single_stmt =
+    as_a <const gimple_statement_omp_single> (gs);
+  return omp_single_stmt->clauses;
 }
 
 
@@ -4448,8 +4843,9 @@ gimple_omp_single_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_single_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SINGLE);
-  return &gs->gimple_omp_single.clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  return &omp_single_stmt->clauses;
 }
 
 
@@ -4458,8 +4854,9 @@ gimple_omp_single_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_single_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SINGLE);
-  gs->gimple_omp_single.clauses = clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  omp_single_stmt->clauses = clauses;
 }
 
 
@@ -4468,8 +4865,9 @@ gimple_omp_single_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_target_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return gs->gimple_omp_parallel.clauses;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->clauses;
 }
 
 
@@ -4478,8 +4876,9 @@ gimple_omp_target_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_target_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return &gs->gimple_omp_parallel.clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->clauses;
 }
 
 
@@ -4488,8 +4887,9 @@ gimple_omp_target_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  gs->gimple_omp_parallel.clauses = clauses;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->clauses = clauses;
 }
 
 
@@ -4509,7 +4909,7 @@ static inline void
 gimple_omp_target_set_kind (gimple g, int kind)
 {
   GIMPLE_CHECK (g, GIMPLE_OMP_TARGET);
-  g->gsbase.subcode = (g->gsbase.subcode & ~GF_OMP_TARGET_KIND_MASK)
+  g->subcode = (g->subcode & ~GF_OMP_TARGET_KIND_MASK)
 		      | (kind & GF_OMP_TARGET_KIND_MASK);
 }
 
@@ -4519,8 +4919,9 @@ gimple_omp_target_set_kind (gimple g, int kind)
 static inline tree
 gimple_omp_target_child_fn (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return gs->gimple_omp_parallel.child_fn;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->child_fn;
 }
 
 /* Return a pointer to the child function used to hold the body of
@@ -4529,8 +4930,9 @@ gimple_omp_target_child_fn (const_gimple gs)
 static inline tree *
 gimple_omp_target_child_fn_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return &gs->gimple_omp_parallel.child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->child_fn;
 }
 
 
@@ -4539,8 +4941,9 @@ gimple_omp_target_child_fn_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  gs->gimple_omp_parallel.child_fn = child_fn;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->child_fn = child_fn;
 }
 
 
@@ -4550,8 +4953,9 @@ gimple_omp_target_set_child_fn (gimple gs, tree child_fn)
 static inline tree
 gimple_omp_target_data_arg (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return gs->gimple_omp_parallel.data_arg;
+  const gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <const gimple_statement_omp_parallel> (gs);
+  return omp_parallel_stmt->data_arg;
 }
 
 
@@ -4560,8 +4964,9 @@ gimple_omp_target_data_arg (const_gimple gs)
 static inline tree *
 gimple_omp_target_data_arg_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  return &gs->gimple_omp_parallel.data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  return &omp_parallel_stmt->data_arg;
 }
 
 
@@ -4570,8 +4975,9 @@ gimple_omp_target_data_arg_ptr (gimple gs)
 static inline void
 gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TARGET);
-  gs->gimple_omp_parallel.data_arg = data_arg;
+  gimple_statement_omp_parallel *omp_parallel_stmt =
+    as_a <gimple_statement_omp_parallel> (gs);
+  omp_parallel_stmt->data_arg = data_arg;
 }
 
 
@@ -4580,8 +4986,9 @@ gimple_omp_target_set_data_arg (gimple gs, tree data_arg)
 static inline tree
 gimple_omp_teams_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
-  return gs->gimple_omp_single.clauses;
+  const gimple_statement_omp_single *omp_single_stmt =
+    as_a <const gimple_statement_omp_single> (gs);
+  return omp_single_stmt->clauses;
 }
 
 
@@ -4590,8 +4997,9 @@ gimple_omp_teams_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_teams_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
-  return &gs->gimple_omp_single.clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  return &omp_single_stmt->clauses;
 }
 
 
@@ -4600,8 +5008,9 @@ gimple_omp_teams_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_teams_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_TEAMS);
-  gs->gimple_omp_single.clauses = clauses;
+  gimple_statement_omp_single *omp_single_stmt =
+    as_a <gimple_statement_omp_single> (gs);
+  omp_single_stmt->clauses = clauses;
 }
 
 
@@ -4610,8 +5019,9 @@ gimple_omp_teams_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_sections_clauses (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return gs->gimple_omp_sections.clauses;
+  const gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <const gimple_statement_omp_sections> (gs);
+  return omp_sections_stmt->clauses;
 }
 
 
@@ -4620,8 +5030,9 @@ gimple_omp_sections_clauses (const_gimple gs)
 static inline tree *
 gimple_omp_sections_clauses_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return &gs->gimple_omp_sections.clauses;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  return &omp_sections_stmt->clauses;
 }
 
 
@@ -4631,8 +5042,9 @@ gimple_omp_sections_clauses_ptr (gimple gs)
 static inline void
 gimple_omp_sections_set_clauses (gimple gs, tree clauses)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  gs->gimple_omp_sections.clauses = clauses;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  omp_sections_stmt->clauses = clauses;
 }
 
 
@@ -4642,8 +5054,9 @@ gimple_omp_sections_set_clauses (gimple gs, tree clauses)
 static inline tree
 gimple_omp_sections_control (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return gs->gimple_omp_sections.control;
+  const gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <const gimple_statement_omp_sections> (gs);
+  return omp_sections_stmt->control;
 }
 
 
@@ -4653,8 +5066,9 @@ gimple_omp_sections_control (const_gimple gs)
 static inline tree *
 gimple_omp_sections_control_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  return &gs->gimple_omp_sections.control;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  return &omp_sections_stmt->control;
 }
 
 
@@ -4664,8 +5078,9 @@ gimple_omp_sections_control_ptr (gimple gs)
 static inline void
 gimple_omp_sections_set_control (gimple gs, tree control)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_SECTIONS);
-  gs->gimple_omp_sections.control = control;
+  gimple_statement_omp_sections *omp_sections_stmt =
+    as_a <gimple_statement_omp_sections> (gs);
+  omp_sections_stmt->control = control;
 }
 
 
@@ -4674,10 +5089,11 @@ gimple_omp_sections_set_control (gimple gs, tree control)
 static inline void
 gimple_omp_for_set_cond (gimple gs, size_t i, enum tree_code cond)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
+  gimple_statement_omp_for *omp_for_stmt =
+    as_a <gimple_statement_omp_for> (gs);
   gcc_gimple_checking_assert (TREE_CODE_CLASS (cond) == tcc_comparison
-			      && i < gs->gimple_omp_for.collapse);
-  gs->gimple_omp_for.iter[i].cond = cond;
+			      && i < omp_for_stmt->collapse);
+  omp_for_stmt->iter[i].cond = cond;
 }
 
 
@@ -4686,9 +5102,10 @@ gimple_omp_for_set_cond (gimple gs, size_t i, enum tree_code cond)
 static inline enum tree_code
 gimple_omp_for_cond (const_gimple gs, size_t i)
 {
-  GIMPLE_CHECK (gs, GIMPLE_OMP_FOR);
-  gcc_gimple_checking_assert (i < gs->gimple_omp_for.collapse);
-  return gs->gimple_omp_for.iter[i].cond;
+  const gimple_statement_omp_for *omp_for_stmt =
+    as_a <const gimple_statement_omp_for> (gs);
+  gcc_gimple_checking_assert (i < omp_for_stmt->collapse);
+  return omp_for_stmt->iter[i].cond;
 }
 
 
@@ -4697,8 +5114,9 @@ gimple_omp_for_cond (const_gimple gs, size_t i)
 static inline void
 gimple_omp_atomic_store_set_val (gimple g, tree val)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  g->gimple_omp_atomic_store.val = val;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  omp_atomic_store_stmt->val = val;
 }
 
 
@@ -4707,8 +5125,9 @@ gimple_omp_atomic_store_set_val (gimple g, tree val)
 static inline tree
 gimple_omp_atomic_store_val (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  return g->gimple_omp_atomic_store.val;
+  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;
 }
 
 
@@ -4717,8 +5136,9 @@ gimple_omp_atomic_store_val (const_gimple g)
 static inline tree *
 gimple_omp_atomic_store_val_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_STORE);
-  return &g->gimple_omp_atomic_store.val;
+  gimple_statement_omp_atomic_store *omp_atomic_store_stmt =
+    as_a <gimple_statement_omp_atomic_store> (g);
+  return &omp_atomic_store_stmt->val;
 }
 
 
@@ -4727,8 +5147,9 @@ gimple_omp_atomic_store_val_ptr (gimple g)
 static inline void
 gimple_omp_atomic_load_set_lhs (gimple g, tree lhs)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  g->gimple_omp_atomic_load.lhs = lhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  omp_atomic_load_stmt->lhs = lhs;
 }
 
 
@@ -4737,8 +5158,9 @@ gimple_omp_atomic_load_set_lhs (gimple g, tree lhs)
 static inline tree
 gimple_omp_atomic_load_lhs (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return g->gimple_omp_atomic_load.lhs;
+  const gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <const gimple_statement_omp_atomic_load> (g);
+  return omp_atomic_load_stmt->lhs;
 }
 
 
@@ -4747,8 +5169,9 @@ gimple_omp_atomic_load_lhs (const_gimple g)
 static inline tree *
 gimple_omp_atomic_load_lhs_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return &g->gimple_omp_atomic_load.lhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  return &omp_atomic_load_stmt->lhs;
 }
 
 
@@ -4757,8 +5180,9 @@ gimple_omp_atomic_load_lhs_ptr (gimple g)
 static inline void
 gimple_omp_atomic_load_set_rhs (gimple g, tree rhs)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  g->gimple_omp_atomic_load.rhs = rhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  omp_atomic_load_stmt->rhs = rhs;
 }
 
 
@@ -4767,8 +5191,9 @@ gimple_omp_atomic_load_set_rhs (gimple g, tree rhs)
 static inline tree
 gimple_omp_atomic_load_rhs (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return g->gimple_omp_atomic_load.rhs;
+  const gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <const gimple_statement_omp_atomic_load> (g);
+  return omp_atomic_load_stmt->rhs;
 }
 
 
@@ -4777,8 +5202,9 @@ gimple_omp_atomic_load_rhs (const_gimple g)
 static inline tree *
 gimple_omp_atomic_load_rhs_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_ATOMIC_LOAD);
-  return &g->gimple_omp_atomic_load.rhs;
+  gimple_statement_omp_atomic_load *omp_atomic_load_stmt =
+    as_a <gimple_statement_omp_atomic_load> (g);
+  return &omp_atomic_load_stmt->rhs;
 }
 
 
@@ -4787,8 +5213,9 @@ gimple_omp_atomic_load_rhs_ptr (gimple g)
 static inline tree
 gimple_omp_continue_control_def (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return g->gimple_omp_continue.control_def;
+  const gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <const gimple_statement_omp_continue> (g);
+  return omp_continue_stmt->control_def;
 }
 
 /* The same as above, but return the address.  */
@@ -4796,8 +5223,9 @@ gimple_omp_continue_control_def (const_gimple g)
 static inline tree *
 gimple_omp_continue_control_def_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return &g->gimple_omp_continue.control_def;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  return &omp_continue_stmt->control_def;
 }
 
 /* Set the definition of the control variable in a GIMPLE_OMP_CONTINUE.  */
@@ -4805,8 +5233,9 @@ gimple_omp_continue_control_def_ptr (gimple g)
 static inline void
 gimple_omp_continue_set_control_def (gimple g, tree def)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  g->gimple_omp_continue.control_def = def;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  omp_continue_stmt->control_def = def;
 }
 
 
@@ -4815,8 +5244,9 @@ gimple_omp_continue_set_control_def (gimple g, tree def)
 static inline tree
 gimple_omp_continue_control_use (const_gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return g->gimple_omp_continue.control_use;
+  const gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <const gimple_statement_omp_continue> (g);
+  return omp_continue_stmt->control_use;
 }
 
 
@@ -4825,8 +5255,9 @@ gimple_omp_continue_control_use (const_gimple g)
 static inline tree *
 gimple_omp_continue_control_use_ptr (gimple g)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  return &g->gimple_omp_continue.control_use;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  return &omp_continue_stmt->control_use;
 }
 
 
@@ -4835,8 +5266,9 @@ gimple_omp_continue_control_use_ptr (gimple g)
 static inline void
 gimple_omp_continue_set_control_use (gimple g, tree use)
 {
-  GIMPLE_CHECK (g, GIMPLE_OMP_CONTINUE);
-  g->gimple_omp_continue.control_use = use;
+  gimple_statement_omp_continue *omp_continue_stmt =
+    as_a <gimple_statement_omp_continue> (g);
+  omp_continue_stmt->control_use = use;
 }
 
 /* Return a pointer to the body for the GIMPLE_TRANSACTION statement GS.  */
@@ -4844,8 +5276,9 @@ gimple_omp_continue_set_control_use (gimple g, tree use)
 static inline gimple_seq *
 gimple_transaction_body_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return &gs->gimple_transaction.body;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  return &transaction_stmt->body;
 }
 
 /* Return the body for the GIMPLE_TRANSACTION statement GS.  */
@@ -4861,15 +5294,17 @@ gimple_transaction_body (gimple gs)
 static inline tree
 gimple_transaction_label (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return gs->gimple_transaction.label;
+  const gimple_statement_transaction *transaction_stmt =
+    as_a <const gimple_statement_transaction> (gs);
+  return transaction_stmt->label;
 }
 
 static inline tree *
 gimple_transaction_label_ptr (gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return &gs->gimple_transaction.label;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  return &transaction_stmt->label;
 }
 
 /* Return the subcode associated with a GIMPLE_TRANSACTION.  */
@@ -4878,7 +5313,7 @@ static inline unsigned int
 gimple_transaction_subcode (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return gs->gsbase.subcode;
+  return gs->subcode;
 }
 
 /* Set BODY to be the body for the GIMPLE_TRANSACTION statement GS.  */
@@ -4886,8 +5321,9 @@ gimple_transaction_subcode (const_gimple gs)
 static inline void
 gimple_transaction_set_body (gimple gs, gimple_seq body)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  gs->gimple_transaction.body = body;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  transaction_stmt->body = body;
 }
 
 /* Set the label associated with a GIMPLE_TRANSACTION.  */
@@ -4895,8 +5331,9 @@ gimple_transaction_set_body (gimple gs, gimple_seq body)
 static inline void
 gimple_transaction_set_label (gimple gs, tree label)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  gs->gimple_transaction.label = label;
+  gimple_statement_transaction *transaction_stmt =
+    as_a <gimple_statement_transaction> (gs);
+  transaction_stmt->label = label;
 }
 
 /* Set the subcode associated with a GIMPLE_TRANSACTION.  */
@@ -4905,7 +5342,7 @@ static inline void
 gimple_transaction_set_subcode (gimple gs, unsigned int subcode)
 {
   GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  gs->gsbase.subcode = subcode;
+  gs->subcode = subcode;
 }
 
 
@@ -5015,7 +5452,7 @@ static inline enum br_predictor
 gimple_predict_predictor (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
-  return (enum br_predictor) (gs->gsbase.subcode & ~GF_PREDICT_TAKEN);
+  return (enum br_predictor) (gs->subcode & ~GF_PREDICT_TAKEN);
 }
 
 
@@ -5025,7 +5462,7 @@ static inline void
 gimple_predict_set_predictor (gimple gs, enum br_predictor predictor)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
-  gs->gsbase.subcode = (gs->gsbase.subcode & GF_PREDICT_TAKEN)
+  gs->subcode = (gs->subcode & GF_PREDICT_TAKEN)
 		       | (unsigned) predictor;
 }
 
@@ -5036,7 +5473,7 @@ static inline enum prediction
 gimple_predict_outcome (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
-  return (gs->gsbase.subcode & GF_PREDICT_TAKEN) ? TAKEN : NOT_TAKEN;
+  return (gs->subcode & GF_PREDICT_TAKEN) ? TAKEN : NOT_TAKEN;
 }
 
 
@@ -5047,9 +5484,9 @@ gimple_predict_set_outcome (gimple gs, enum prediction outcome)
 {
   GIMPLE_CHECK (gs, GIMPLE_PREDICT);
   if (outcome == TAKEN)
-    gs->gsbase.subcode |= GF_PREDICT_TAKEN;
+    gs->subcode |= GF_PREDICT_TAKEN;
   else
-    gs->gsbase.subcode &= ~GF_PREDICT_TAKEN;
+    gs->subcode &= ~GF_PREDICT_TAKEN;
 }
 
 
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index caecbf2..9e52d1a 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2631,7 +2631,7 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
 		    && TREE_CODE ((**debug_args)[i + 1]) == DEBUG_EXPR_DECL)
 		  {
 		    t = (**debug_args)[i + 1];
-		    stmt->gsbase.subcode = GIMPLE_DEBUG_BIND;
+		    stmt->subcode = GIMPLE_DEBUG_BIND;
 		    gimple_debug_bind_set_value (stmt, t);
 		    break;
 		  }
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index da7bf5b..417d5b5 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -184,7 +184,7 @@ make_phi_node (tree var, int len)
   memset (phi, 0, (sizeof (struct gimple_statement_phi)
 		   - sizeof (struct phi_arg_d)
 		   + sizeof (struct phi_arg_d) * len));
-  phi->gsbase.code = GIMPLE_PHI;
+  phi->code = GIMPLE_PHI;
   gimple_init_singleton (phi);
   phi->gimple_phi.nargs = len;
   phi->gimple_phi.capacity = capacity;
-- 
1.7.11.7


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

* Re: [PATCH 1/6] Convert gimple types from a union to C++ inheritance
  2013-11-14 23:00     ` Jeff Law
@ 2013-11-19  0:22       ` David Malcolm
  2013-11-19  8:49         ` Jeff Law
  0 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2013-11-19  0:22 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Andrew MacLeod

On Thu, 2013-11-14 at 14:51 -0700, Jeff Law wrote:
> On 10/31/13 10:26, David Malcolm wrote:
> > 	* Makefile.in (GIMPLE_H): Add dep on is-a.h.
> Not asking you, but I'd like to hope many of the *_H things in 
> Makefile.in should be going away...
> 
> 
> 
> >
> > diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> > index cc88fb8..7fbb533 100644
> > --- a/gcc/Makefile.in
> > +++ b/gcc/Makefile.in
> > @@ -887,7 +887,7 @@ BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) \
> >   	cfg-flags.def cfghooks.h
> >   GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
> >   	$(GGC_H) $(BASIC_BLOCK_H) $(TREE_H) tree-ssa-operands.h \
> > -	tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H)
> > +	tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H) is-a.h
> >   GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
> >   RECOG_H = recog.h
> >   EMIT_RTL_H = emit-rtl.h
> Ugh.  OK I guess.  I hate all these _H thingies.  Ideally they'll go 
> away at some point.  I think their biggest use now is for 
> PLUGIN_HEADERS.  But that's not an issue for this patch to go forward.
> 
> 
> 
> > diff --git a/gcc/ggc.h b/gcc/ggc.h
> > index b31bc80..bb8f939 100644
> > --- a/gcc/ggc.h
> > +++ b/gcc/ggc.h
> > @@ -269,10 +269,10 @@ ggc_alloc_cleared_tree_node_stat (size_t s MEM_STAT_DECL)
> >     return (union tree_node *) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
> >   }
> >
> > -static inline union gimple_statement_d *
> > -ggc_alloc_cleared_gimple_statement_d_stat (size_t s MEM_STAT_DECL)
> > +static inline struct gimple_statement_base *
> > +ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL)
> >   {
> > -  return (union gimple_statement_d *)
> > +  return (struct gimple_statement_base *)
> >       ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
> >   }
> Didn't I see something in the last 48hrs indicating that we don't need 
> "static inline" anymore, just "inline"?  If so, can you drop the static 
> here since you're changing it already.
I looked, but I'm not sure which change you're referring to; sorry.

Note that all 7 of the inline functions in ggc.h are "static inline",
not just this one; it feels like a separate change to be touching the
"static"ness of them IMHO.

> With that, this, IMO is OK and a definite step forward.
> 
> Given the contention over this, please give other maintainers 24hrs to 
> object before installing the set.

Thanks.  It's now been a few days.  Patch 3 (the autogenerated one) has
bitrotted somewhat due to the reorganization of gimple.h, so I'm
rebootstrapping an updated version of it now; I've posted it for review
as http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02156.html


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

* Re: [PATCH 5/6] Port various places from union access to subclass access.
  2013-11-14  9:23     ` Jeff Law
@ 2013-11-19  0:52       ` David Malcolm
  0 siblings, 0 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-19  0:52 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Andrew MacLeod

On Thu, 2013-11-14 at 00:34 -0700, Jeff Law wrote:
> On 10/31/13 10:26, David Malcolm wrote:

[...]

> > diff --git a/gcc/gimple.c b/gcc/gimple.c
> > index 9b1337a..e9ef8e0 100644
> > --- a/gcc/gimple.c
> > +++ b/gcc/gimple.c
> > @@ -641,21 +641,22 @@ static inline gimple
> >   gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
> >                       unsigned nclobbers, unsigned nlabels)
> >   {
> > -  gimple p;
> > +  gimple_statement_asm *p;
> >     int size = strlen (string);
> >
> >     /* ASMs with labels cannot have outputs.  This should have been
> >        enforced by the front end.  */
> >     gcc_assert (nlabels == 0 || noutputs == 0);
> >
> > -  p = gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
> > -			     ninputs + noutputs + nclobbers + nlabels);
> > +  p = as_a <gimple_statement_asm> (
> > +        gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
> > +			       ninputs + noutputs + nclobbers + nlabels));
> >
> > -  p->gimple_asm.ni = ninputs;
> > -  p->gimple_asm.no = noutputs;
> > -  p->gimple_asm.nc = nclobbers;
> > -  p->gimple_asm.nl = nlabels;
> > -  p->gimple_asm.string = ggc_alloc_string (string, size);
> > +  p->ni = ninputs;
> > +  p->no = noutputs;
> > +  p->nc = nclobbers;
> > +  p->nl = nlabels;
> > +  p->string = ggc_alloc_string (string, size);
> As noted in a prior message, having build methods would eliminate this 
> downcasting.  Not necessary for this patch, just wanted to point it out 
> to anyone reading.  I won't point it out everywhere ;-)

This one (gimple_build_asm_1) is itself a build method.  The checking on
the downcast could be argued to be redundant, since presumably we trust
gimple_build_with_ops to give us a stmt with the code we asked for, but
I don't think it hurts.

> So given the prior disussions around as_a, I'm not going to object to 
> these as_a instances.  I see them as warts/markers that we have further 
> work to do in terms of fleshing out the class and possibly refactoring 
> code.
> 
> Conditionally OK.  Conditional on the other related patches going in and 
> keeping it updated with Andrew's churn.  If/when the set goes in, post 
> the final version you actually checkin -- no re-review is needed for 
> this hunk so long as any changes are the obvious fixing of fallout from 
> Andrew's work.

Thanks.

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

* Re: [PATCH 1/6] Convert gimple types from a union to C++ inheritance
  2013-11-19  0:22       ` David Malcolm
@ 2013-11-19  8:49         ` Jeff Law
  0 siblings, 0 replies; 116+ messages in thread
From: Jeff Law @ 2013-11-19  8:49 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Andrew MacLeod

On 11/18/13 14:00, David Malcolm wrote:
>>> @@ -269,10 +269,10 @@ ggc_alloc_cleared_tree_node_stat (size_t s MEM_STAT_DECL)
>>>      return (union tree_node *) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
>>>    }
>>>
>>> -static inline union gimple_statement_d *
>>> -ggc_alloc_cleared_gimple_statement_d_stat (size_t s MEM_STAT_DECL)
>>> +static inline struct gimple_statement_base *
>>> +ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL)
>>>    {
>>> -  return (union gimple_statement_d *)
>>> +  return (struct gimple_statement_base *)
>>>        ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
>>>    }
>> Didn't I see something in the last 48hrs indicating that we don't need
>> "static inline" anymore, just "inline"?  If so, can you drop the static
>> here since you're changing it already.
> I looked, but I'm not sure which change you're referring to; sorry.
>
> Note that all 7 of the inline functions in ggc.h are "static inline",
> not just this one; it feels like a separate change to be touching the
> "static"ness of them IMHO.
Don't stress about it.  If I find the reference, I'll pass it along 
and/or just fix them myself :-)

>
> Thanks.  It's now been a few days.  Patch 3 (the autogenerated one) has
> bitrotted somewhat due to the reorganization of gimple.h, so I'm
> rebootstrapping an updated version of it now; I've posted it for review
> as http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02156.html
I'll give it another look shortly.

jeff

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

* Re: [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-18 22:17       ` [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance) David Malcolm
@ 2013-11-19  8:49         ` Jeff Law
  2013-11-19 16:36           ` David Malcolm
  2013-11-22  0:27         ` Jakub Jelinek
  1 sibling, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-19  8:49 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches, Andrew MacLeod

On 11/18/13 13:25, David Malcolm wrote:
>
> I regenerated it and am bootstrapping now.  I glanced over it and
> nothing major seems to have changed; just changes due to the movement of
> code between files.   Am attaching the changed patch.
Yea, there's a lot of churn right now, so this is kind-of expected.

Thanks for re-posting and verifying it's good to go.  Never hurts to be 
careful.

>
> I think so, yes, though you'll have to cast it to the appropriate
> subclass by hand; rather than the status quo of getting multiple
> screenfuls of text, you'll just get the gimple_statement_base fields:
Right.  It's parsing the pages of text that I find to be a totally 
pointless waste of time.  It's gotten worse, mostly because I was away 
for too long and I don't have the accessors in muscle-memory.

WRT elimination of the GIMPLE_CHECKs, understood on the state of things 
and why the script didn't eliminate them in the various places I pointed 
out.

This is fine.  Please install.

Thanks,
jeff

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

* Re: [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-19  8:49         ` Jeff Law
@ 2013-11-19 16:36           ` David Malcolm
  0 siblings, 0 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-19 16:36 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Andrew MacLeod

On Mon, 2013-11-18 at 22:13 -0700, Jeff Law wrote:
> On 11/18/13 13:25, David Malcolm wrote:
> >
> > I regenerated it and am bootstrapping now.  I glanced over it and
> > nothing major seems to have changed; just changes due to the movement of
> > code between files.   Am attaching the changed patch.
> Yea, there's a lot of churn right now, so this is kind-of expected.
> 
> Thanks for re-posting and verifying it's good to go.  Never hurts to be 
> careful.
> 
> >
> > I think so, yes, though you'll have to cast it to the appropriate
> > subclass by hand; rather than the status quo of getting multiple
> > screenfuls of text, you'll just get the gimple_statement_base fields:
> Right.  It's parsing the pages of text that I find to be a totally 
> pointless waste of time.  It's gotten worse, mostly because I was away 
> for too long and I don't have the accessors in muscle-memory.
> 
> WRT elimination of the GIMPLE_CHECKs, understood on the state of things 
> and why the script didn't eliminate them in the various places I pointed 
> out.
> 
> This is fine.  Please install.

Thanks; I've committed the combined patch series to trunk as r205034.


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

* Re: [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-18 22:17       ` [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance) David Malcolm
  2013-11-19  8:49         ` Jeff Law
@ 2013-11-22  0:27         ` Jakub Jelinek
  2013-11-22  0:35           ` Jeff Law
  1 sibling, 1 reply; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-22  0:27 UTC (permalink / raw)
  To: David Malcolm; +Cc: Jeff Law, gcc-patches, Andrew MacLeod

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.

	Jakub

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

* Re: [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-22  0:27         ` Jakub Jelinek
@ 2013-11-22  0:35           ` Jeff Law
  2013-11-22  1:51             ` Jakub Jelinek
  0 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-22  0:35 UTC (permalink / raw)
  To: Jakub Jelinek, David Malcolm; +Cc: gcc-patches, Andrew MacLeod

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?

jeff

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

* Re: [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-22  0:35           ` Jeff Law
@ 2013-11-22  1:51             ` Jakub Jelinek
  2013-11-22  2:52               ` Andrew MacLeod
  0 siblings, 1 reply; 116+ messages in thread
From: Jakub Jelinek @ 2013-11-22  1:51 UTC (permalink / raw)
  To: Jeff Law; +Cc: David Malcolm, gcc-patches, Andrew MacLeod

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

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

* Re: [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-22  1:51             ` Jakub Jelinek
@ 2013-11-22  2:52               ` Andrew MacLeod
  2013-11-22  3:48                 ` David Malcolm
  2013-11-25 18:09                 ` [PATCH] Fix checking of gimple types David Malcolm
  0 siblings, 2 replies; 116+ messages in thread
From: Andrew MacLeod @ 2013-11-22  2:52 UTC (permalink / raw)
  To: Jakub Jelinek, Jeff Law; +Cc: David Malcolm, gcc-patches

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.

Andrew

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

* Re: [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance)
  2013-11-22  2:52               ` Andrew MacLeod
@ 2013-11-22  3:48                 ` David Malcolm
  2013-11-25 18:09                 ` [PATCH] Fix checking of gimple types David Malcolm
  1 sibling, 0 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-22  3:48 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Jakub Jelinek, Jeff Law, gcc-patches

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.

This was a bug in my script.  Sorry.  Working on a fix.

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

* [PATCH] Fix checking of gimple types
  2013-11-22  2:52               ` Andrew MacLeod
  2013-11-22  3:48                 ` David Malcolm
@ 2013-11-25 18:09                 ` David Malcolm
  2013-11-25 18:42                   ` Michael Matz
                                     ` (2 more replies)
  1 sibling, 3 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-25 18:09 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Jakub Jelinek, Jeff Law, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 9252 bytes --]

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



[-- Attachment #2: fix-gimple-checking.patch --]
[-- Type: text/x-patch, Size: 36141 bytes --]

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)

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

* Re: [PATCH] Fix checking of gimple types
  2013-11-25 18:09                 ` [PATCH] Fix checking of gimple types David Malcolm
@ 2013-11-25 18:42                   ` Michael Matz
  2013-11-25 22:18                   ` Jeff Law
  2014-07-23 13:16                   ` Thomas Schwinge
  2 siblings, 0 replies; 116+ messages in thread
From: Michael Matz @ 2013-11-25 18:42 UTC (permalink / raw)
  To: David Malcolm; +Cc: Andrew MacLeod, Jakub Jelinek, Jeff Law, gcc-patches

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.

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

* Re: [PATCH] Fix checking of gimple types
  2013-11-25 18:09                 ` [PATCH] Fix checking of gimple types David Malcolm
  2013-11-25 18:42                   ` Michael Matz
@ 2013-11-25 22:18                   ` Jeff Law
  2013-11-27  8:54                     ` David Malcolm
  2014-07-23 13:16                   ` Thomas Schwinge
  2 siblings, 1 reply; 116+ messages in thread
From: Jeff Law @ 2013-11-25 22:18 UTC (permalink / raw)
  To: David Malcolm, Andrew MacLeod; +Cc: Jakub Jelinek, gcc-patches

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

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

* Re: [PATCH] Fix checking of gimple types
  2013-11-25 22:18                   ` Jeff Law
@ 2013-11-27  8:54                     ` David Malcolm
  0 siblings, 0 replies; 116+ messages in thread
From: David Malcolm @ 2013-11-27  8:54 UTC (permalink / raw)
  To: Jeff Law; +Cc: Andrew MacLeod, Jakub Jelinek, gcc-patches

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.

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

* Re: [PATCH] Fix checking of gimple types
  2013-11-25 18:09                 ` [PATCH] Fix checking of gimple types David Malcolm
  2013-11-25 18:42                   ` Michael Matz
  2013-11-25 22:18                   ` Jeff Law
@ 2014-07-23 13:16                   ` Thomas Schwinge
  2014-07-24  1:50                     ` David Malcolm
  2 siblings, 1 reply; 116+ messages in thread
From: Thomas Schwinge @ 2014-07-23 13:16 UTC (permalink / raw)
  To: David Malcolm, Andrew MacLeod; +Cc: Jakub Jelinek, Jeff Law, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 53150 bytes --]

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

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

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

* Re: [PATCH] Fix checking of gimple types
  2014-07-23 13:16                   ` Thomas Schwinge
@ 2014-07-24  1:50                     ` David Malcolm
  2014-07-29  8:11                       ` Thomas Schwinge
  0 siblings, 1 reply; 116+ messages in thread
From: David Malcolm @ 2014-07-24  1:50 UTC (permalink / raw)
  To: Thomas Schwinge; +Cc: Andrew MacLeod, Jakub Jelinek, Jeff Law, gcc-patches

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


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

* Re: [PATCH] Fix checking of gimple types
  2014-07-24  1:50                     ` David Malcolm
@ 2014-07-29  8:11                       ` Thomas Schwinge
  0 siblings, 0 replies; 116+ messages in thread
From: Thomas Schwinge @ 2014-07-29  8:11 UTC (permalink / raw)
  To: David Malcolm
  Cc: Andrew MacLeod, Jakub Jelinek, Jeff Law, gcc-patches, Cesar Philippidis

[-- Attachment #1: Type: text/plain, Size: 63305 bytes --]

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

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

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

end of thread, other threads:[~2014-07-29  8:07 UTC | newest]

Thread overview: 116+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-31  5:45 RFC: gimple.[ch] break apart Andrew MacLeod
2013-10-31  6:15 ` Jeff Law
2013-10-31 16:41 ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) David Malcolm
2013-10-31 16:27   ` [PATCH 4/6] Implement is_a_helper <>::test specializations for various gimple types David Malcolm
2013-11-14  9:41     ` Jeff Law
2013-11-18 19:51       ` David Malcolm
2013-11-18 20:10         ` Andrew MacLeod
2013-11-18 20:15         ` Jeff Law
2013-10-31 16:27   ` [PATCH 1/6] Convert gimple types from a union to C++ inheritance David Malcolm
2013-11-14 23:00     ` Jeff Law
2013-11-19  0:22       ` David Malcolm
2013-11-19  8:49         ` Jeff Law
2013-10-31 16:27   ` [PATCH 2/6] Hand-written port of various accessors within gimple.h David Malcolm
2013-11-14  9:53     ` Jeff Law
2013-10-31 16:31   ` [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance David Malcolm
2013-11-14  9:43     ` Jeff Law
2013-11-18 22:17       ` [PATCH] Updated automated patch (was Re: [PATCH 3/6] Automated part of conversion of gimple types to use C++ inheritance) David Malcolm
2013-11-19  8:49         ` Jeff Law
2013-11-19 16:36           ` David Malcolm
2013-11-22  0:27         ` Jakub Jelinek
2013-11-22  0:35           ` Jeff Law
2013-11-22  1:51             ` Jakub Jelinek
2013-11-22  2:52               ` Andrew MacLeod
2013-11-22  3:48                 ` David Malcolm
2013-11-25 18:09                 ` [PATCH] Fix checking of gimple types David Malcolm
2013-11-25 18:42                   ` Michael Matz
2013-11-25 22:18                   ` Jeff Law
2013-11-27  8:54                     ` David Malcolm
2014-07-23 13:16                   ` Thomas Schwinge
2014-07-24  1:50                     ` David Malcolm
2014-07-29  8:11                       ` Thomas Schwinge
2013-10-31 16:46   ` [PATCH 6/6] Update gdb hooks to reflect changes to " David Malcolm
2013-11-14  9:10     ` Jeff Law
2013-10-31 16:49   ` [PATCH 5/6] Port various places from union access to subclass access David Malcolm
2013-11-14  9:23     ` Jeff Law
2013-11-19  0:52       ` David Malcolm
2013-10-31 18:43   ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) Basile Starynkevitch
2013-11-01 21:36   ` Andrew MacLeod
2013-11-01 21:41     ` Jakub Jelinek
2013-11-01 21:47       ` Andrew MacLeod
2013-11-01 21:57         ` Jakub Jelinek
2013-11-01 22:58           ` David Malcolm
2013-11-04 13:23             ` Andrew MacLeod
2013-11-04 21:52               ` David Malcolm
2013-11-04 22:09                 ` David Malcolm
2013-11-04 22:31                   ` Andrew MacLeod
2013-11-05 21:27                     ` Jeff Law
2013-11-04 22:43                   ` Andrew MacLeod
2013-11-04 22:28                 ` Jakub Jelinek
2013-11-04 22:49                   ` Andrew MacLeod
2013-11-05 21:09                   ` Jeff Law
2013-11-05 11:53                 ` Richard Biener
2013-11-05 12:33                   ` David Malcolm
2013-11-05 12:52                     ` Richard Biener
2013-11-04 14:00           ` Andrew MacLeod
2013-11-04 14:01             ` Jakub Jelinek
2013-11-04 14:15               ` Andrew MacLeod
2013-11-04 18:23       ` Jeff Law
2013-11-01 22:43     ` David Malcolm
2013-11-01 23:43       ` Trevor Saunders
2013-11-04 13:15       ` Andrew MacLeod
2013-11-05 17:23     ` [PATCH] Add gimple subclasses for every gimple code (was Re: [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3)) David Malcolm
2013-11-06 16:53       ` Michael Matz
2013-11-07  6:19         ` David Malcolm
2013-11-07  7:08           ` Jeff Law
2013-11-08 19:23             ` David Malcolm
2013-11-14  8:38               ` Jeff Law
2013-11-14 15:06                 ` Michael Matz
2013-11-14 18:32                 ` David Malcolm
2013-11-15  2:49                   ` Jeff Law
2013-11-07 14:57           ` Michael Matz
2013-11-08  0:07         ` Alec Teal
2013-11-08 14:31           ` Michael Matz
2013-11-05 18:22     ` [PATCH 0/6] Conversion of gimple types to C++ inheritance (v3) Andrew MacLeod
2013-11-05 21:33   ` Jeff Law
2013-11-05 22:01     ` David Malcolm
2013-11-05 22:17       ` Jeff Law
2013-11-06  1:14         ` Ian Lance Taylor
2013-11-06 20:49           ` Jeff Law
2013-11-06 20:57             ` Trevor Saunders
2013-11-05 22:24       ` Andrew MacLeod
2013-11-05 22:12     ` Andrew MacLeod
2013-11-06  9:37     ` Richard Biener
2013-11-06 11:20       ` Bernd Schmidt
2013-11-06 11:43         ` Richard Biener
2013-11-06 11:53           ` Jakub Jelinek
2013-11-06 13:14             ` Richard Biener
2013-11-06 13:23               ` Jakub Jelinek
2013-11-06 16:42                 ` David Malcolm
2013-11-06 16:55                   ` Jakub Jelinek
2013-11-06 18:34                     ` Tom Tromey
2013-11-06 19:15                       ` Jeff Law
2013-11-06 20:05                         ` Tom Tromey
2013-11-06 20:45                           ` Jeff Law
2013-11-06 13:31             ` Joseph S. Myers
2013-11-06 21:25               ` Jeff Law
2013-11-06 21:09             ` Jeff Law
2013-11-06 12:42           ` Bernd Schmidt
2013-11-06 21:04           ` Jeff Law
2013-11-06 21:06           ` Andrew MacLeod
2013-11-06 21:52             ` Jeff Law
2013-11-07 10:29             ` Richard Biener
2013-11-07 14:01               ` Joseph S. Myers
2013-11-07 14:42                 ` Richard Biener
2013-11-07 14:53               ` Andrew MacLeod
2013-11-10 12:35             ` Richard Sandiford
2013-11-10 15:27               ` Richard Biener
2013-11-06 11:56         ` Eric Botcazou
2013-11-06 20:51         ` Jeff Law
2013-11-06 21:26       ` Jeff Law
2013-11-14  8:40   ` Jeff Law
2013-11-05 16:58 ` [patch] Create gimple-expr..[ch] ... was Re: RFC: gimple.[ch] break apart Andrew MacLeod
2013-11-05 17:52   ` Jeff Law
2013-11-07 10:58   ` Basile Starynkevitch
2013-11-07 13:47     ` Andrew MacLeod
2013-11-07 18:13       ` Diego Novillo

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