Patchwork [1/6] Convert gimple types from a union to C++ inheritance

login
register
mail settings
Submitter David Malcolm
Date Oct. 31, 2013, 4:26 p.m.
Message ID <1383236801-13234-2-git-send-email-dmalcolm@redhat.com>
Download mbox | patch
Permalink /patch/287553/
State New
Headers show

Comments

David Malcolm - Oct. 31, 2013, 4:26 p.m.
* 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(-)
Jeff Law - Nov. 14, 2013, 9:51 p.m.
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
David Malcolm - Nov. 18, 2013, 9 p.m.
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
Jeff Law - Nov. 19, 2013, 5:03 a.m.
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

Patch

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.  */