This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tuples] Compact tuple fields


This started as a small patch yesterday, but there are many functions
in gimple.[ch] that were affected.

I've been doing some initial tests comparing trunk vs tuples.  To make
sure that I was comparing apples-to-apples, I compared against trunk
as of the last merge (rev 135951) and disabled on my tree every pass
that is still not converted in the branch.

I tested cc1-i-files and SPEC2000.

The results are muddled because we are not yet getting rid of some of
the trees that are coming from the parser.  So, the amount of memory
allocated during gimplification has increased significantly (in the
45-50% range).  However, the total amount of allocated memory is
nearly constant or has increased a little, so that's good news.

Compile times seem to have improved consistently, though.  I got >4%
improvement in SPEC2000 and cc1-i-files.  Attached are the comparisons
of -ftime-report output (before is trunk, after is tuples).

In terms of memory savings for statements, this is what I think we
should see after we finishing tweaking and tuning the implementation.
I'll use one of the more common statement as examples (all the sizes
are for a 64-bit host):

                        a = b + c

On mainline we need: 48 bytes for GIMPLE_MODIFY_STMT, 64 bytes for
PLUS_EXPR and 96 bytes for the statement annotation.  Total = 208
bytes.  Both GIMPLE_MODIFY_STMT and PLUS_EXPR are allocated
separately.

With this patch, tuples needs: 96 bytes for GIMPLE_ASSIGN, 16 bytes
for 'b' and 'c'.  Total = 112 bytes.  Everything is allocated
together.

So, this *should* translate to memory savings.  Not huge memory
savings, mind you.  Statements are not the biggest thing we have.
There is also sequences which are not much smaller than
tree_statement_list and the rest of the memory taken by symbols,
types, SSA names, etc.  All of which we are still using.

I'm not quite sure how exactly to test for memory utilization, I
compiled with gather-detailed-mem-stats and the results are pretty
overwhelming.  I'm not quite sure what number to look at, so I'm using
the last column of -ftime-report.

Jan, what's a good way of testing this other than top?  In particular,
I would like to track down all those places were we are either still
allocating trees for no reason or doing silly things with tuples.

The patch reorganizes the tuple hierarchy to remove some obvious holes
and misalignments that were making things bigger than necessary.  This
makes the above tuple about 26% smaller than it was before.

The really big change in this patch is the unified allocation for the
tuple body and its operands.  Before, operands were allocated
separately.  Now, the operand vector is always at the end of every
tuple that uses operands.  Since different tuples will have this array
at different offsets, the offset into each operand is computed at
compile time and stored in the gimple_ops_offset_[] table.

Since every access to the operand is controlled via gimple_ops(),
there is only one place where we do the address arithmetic.  None of
this is exposed outside gimple.[ch].

I also removed some direct uses of tuples fields in files outside of
gimple.[ch].

Tested on x86_64 and ppc64.  Will commit after the ppc64 tests finish.


2008-06-06  Diego Novillo  <dnovillo@google.com>

	* gimple.def: Add a third argument to all GIMPLE codes.
	Update all users.
	* calls.c (gimple_alloca_call_p): Fix comment.
	* system.h (CONST_CAST_GIMPLE): Define.
	* gimple.c (gimple_ops_offset_): Declare.  Fill in from
	third argument in gimple.def.
	(gimple_set_stored_syms, gimple_set_loaded_syms): Move
	from tree-ssa-operands.c
	(gimple_alloc): Add argument NUM_OPS.  Update all users.
	Compute size by adding enough space for NUM_OPS operands.
	(gimple_alloc_ops): Remove.  Update all users.
	(gimple_assign_set_rhs_from_tree): Change first argument
	to gimple_stmt_iterator *.  Update all users.
	Allocate a new statement, if there are more operands that
	can fit in the old one.
	(gimple_assign_set_rhs_with_ops): Likewise.
	(gimple_copy): Fix clearing of stores/loads sets in the
	copied statement.
	* gimple.h (struct gimple_statement_base): Remove fields
	UNUSED_1, UNUSED_2, UNUSED_3.
	Add fields MODIFIED, HAS_VOLATILE_OPS, REFERENCES_MEMORY_P,
	UID and NUM_OPS.
	Re-organize existing fields to eliminate holes on 64 bit
	hosts.
	Update all users.
	(struct gimple_statement_with_ops_base): Define.
	Factor out struct gimple_statement_with_ops.  Include fields GSBASE,
	ADDRESSES_TAKEN, DEF_OPS and USE_OPS.
	(struct gimple_statement_with_ops): Include struct
	gimple_statement_with_ops_base.
	Remove field NUM_OPS.
	(struct gimple_statement_with_memory_ops_base): Define.
	Factor out of struct gimple_statement_with_memory_ops.
	Include fields OPBASE, VDEF_OPS, VUSE_OPS, STORES and
	LOADS.
	Remove fields HAS_VOLATILE_OPS and REFERENCES_MEMORY_P.
	(struct gimple_statement_with_memory_ops): Include
	struct gimple_statement_with_memory_ops_base.
	(struct gimple_statement_phi): Change size_t fields to
	unsigned.  Update all users.
	(struct gimple_statement_asm): Include struct
	gimple_statement_with_memory_ops_base.
	Change fields NI and NO to unsigned char.
	Change field NC to short.
	Update all users.
	Add field OP.
	(struct gimple_statement_change_dynamic_type): Remove.
	Update all users.
	(union gimple_statement_d): Rename field WITH_OPS to GSOPS.
	Rename field WITH_MEM_OPS to GSMEM.
	Update all users.
	(gimple_addresses_taken): New.
	(gimple_addresses_taken_ptr): New.
	(gimple_set_addresses_taken): New.
	(gimple_num_ops): Move earlier.
	(gimple_ops): Use gimple_ops_offset_ to compute address
	of the operand vector.
	(gimple_op): Call gimple_ops.
	(gimple_op_ptr): Likewise.
	(gimple_set_op): Likewise.
	(gimple_switch_num_labels): Call gimple_num_ops.
	(gimple_switch_set_num_labels): Call gimple_set_num_ops.
	(gimple_switch_set_label): Call gimple_num_ops.
	(gimple_return_retval_ptr): Likewise.
	(gimple_return_retval): Likewise.
	(gimple_set_retval): Likewise.
	(gimple_cdt_new_type): Use operand 1.
	(gimple_cdt_new_type_ptr): Likewise.
	(gimple_cdt_set_new_type): Likewise.
	* tree-cfg.c (gimple_block_ends_with_call_p): Use
	CONST_CAST_BB.
	* tree-ssa-operands.c (gimple_set_stored_syms,
	gimple_set_loaded_syms): Declare.
	* value-prof.c (gimple_divmod_fixed_value_transform,
	gimple_mod_pow2_value_transform,
	gimple_mod_subtract_transform): Change argument to
	gimple_stmt_iterator *.  Update all users.
	* tree-ssa-ccp.c (fold_gimple_assign): Change parameter
	to gimple_stmt_iterator *.  Update all users

Index: tree-complex.c
===================================================================
--- tree-complex.c	(revision 136344)
+++ tree-complex.c	(working copy)
@@ -652,15 +652,13 @@ update_complex_components_on_edge (edge
 static void
 update_complex_assignment (gimple_stmt_iterator *gsi, tree r, tree i)
 {
-  gimple stmt;
-
-  stmt = gsi_stmt (*gsi);
+  gimple_stmt_iterator orig_si = *gsi;

   if (gimple_in_ssa_p (cfun))
-    update_complex_components (gsi, stmt, r, i);
-
-  gimple_assign_set_rhs_with_ops (stmt, COMPLEX_EXPR, r, i);
-  update_stmt (stmt);
+    update_complex_components (gsi, gsi_stmt (*gsi), r, i);
+
+  gimple_assign_set_rhs_with_ops (&orig_si, COMPLEX_EXPR, r, i);
+  update_stmt (gsi_stmt (orig_si));
 }


@@ -1383,7 +1381,8 @@ expand_complex_comparison (gimple_stmt_i

     case GIMPLE_ASSIGN:
       type = TREE_TYPE (gimple_assign_lhs (stmt));
-      gimple_assign_set_rhs_from_tree (stmt, fold_convert (type, cc));
+      gimple_assign_set_rhs_from_tree (gsi, fold_convert (type, cc));
+      stmt = gsi_stmt (*gsi);
       break;

     case GIMPLE_COND:
@@ -1465,7 +1464,8 @@ expand_complex_operations_1 (gimple_stmt
 	    rhs = extract_component (gsi, TREE_OPERAND (rhs, 0),
 		                     gimple_subcode (stmt) == IMAGPART_EXPR,
 				     false);
-	    gimple_assign_set_rhs_from_tree (stmt, rhs);
+	    gimple_assign_set_rhs_from_tree (gsi, rhs);
+	    stmt = gsi_stmt (*gsi);
 	    update_stmt (stmt);
 	  }
       }
Index: value-prof.c
===================================================================
--- value-prof.c	(revision 136344)
+++ value-prof.c	(working copy)
@@ -81,9 +81,9 @@ static tree gimple_divmod_fixed_value (g
 static tree gimple_mod_pow2 (gimple, int, gcov_type, gcov_type);
 static tree gimple_mod_subtract (gimple, int, int, int, gcov_type, gcov_type,
 				 gcov_type);
-static bool gimple_divmod_fixed_value_transform (gimple);
-static bool gimple_mod_pow2_value_transform (gimple);
-static bool gimple_mod_subtract_transform (gimple);
+static bool gimple_divmod_fixed_value_transform (gimple_stmt_iterator *);
+static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
+static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
 static bool gimple_stringops_transform (gimple_stmt_iterator *);
 static bool gimple_ic_transform (gimple);

@@ -484,9 +484,9 @@ gimple_value_profile_transformations (vo
 	     current statement remain valid (although possibly
 	     modified) upon return.  */
 	  if (flag_value_profile_transformations
-	      && (gimple_mod_subtract_transform (stmt)
-		  || gimple_divmod_fixed_value_transform (stmt)
-		  || gimple_mod_pow2_value_transform (stmt)
+	      && (gimple_mod_subtract_transform (&gsi)
+		  || gimple_divmod_fixed_value_transform (&gsi)
+		  || gimple_mod_pow2_value_transform (&gsi)
 		  || gimple_stringops_transform (&gsi)
 		  || gimple_ic_transform (stmt)))
 	    {
@@ -602,14 +602,16 @@ gimple_divmod_fixed_value (gimple stmt,
 /* Do transform 1) on INSN if applicable.  */

 static bool
-gimple_divmod_fixed_value_transform (gimple stmt)
+gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si)
 {
   histogram_value histogram;
   enum tree_code code;
   gcov_type val, count, all;
   tree result, value, tree_val;
   int prob;
+  gimple stmt;

+  stmt = gsi_stmt (*si);
   if (gimple_code (stmt) != GIMPLE_ASSIGN)
     return false;

@@ -661,7 +663,7 @@ gimple_divmod_fixed_value_transform (gim
       print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
     }

-  gimple_assign_set_rhs_from_tree (stmt, result);
+  gimple_assign_set_rhs_from_tree (si, result);

   return true;
 }
@@ -756,14 +758,16 @@ gimple_mod_pow2 (gimple stmt, int prob,

 /* Do transform 2) on INSN if applicable.  */
 static bool
-gimple_mod_pow2_value_transform (gimple stmt)
+gimple_mod_pow2_value_transform (gimple_stmt_iterator *si)
 {
   histogram_value histogram;
   enum tree_code code;
   gcov_type count, wrong_values, all;
   tree lhs_type, result, value;
   int prob;
+  gimple stmt;

+  stmt = gsi_stmt (*si);
   if (gimple_code (stmt) != GIMPLE_ASSIGN)
     return false;

@@ -808,7 +812,7 @@ gimple_mod_pow2_value_transform (gimple

   result = gimple_mod_pow2 (stmt, prob, count, all);

-  gimple_assign_set_rhs_from_tree (stmt, result);
+  gimple_assign_set_rhs_from_tree (si, result);

   return true;
 }
@@ -928,10 +932,10 @@ gimple_mod_subtract (gimple stmt, int pr
 }


-/* Do transforms 3) and 4) on STMT if applicable.  */
+/* Do transforms 3) and 4) on the statement pointed-to by SI if applicable.  */

 static bool
-gimple_mod_subtract_transform (gimple stmt)
+gimple_mod_subtract_transform (gimple_stmt_iterator *si)
 {
   histogram_value histogram;
   enum tree_code code;
@@ -940,7 +944,9 @@ gimple_mod_subtract_transform (gimple st
   int prob1, prob2;
   unsigned int i, steps;
   gcov_type count1, count2;
+  gimple stmt;

+  stmt = gsi_stmt (*si);
   if (gimple_code (stmt) != GIMPLE_ASSIGN)
     return false;

@@ -1005,7 +1011,7 @@ gimple_mod_subtract_transform (gimple st
      and will need to be changed if "steps" can change.  */
   result = gimple_mod_subtract (stmt, prob1, prob2, i, count1, count2, all);

-  gimple_assign_set_rhs_from_tree (stmt, result);
+  gimple_assign_set_rhs_from_tree (si, result);

   return true;
 }
Index: gimple.def
===================================================================
--- gimple.def	(revision 136344)
+++ gimple.def	(working copy)
@@ -21,12 +21,19 @@ Software Foundation, 51 Franklin Street,
 02110-1301, USA.  */

 /* The format of this file is
-   DEFGSCODE(GIMPLE_symbol, printable name).
+   DEFGSCODE(GIMPLE_symbol, printable name, structure).

-   Where symbol is the enumeration name without the ``GIMPLE_''.  */
+   Where symbol is the enumeration name without the ``GIMPLE_''.
+   The argument STRUCTURE is used to compute offsets into each of the
+   tuple structures that contain operands.  Since vector operands
+   are at different offsets depending on the particular structure
+   used, these offsets are computed at compile time for efficient
+   lookup at runtime.  See gimple_ops().
+
+   If a code does not use operand vectors, STRUCTURE should be NULL.  */

 /* Error marker.  This is used in similar ways as ERROR_MARK in tree.def.  */
-DEFGSCODE(GIMPLE_ERROR_MARK, "gimple_error_mark")
+DEFGSCODE(GIMPLE_ERROR_MARK, "gimple_error_mark", NULL)

 /* IMPORTANT.  Do not rearrange the codes between GIMPLE_COND and
    GIMPLE_RETURN.  The ordering is exposed by gimple_has_ops calls.
@@ -45,15 +52,15 @@ DEFGSCODE(GIMPLE_ERROR_MARK, "gimple_err

    TRUE_LABEL and FALSE_LABEL are the LABEL_DECL nodes used as the
    jump target for the comparison.  */
-DEFGSCODE(GIMPLE_COND, "gimple_cond")
+DEFGSCODE(GIMPLE_COND, "gimple_cond", struct gimple_statement_with_ops)

 /* GIMPLE_GOTO <TARGET> represents unconditional jumps.
    TARGET is a LABEL_DECL or an expression node for computed GOTOs.  */
-DEFGSCODE(GIMPLE_GOTO, "gimple_goto")
+DEFGSCODE(GIMPLE_GOTO, "gimple_goto", struct gimple_statement_with_ops)

 /* GIMPLE_LABEL <LABEL> represents label statements.  LABEL is a
    LABEL_DECL representing a jump target.  */
-DEFGSCODE(GIMPLE_LABEL, "gimple_label")
+DEFGSCODE(GIMPLE_LABEL, "gimple_label", struct gimple_statement_with_ops)

 /* GIMPLE_SWITCH <INDEX, DEFAULT_LAB, LAB1, ..., LABN> represents the
    multiway branch:
@@ -70,7 +77,7 @@ DEFGSCODE(GIMPLE_LABEL, "gimple_label")

    DEFAULT_LAB, LAB1 ... LABN are the tree nodes representing case labels.
    They must be CASE_LABEL_EXPR nodes.  */
-DEFGSCODE(GIMPLE_SWITCH, "gimple_switch")
+DEFGSCODE(GIMPLE_SWITCH, "gimple_switch", struct gimple_statement_with_ops)

 /* GIMPLE_CHANGE_DYNAMIC_TYPE indicates a change in the dynamic type
    of a memory location.  This has no value and generates no
@@ -80,7 +87,8 @@ DEFGSCODE(GIMPLE_SWITCH, "gimple_switch"
    (gimple_cdt_new_type) is the new type.  The second operand
    (gimple_cdt_location) is the location (pointer) whose type is being
    changed.  */
-DEFGSCODE(GIMPLE_CHANGE_DYNAMIC_TYPE, "gimple_change_dynamic_type")
+DEFGSCODE(GIMPLE_CHANGE_DYNAMIC_TYPE, "gimple_change_dynamic_type",
+	  struct gimple_statement_with_ops)

 /* IMPORTANT.  Do not rearrange the codes between GIMPLE_ASSIGN and
    GIMPLE_RETURN.  It's exposed by GIMPLE_RANGE_CHECK calls. These are
@@ -104,7 +112,8 @@ DEFGSCODE(GIMPLE_CHANGE_DYNAMIC_TYPE, "g
    RHS2 is the second operand on the RHS of the assignemnt. It must be a tree
    node accepted by is_gimple_operand.  This argument exists only if SUBCODE is
    of class GIMPLE_BINARY_RHS.  */
-DEFGSCODE(GIMPLE_ASSIGN, "gimple_assign")
+DEFGSCODE(GIMPLE_ASSIGN, "gimple_assign",
+	  struct gimple_statement_with_memory_ops)

 /* GIMPLE_ASM <STRING, I1, ..., IN, O1, ... OM, C1, ..., CP>
    represents inline assembly statements.
@@ -113,7 +122,7 @@ DEFGSCODE(GIMPLE_ASSIGN, "gimple_assign"
    I1 ... IN are the N input operands.
    O1 ... OM are the M output operands.
    C1 ... CP are the P clobber operands.  */
-DEFGSCODE(GIMPLE_ASM, "gimple_asm")
+DEFGSCODE(GIMPLE_ASM, "gimple_asm", struct gimple_statement_asm)

 /* GIMPLE_CALL <FN, LHS, ARG1, ..., ARGN[, CHAIN]> represents function
    calls.
@@ -127,29 +136,31 @@ DEFGSCODE(GIMPLE_ASM, "gimple_asm")
    is_gimple_operand.

     CHAIN is the optional static chain link for nested functions.  */
-DEFGSCODE(GIMPLE_CALL, "gimple_call")
+DEFGSCODE(GIMPLE_CALL, "gimple_call",
+	  struct gimple_statement_with_memory_ops)

 /* 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.  */
-DEFGSCODE(GIMPLE_RETURN, "gimple_return")
+DEFGSCODE(GIMPLE_RETURN, "gimple_return",
+	  struct gimple_statement_with_memory_ops)

 /* 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.  */
-DEFGSCODE(GIMPLE_BIND, "gimple_bind")
+DEFGSCODE(GIMPLE_BIND, "gimple_bind", NULL)

 /* 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.  */
-DEFGSCODE(GIMPLE_CATCH, "gimple_catch")
+DEFGSCODE(GIMPLE_CATCH, "gimple_catch", NULL)

 /* 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.  */
-DEFGSCODE(GIMPLE_EH_FILTER, "gimple_eh_filter")
+DEFGSCODE(GIMPLE_EH_FILTER, "gimple_eh_filter", NULL)

 /* GIMPLE_PHI <RESULT, ARG1, ..., ARGN> represents the PHI node

@@ -161,11 +172,11 @@ DEFGSCODE(GIMPLE_EH_FILTER, "gimple_eh_f
    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.  */
-DEFGSCODE(GIMPLE_PHI, "gimple_phi")
+DEFGSCODE(GIMPLE_PHI, "gimple_phi", NULL)

 /* GIMPLE_RESX <REGION> resumes execution after an exception.
    REGION is the region number being left.  */
-DEFGSCODE(GIMPLE_RESX, "gimple_resx")
+DEFGSCODE(GIMPLE_RESX, "gimple_resx", NULL)

 /* GIMPLE_TRY <TRY_KIND, EVAL, CLEANUP>
    represents a try/catch or a try/finally statement.
@@ -180,10 +191,10 @@ DEFGSCODE(GIMPLE_RESX, "gimple_resx")
    GIMPLE_TRY_FINALLY, CLEANUP is always executed after executing EVAL
    (regardless of whether EVAL finished normally, or jumped out or an
    exception was thrown).  */
-DEFGSCODE(GIMPLE_TRY, "gimple_try")
+DEFGSCODE(GIMPLE_TRY, "gimple_try", NULL)

 /* GIMPLE_NOP represents the "do nothing" statement.  */
-DEFGSCODE(GIMPLE_NOP, "gimple_nop")
+DEFGSCODE(GIMPLE_NOP, "gimple_nop", NULL)

 /* 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
@@ -194,12 +205,12 @@ DEFGSCODE(GIMPLE_NOP, "gimple_nop")
    GIMPLE_OMP_LOAD (tmp, mem)
    val = some computations involving tmp;
    GIMPLE_OMP_STORE (val).  */
-DEFGSCODE(GIMPLE_OMP_ATOMIC_LOAD, "gimple_omp_atomic_load")
-DEFGSCODE(GIMPLE_OMP_ATOMIC_STORE, "gimple_omp_atomic_store")
+DEFGSCODE(GIMPLE_OMP_ATOMIC_LOAD, "gimple_omp_atomic_load", NULL)
+DEFGSCODE(GIMPLE_OMP_ATOMIC_STORE, "gimple_omp_atomic_store", NULL)

 /* GIMPLE_OMP_CONTINUE marks the location of the loop or sections
    iteration in partially lowered OpenMP code.  */
-DEFGSCODE(GIMPLE_OMP_CONTINUE, "gimple_omp_continue")
+DEFGSCODE(GIMPLE_OMP_CONTINUE, "gimple_omp_continue", NULL)

 /* GIMPLE_OMP_CRITICAL <NAME, BODY> represents

@@ -207,7 +218,7 @@ DEFGSCODE(GIMPLE_OMP_CONTINUE, "gimple_o

    NAME is the name given to the critical section.
    BODY is the sequence of statements that are inside the critical section.  */
-DEFGSCODE(GIMPLE_OMP_CRITICAL, "gimple_omp_critical")
+DEFGSCODE(GIMPLE_OMP_CRITICAL, "gimple_omp_critical", NULL)


 /* GIMPLE_OMP_FOR <BODY, CLAUSES, INDEX, INITIAL, FINAL, COND, INCR, PRE_BODY>
@@ -245,15 +256,15 @@ DEFGSCODE(GIMPLE_OMP_CRITICAL, "gimple_o
    expressions that are evaluated without any synchronization.
    The evaluation order, frequency of evaluation and side-effects are
    unspecified by the standard.  */
-DEFGSCODE(GIMPLE_OMP_FOR, "gimple_omp_for")
+DEFGSCODE(GIMPLE_OMP_FOR, "gimple_omp_for", NULL)

 /* GIMPLE_OMP_MASTER <BODY> represents #pragma omp master.
    BODY is the sequence of statements to execute in the master section.  */
-DEFGSCODE(GIMPLE_OMP_MASTER, "gimple_omp_master")
+DEFGSCODE(GIMPLE_OMP_MASTER, "gimple_omp_master", NULL)

 /* GIMPLE_OMP_ORDERED <BODY> represents #pragma omp ordered.
    BODY is the sequence of statements to execute in the ordered section.  */
-DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered")
+DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered", NULL)

 /* GIMPLE_OMP_PARALLEL <BODY, CLAUSES, CHILD_FN, DATA_ARG> represents

@@ -271,14 +282,14 @@ DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_om
    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")
+DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", NULL)

 /* OMP_RETURN marks the end of an OpenMP directive.  */
-DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return")
+DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", NULL)

 /* OMP_SECTION <BODY> represents #pragma omp section.
    BODY is the sequence of statements in the section body.  */
-DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_omp_section")
+DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_omp_section", NULL)


 /* OMP_SECTIONS <BODY, CLAUSES, CONTROL> represents #pragma omp sections.
@@ -287,21 +298,21 @@ DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_om
    CLAUSES is a TREE_LIST node holding the list of associated clauses.
    CONTROL is a VAR_DECL used for deciding which of the sections
    to execute.  */
-DEFGSCODE(GIMPLE_OMP_SECTIONS, "gimple_omp_sections")
+DEFGSCODE(GIMPLE_OMP_SECTIONS, "gimple_omp_sections", NULL)

 /* GIMPLE_OMP_SECTIONS_SWITCH is a marker placed immediately after
    OMP_SECTIONS.  It represents the GIMPLE_SWITCH used to decide which
    branch is taken.  */
-DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch")
+DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch", NULL)

 /* GIMPLE_OMP_SINGLE <BODY, CLAUSES> represents #pragma omp single
    BODY is the sequence of statements inside the single section.
    CLAUSES is a TREE_LIST node holding the associated clauses.  */
-DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single")
+DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", NULL)

 /*  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.  */
-DEFGSCODE(GIMPLE_WITH_CLEANUP_EXPR, "gimple_with_cleanup_expr")
+DEFGSCODE(GIMPLE_WITH_CLEANUP_EXPR, "gimple_with_cleanup_expr", NULL)
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c	(revision 136344)
+++ tree-ssa-ccp.c	(working copy)
@@ -2628,13 +2628,15 @@ ccp_fold_builtin (gimple stmt)
   return result;
 }

-/* Attempt to fold an assignment statement.  Return true if any changes were
-   made.  The statement is modified in place, but its RHS class may change.
-   It is assumed that the operands have been previously folded.  */
+/* Attempt to fold an assignment statement pointed-to by SI.  Return true if
+   any changes were made.  The statement is modified in place, but its RHS
+   class may change. It is assumed that the operands have been previously
+   folded.  */

 static bool
-fold_gimple_assign (gimple stmt)
+fold_gimple_assign (gimple_stmt_iterator *si)
 {
+  gimple stmt = gsi_stmt (*si);
   enum tree_code subcode = gimple_assign_rhs_code (stmt);

   tree result = NULL;
@@ -2666,14 +2668,14 @@ fold_gimple_assign (gimple stmt)

         if (result != rhs && valid_gimple_rhs_p (result))
           {
-            gimple_assign_set_rhs_from_tree (stmt, result);
+            gimple_assign_set_rhs_from_tree (si, result);
             return true;
           }
         else
           /* It is possible that fold_stmt_r simplified the RHS.
              Make sure that the subcode of this statement still
              reflects the principal operator of the rhs operand. */
-          gimple_assign_set_rhs_from_tree (stmt, rhs);
+          gimple_assign_set_rhs_from_tree (si, rhs);
       }
       break;

@@ -2687,7 +2689,7 @@ fold_gimple_assign (gimple stmt)
           STRIP_USELESS_TYPE_CONVERSION (result);
           if (valid_gimple_rhs_p (result))
             {
-              gimple_assign_set_rhs_from_tree (stmt, result);
+              gimple_assign_set_rhs_from_tree (si, result);
               return true;
             }
         }
@@ -2712,7 +2714,7 @@ fold_gimple_assign (gimple stmt)
           STRIP_USELESS_TYPE_CONVERSION (result);
           if (valid_gimple_rhs_p (result))
             {
-              gimple_assign_set_rhs_from_tree (stmt, result);
+              gimple_assign_set_rhs_from_tree (si, result);
               return true;
             }
         }
@@ -2841,7 +2843,8 @@ fold_stmt (gimple_stmt_iterator *gsi)
   switch (gimple_code (stmt))
     {
     case GIMPLE_ASSIGN:
-      changed |= fold_gimple_assign (stmt);
+      changed |= fold_gimple_assign (gsi);
+      stmt = gsi_stmt (*gsi);
       break;
     case GIMPLE_COND:
       changed |= fold_gimple_cond (stmt);
@@ -2884,6 +2887,7 @@ fold_stmt_inplace (gimple stmt)
   tree res;
   struct fold_stmt_r_data fold_stmt_r_data;
   struct walk_stmt_info wi;
+  gimple_stmt_iterator si;

   bool changed = false;
   bool inside_addr_expr = false;
@@ -2910,7 +2914,9 @@ fold_stmt_inplace (gimple stmt)
   switch (gimple_code (stmt))
     {
     case GIMPLE_ASSIGN:
-      changed |= fold_gimple_assign (stmt);
+      si = gsi_for_stmt (stmt);
+      changed |= fold_gimple_assign (&si);
+      gcc_assert (gsi_stmt (si) == stmt);
       break;
     case GIMPLE_COND:
       changed |= fold_gimple_cond (stmt);
Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c	(revision 136344)
+++ tree-ssa-loop-ivopts.c	(working copy)
@@ -5086,7 +5086,10 @@ rewrite_use_nonlinear_expr (struct ivopt
       remove_statement (use->stmt, false);
     }
   else
-    gimple_assign_set_rhs_from_tree (use->stmt, op);
+    {
+      gimple_assign_set_rhs_from_tree (&bsi, op);
+      use->stmt = gsi_stmt (bsi);
+    }
 }

 /* Replaces ssa name in index IDX by its basic variable.  Callback for
Index: calls.c
===================================================================
--- calls.c	(revision 136344)
+++ calls.c	(working copy)
@@ -548,7 +548,9 @@ setjmp_call_p (const_tree fndecl)
   return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE;
 }

-/* Return true when an expression stmt contains alloca call.  */
+
+/* Return true if STMT is an alloca call.  */
+
 bool
 gimple_alloca_call_p (const_gimple stmt)
 {
Index: tree-predcom.c
===================================================================
--- tree-predcom.c	(revision 136344)
+++ tree-predcom.c	(working copy)
@@ -1254,16 +1254,18 @@ replace_ref_with (gimple stmt, tree new,
      appear as lhs or rhs of modify statement.  */
   gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN);

+  bsi = gsi_for_stmt (stmt);
+
   /* If we do not need to initialize NEW, just replace the use of OLD.  */
   if (!set)
     {
       gcc_assert (!in_lhs);
-      gimple_assign_set_rhs_from_tree (stmt, new);
+      gimple_assign_set_rhs_from_tree (&bsi, new);
+      stmt = gsi_stmt (bsi);
       update_stmt (stmt);
       return;
     }

-  bsi = gsi_for_stmt (stmt);
   if (in_lhs)
     {
       /* We have statement
@@ -2179,6 +2181,7 @@ static void
 remove_name_from_operation (gimple stmt, tree op)
 {
   tree other_op;
+  gimple_stmt_iterator si;

   gcc_assert (gimple_code (stmt) == GIMPLE_ASSIGN);

@@ -2187,7 +2190,12 @@ remove_name_from_operation (gimple stmt,
   else
     other_op = gimple_assign_rhs1 (stmt);

-  gimple_assign_set_rhs_from_tree (stmt, other_op);
+  si = gsi_for_stmt (stmt);
+  gimple_assign_set_rhs_from_tree (&si, other_op);
+
+  /* We should not have reallocated STMT.  */
+  gcc_assert (gsi_stmt (si) == stmt);
+
   update_stmt (stmt);
 }

@@ -2266,10 +2274,11 @@ reassociate_to_the_same_stmt (tree name1
 					   gimple_assign_rhs1 (s1),
 					   gimple_assign_rhs2 (s1));

-  gimple_assign_set_rhs_with_ops (s1, code, new_name, tmp_name);
+  bsi = gsi_for_stmt (s1);
+  gimple_assign_set_rhs_with_ops (&bsi, code, new_name, tmp_name);
+  s1 = gsi_stmt (bsi);
   update_stmt (s1);

-  bsi = gsi_for_stmt (s1);
   gsi_insert_before (&bsi, new_stmt, GSI_SAME_STMT);
   gsi_insert_before (&bsi, tmp_stmt, GSI_SAME_STMT);

Index: tree-ssa-copy.c
===================================================================
--- tree-ssa-copy.c	(revision 136344)
+++ tree-ssa-copy.c	(working copy)
@@ -445,7 +445,8 @@ propagate_tree_value_into_stmt (gimple_s
       if (gimple_assign_single_p (stmt))
         expr = gimple_assign_rhs1 (stmt);
       propagate_tree_value (&expr, val);
-      gimple_assign_set_rhs_from_tree (stmt, expr);
+      gimple_assign_set_rhs_from_tree (gsi, expr);
+      stmt = gsi_stmt (*gsi);
     }
   else if (gimple_code (stmt) == GIMPLE_COND)
     {
Index: tree-ssa.c
===================================================================
--- tree-ssa.c	(revision 136344)
+++ tree-ssa.c	(working copy)
@@ -1006,17 +1006,17 @@ delete_tree_ssa (void)

 	  if (gimple_has_ops (stmt))
 	    {
-	      stmt->with_ops.def_ops = NULL;
-	      stmt->with_ops.use_ops = NULL;
-	      BITMAP_FREE (stmt->with_ops.addresses_taken);
+	      gimple_set_def_ops (stmt, NULL);
+	      gimple_set_use_ops (stmt, NULL);
+	      gimple_set_addresses_taken (stmt, NULL);
 	    }

 	  if (gimple_has_mem_ops (stmt))
 	    {
-	      stmt->with_mem_ops.vdef_ops = NULL;
-	      stmt->with_mem_ops.vuse_ops = NULL;
-	      BITMAP_FREE (stmt->with_mem_ops.stores);
-	      BITMAP_FREE (stmt->with_mem_ops.loads);
+	      gimple_set_vdef_ops (stmt, NULL);
+	      gimple_set_vuse_ops (stmt, NULL);
+	      BITMAP_FREE (stmt->gsmem.membase.stores);
+	      BITMAP_FREE (stmt->gsmem.membase.loads);
 	    }

 	  gimple_set_modified (stmt, true);
Index: system.h
===================================================================
--- system.h	(revision 136344)
+++ system.h	(working copy)
@@ -796,6 +796,7 @@ extern void fancy_abort (const char *, i
 #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))

 /* Activate -Wcast-qual as a warning (not an error/-Werror).  */
 #if GCC_VERSION >= 4003
Index: tree-vect-generic.c
===================================================================
--- tree-vect-generic.c	(revision 136344)
+++ tree-vect-generic.c	(working copy)
@@ -515,7 +515,7 @@ expand_vector_operations_1 (gimple_stmt_
      gimple_assign_set_rhs_from_tree. One way to do it is change
      expand_vector_operation and its callees to return a tree_code,
      RHS1 and RHS2 instead of a tree. */
-  gimple_assign_set_rhs_from_tree (stmt, new_rhs);
+  gimple_assign_set_rhs_from_tree (gsi, new_rhs);

   gimple_set_modified (gsi_stmt (*gsi), true);
 }
Index: gimple.c
===================================================================
--- gimple.c	(revision 136344)
+++ gimple.c	(working copy)
@@ -36,12 +36,22 @@ Software Foundation, 51 Franklin Street,
 #include "value-prof.h"
 #include "flags.h"

-#define DEFGSCODE(SYM, NAME)	NAME,
+#define DEFGSCODE(SYM, NAME, STRUCT)	NAME,
 const char *const gimple_code_name[] = {
 #include "gimple.def"
 };
 #undef DEFGSCODE

+/* All the tuples have their operand vector at the very bottom
+   of the structure.  Therefore, the offset required to find the
+   operands vector the size of the structure minus the size of the 1
+   element tree array at the end (see gimple_ops).  */
+#define DEFGSCODE(SYM, NAME, STRUCT)	(sizeof (STRUCT) - sizeof (tree)),
+const size_t gimple_ops_offset_[] = {
+#include "gimple.def"
+};
+#undef DEFGSCODE
+
 #ifdef GATHER_STATISTICS
 /* Gimple stats.  */

@@ -63,6 +73,11 @@ static const char * const gimple_alloc_k
    fairly often during gimplification.  */
 static GTY ((deletable)) struct gimple_seq_d *gimple_seq_cache;

+/* Private API manipulation functions shared only with some
+   other files.  */
+extern void gimple_set_stored_syms (gimple, bitmap, bitmap_obstack *);
+extern void gimple_set_loaded_syms (gimple, bitmap, bitmap_obstack *);
+
 /* Gimple tuple constructors.
    Note: Any constructor taking a ``gimple_seq'' as a parameter, can
    be passed a NULL to start with an empty sequence.  */
@@ -174,7 +189,7 @@ gimple_size (enum gimple_code code)
     case GIMPLE_WITH_CLEANUP_EXPR:
       return sizeof (struct gimple_statement_wce);
     case GIMPLE_CHANGE_DYNAMIC_TYPE:
-      return sizeof (struct gimple_statement_change_dynamic_type);
+      return sizeof (struct gimple_statement_with_ops);
     default:
       break;
     }
@@ -183,43 +198,36 @@ gimple_size (enum gimple_code code)
 }


-/* Allocate memory for a GIMPLE statement with code CODE.  */
+/* Allocate memory for a GIMPLE statement with code CODE and NUM_OPS
+   operands.  */

 static gimple
-gimple_alloc (enum gimple_code code)
+gimple_alloc (enum gimple_code code, unsigned num_ops)
 {
-  size_t size = gimple_size (code);
+  size_t size;
   gimple stmt;

-#ifdef GATHER_STATISTICS
-  enum gimple_alloc_kind kind = gimple_alloc_kind (code);
+  size = gimple_size (code);
+  if (num_ops > 0)
+    size += sizeof (tree) * (num_ops - 1);

-  gimple_alloc_counts[(int) kind]++;
-  /* Statements with operands take more space.  Add that later.  */
-  gimple_alloc_sizes[(int) kind] += size;
+#ifdef GATHER_STATISTICS
+  {
+    enum gimple_alloc_kind kind = gimple_alloc_kind (code);
+    gimple_alloc_counts[(int) kind]++;
+    gimple_alloc_sizes[(int) kind] += size;
+  }
 #endif

   stmt = ggc_alloc_cleared (size);
   gimple_set_code (stmt, code);
-  return stmt;
-}
-
-
-/* Allocate memory for NUM operands for statement STMT.  The allocated
-   memory is not returned.  After calling this function, the new
-   operand vector will be available via gimple_op.  */
+  gimple_set_num_ops (stmt, num_ops);

-static void
-gimple_alloc_ops (gimple stmt, size_t num_ops)
-{
-  unsigned int size = sizeof (tree) * num_ops;
+  /* 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->with_ops.op = ggc_alloc_cleared (size);
-  stmt->with_ops.num_ops = num_ops;
-  stmt->with_ops.modified = 1;
-#ifdef GATHER_STATISTICS
-  gimple_alloc_sizes[(int) gimple_alloc_kind (gimple_code (stmt))] += size;
-#endif
+  return stmt;
 }


@@ -229,12 +237,10 @@ gimple_alloc_ops (gimple stmt, size_t nu

 static gimple
 gimple_build_with_ops (enum gimple_code code, enum tree_code subcode,
-		       size_t num_ops)
+		       unsigned num_ops)
 {
-  gimple s = gimple_alloc (code);
+  gimple s = gimple_alloc (code, num_ops);
   gimple_set_subcode (s, subcode);
-  if (num_ops > 0)
-    gimple_alloc_ops (s, num_ops);

   return s;
 }
@@ -256,10 +262,10 @@ gimple_build_return (tree retval)
    GIMPLE_CALL statement to function FN with NARGS arguments.  */

 static inline gimple
-gimple_build_call_1 (tree fn, size_t nargs)
+gimple_build_call_1 (tree fn, unsigned nargs)
 {
   gimple s = gimple_build_with_ops (GIMPLE_CALL, 0, nargs + 3);
-  s->with_ops.op[1] = fn;
+  gimple_set_op (s, 1, fn);
   return s;
 }

@@ -270,8 +276,8 @@ gimple_build_call_1 (tree fn, size_t nar
 gimple
 gimple_build_call_vec (tree fn, VEC(tree, heap) *args)
 {
-  size_t i;
-  size_t nargs = VEC_length (tree, args);
+  unsigned i;
+  unsigned nargs = VEC_length (tree, args);
   gimple call = gimple_build_call_1 (fn, nargs);

   for (i = 0; i < nargs; i++)
@@ -285,11 +291,11 @@ gimple_build_call_vec (tree fn, VEC(tree
    arguments.  The ... are the arguments.  */

 gimple
-gimple_build_call (tree fn, size_t nargs, ...)
+gimple_build_call (tree fn, unsigned nargs, ...)
 {
   va_list ap;
   gimple call;
-  size_t i;
+  unsigned i;

   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));

@@ -311,7 +317,7 @@ gimple_build_call (tree fn, size_t nargs
 gimple
 gimple_build_call_from_tree (tree t)
 {
-  size_t i, nargs;
+  unsigned i, nargs;
   gimple call;
   tree fndecl = get_callee_fndecl (t);

@@ -396,7 +402,7 @@ gimple
 gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1,
                               tree op2)
 {
-  size_t num_ops;
+  unsigned num_ops;
   gimple p;

   /* Need 1 operand for LHS and 1 or 2 for the RHS (depending on the
@@ -514,7 +520,7 @@ gimple_build_goto (tree dest)
 gimple
 gimple_build_nop (void)
 {
-  return gimple_alloc (GIMPLE_NOP);
+  return gimple_alloc (GIMPLE_NOP, 0);
 }


@@ -525,7 +531,7 @@ gimple_build_nop (void)
 gimple
 gimple_build_bind (tree vars, gimple_seq body, tree block)
 {
-  gimple p = gimple_alloc (GIMPLE_BIND);
+  gimple p = gimple_alloc (GIMPLE_BIND, 0);
   gimple_bind_set_vars (p, vars);
   if (body)
     gimple_bind_set_body (p, body);
@@ -542,8 +548,8 @@ gimple_build_bind (tree vars, gimple_seq
    */

 static inline gimple
-gimple_build_asm_1 (const char *string, size_t ninputs, size_t noutputs,
-                    size_t nclobbers)
+gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
+                    unsigned nclobbers)
 {
   gimple p;
   int size = strlen (string);
@@ -554,6 +560,7 @@ gimple_build_asm_1 (const char *string,
   p->gimple_asm.no = noutputs;
   p->gimple_asm.nc = nclobbers;
   p->gimple_asm.string = ggc_alloc_string (string, size);
+
 #ifdef GATHER_STATISTICS
   gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size;
 #endif
@@ -576,7 +583,8 @@ gimple_build_asm_vec (const char *string
                       VEC(tree,gc)* outputs, VEC(tree,gc)* clobbers)
 {
   gimple p;
-  size_t i;
+  unsigned i;
+
   p = gimple_build_asm_1 (string,
                           VEC_length (tree, inputs),
                           VEC_length (tree, outputs),
@@ -603,11 +611,11 @@ gimple_build_asm_vec (const char *string
    ... are trees for each input, output and clobbered register.  */

 gimple
-gimple_build_asm (const char *string, size_t ninputs, size_t noutputs,
-		  size_t nclobbers, ...)
+gimple_build_asm (const char *string, unsigned ninputs, unsigned noutputs,
+		  unsigned nclobbers, ...)
 {
   gimple p;
-  size_t i;
+  unsigned i;
   va_list ap;

   p = gimple_build_asm_1 (string, ninputs, noutputs, nclobbers);
@@ -636,7 +644,7 @@ gimple_build_asm (const char *string, si
 gimple
 gimple_build_catch (tree types, gimple_seq handler)
 {
-  gimple p = gimple_alloc (GIMPLE_CATCH);
+  gimple p = gimple_alloc (GIMPLE_CATCH, 0);
   gimple_catch_set_types (p, types);
   if (handler)
     gimple_catch_set_handler (p, handler);
@@ -652,7 +660,7 @@ gimple_build_catch (tree types, gimple_s
 gimple
 gimple_build_eh_filter (tree types, gimple_seq failure)
 {
-  gimple p = gimple_alloc (GIMPLE_EH_FILTER);
+  gimple p = gimple_alloc (GIMPLE_EH_FILTER, 0);
   gimple_eh_filter_set_types (p, types);
   if (failure)
     gimple_eh_filter_set_failure (p, failure);
@@ -674,7 +682,7 @@ gimple_build_try (gimple_seq eval, gimpl
   gimple p;

   gcc_assert (kind == GIMPLE_TRY_CATCH || kind == GIMPLE_TRY_FINALLY);
-  p = gimple_alloc (GIMPLE_TRY);
+  p = gimple_alloc (GIMPLE_TRY, 0);
   gimple_set_subcode (p, kind);
   if (eval)
     gimple_try_set_eval (p, eval);
@@ -691,7 +699,7 @@ gimple_build_try (gimple_seq eval, gimpl
 gimple
 gimple_build_wce (gimple_seq cleanup)
 {
-  gimple p = gimple_alloc (GIMPLE_WITH_CLEANUP_EXPR);
+  gimple p = gimple_alloc (GIMPLE_WITH_CLEANUP_EXPR, 0);
   if (cleanup)
     gimple_wce_set_cleanup (p, cleanup);

@@ -707,7 +715,7 @@ gimple_build_wce (gimple_seq cleanup)
 gimple
 gimple_build_resx (int region)
 {
-  gimple p = gimple_alloc (GIMPLE_RESX);
+  gimple p = gimple_alloc (GIMPLE_RESX, 0);
   gimple_resx_set_region (p, region);
   return p;
 }
@@ -719,7 +727,7 @@ gimple_build_resx (int region)
    DEFAULT_LABEL is the default label for the switch statement.  */

 static inline gimple
-gimple_build_switch_1 (size_t nlabels, tree index, tree default_label)
+gimple_build_switch_1 (unsigned nlabels, tree index, tree default_label)
 {
   /* nlabels + 1 default label + 1 index.  */
   gimple p = gimple_build_with_ops (GIMPLE_SWITCH, 0, nlabels + 1 + 1);
@@ -736,10 +744,10 @@ gimple_build_switch_1 (size_t nlabels, t
    ... are the labels excluding the default.  */

 gimple
-gimple_build_switch (size_t nlabels, tree index, tree default_label, ...)
+gimple_build_switch (unsigned nlabels, tree index, tree default_label, ...)
 {
   va_list al;
-  size_t i;
+  unsigned i;
   gimple p;

   p = gimple_build_switch_1 (nlabels, index, default_label);
@@ -763,8 +771,8 @@ gimple_build_switch (size_t nlabels, tre
 gimple
 gimple_build_switch_vec (tree index, tree default_label, VEC(tree, heap) *args)
 {
-  size_t i;
-  size_t nlabels = VEC_length (tree, args);
+  unsigned i;
+  unsigned nlabels = VEC_length (tree, args);
   gimple p = gimple_build_switch_1 (nlabels, index, default_label);

   /*  Put labels in labels[1 - (nlabels + 1)].
@@ -784,7 +792,7 @@ gimple_build_switch_vec (tree index, tre
 gimple
 gimple_build_omp_critical (gimple_seq body, tree name)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL);
+  gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL, 0);
   gimple_omp_critical_set_name (p, name);
   if (body)
     gimple_omp_set_body (p, body);
@@ -809,7 +817,7 @@ gimple_build_omp_for (gimple_seq body, t
                       tree initial, tree final, tree incr,
                       gimple_seq pre_body, enum tree_code omp_for_cond)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_FOR);
+  gimple p = gimple_alloc (GIMPLE_OMP_FOR, 0);
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_for_set_clauses (p, clauses);
@@ -836,7 +844,7 @@ gimple
 gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn,
                        tree data_arg)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_PARALLEL);
+  gimple p = gimple_alloc (GIMPLE_OMP_PARALLEL, 0);
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_parallel_set_clauses (p, clauses);
@@ -854,7 +862,7 @@ gimple_build_omp_parallel (gimple_seq bo
 gimple
 gimple_build_omp_section (gimple_seq body)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_SECTION);
+  gimple p = gimple_alloc (GIMPLE_OMP_SECTION, 0);
   if (body)
     gimple_omp_set_body (p, body);

@@ -869,7 +877,7 @@ gimple_build_omp_section (gimple_seq bod
 gimple
 gimple_build_omp_master (gimple_seq body)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_MASTER);
+  gimple p = gimple_alloc (GIMPLE_OMP_MASTER, 0);
   if (body)
     gimple_omp_set_body (p, body);

@@ -885,7 +893,7 @@ gimple_build_omp_master (gimple_seq body
 gimple
 gimple_build_omp_continue (tree control_def, tree control_use)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_CONTINUE);
+  gimple p = gimple_alloc (GIMPLE_OMP_CONTINUE, 0);
   gimple_omp_continue_set_control_def (p, control_def);
   gimple_omp_continue_set_control_use (p, control_use);
   return p;
@@ -899,7 +907,7 @@ gimple_build_omp_continue (tree control_
 gimple
 gimple_build_omp_ordered (gimple_seq body)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_ORDERED);
+  gimple p = gimple_alloc (GIMPLE_OMP_ORDERED, 0);
   if (body)
     gimple_omp_set_body (p, body);

@@ -913,7 +921,7 @@ gimple_build_omp_ordered (gimple_seq bod
 gimple
 gimple_build_omp_return (bool wait_p)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_RETURN);
+  gimple p = gimple_alloc (GIMPLE_OMP_RETURN, 0);
   if (wait_p)
     gimple_omp_return_set_nowait (p);

@@ -930,7 +938,7 @@ gimple_build_omp_return (bool wait_p)
 gimple
 gimple_build_omp_sections (gimple_seq body, tree clauses)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_SECTIONS);
+  gimple p = gimple_alloc (GIMPLE_OMP_SECTIONS, 0);
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_sections_set_clauses (p, clauses);
@@ -944,7 +952,7 @@ gimple_build_omp_sections (gimple_seq bo
 gimple
 gimple_build_omp_sections_switch (void)
 {
-  return gimple_alloc (GIMPLE_OMP_SECTIONS_SWITCH);
+  return gimple_alloc (GIMPLE_OMP_SECTIONS_SWITCH, 0);
 }


@@ -957,7 +965,7 @@ gimple_build_omp_sections_switch (void)
 gimple
 gimple_build_omp_single (gimple_seq body, tree clauses)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_SINGLE);
+  gimple p = gimple_alloc (GIMPLE_OMP_SINGLE, 0);
   if (body)
     gimple_omp_set_body (p, body);
   gimple_omp_single_set_clauses (p, clauses);
@@ -972,7 +980,7 @@ gimple_build_omp_single (gimple_seq body
 gimple
 gimple_build_cdt (tree type, tree ptr)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_CHANGE_DYNAMIC_TYPE, 0, 1);
+  gimple p = gimple_build_with_ops (GIMPLE_CHANGE_DYNAMIC_TYPE, 0, 2);
   gimple_cdt_set_new_type (p, type);
   gimple_cdt_set_location (p, ptr);

@@ -985,7 +993,7 @@ gimple_build_cdt (tree type, tree ptr)
 gimple
 gimple_build_omp_atomic_load (tree lhs, tree rhs)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD);
+  gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD, 0);
   gimple_omp_atomic_load_set_lhs (p, lhs);
   gimple_omp_atomic_load_set_rhs (p, rhs);
   return p;
@@ -998,7 +1006,7 @@ gimple_build_omp_atomic_load (tree lhs,
 gimple
 gimple_build_omp_atomic_store (tree val)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_STORE);
+  gimple p = gimple_alloc (GIMPLE_OMP_ATOMIC_STORE, 0);
   gimple_omp_atomic_store_set_val (p, val);
   return p;
 }
@@ -1040,7 +1048,7 @@ gimple_range_check_failed (const_gimple
 		           enum gimple_code c2)
 {
   char *buffer;
-  size_t length = 0;
+  unsigned length = 0;
   enum gimple_code c;

   for (c = c1; c <= c2; ++c)
@@ -1245,9 +1253,9 @@ walk_gimple_asm (gimple stmt, walk_tree_
 		 struct walk_stmt_info *wi)
 {
   tree ret;
-  size_t noutputs;
+  unsigned noutputs;
   const char **oconstraints;
-  size_t i;
+  unsigned i;
   const char *constraint;
   bool allows_mem, allows_reg, is_inout;

@@ -1318,7 +1326,7 @@ walk_gimple_op (gimple stmt, walk_tree_f
 		struct walk_stmt_info *wi)
 {
   struct pointer_set_t *pset = (wi) ? wi->pset : NULL;
-  size_t i;
+  unsigned i;
   tree ret = NULL_TREE;

   switch (gimple_code (stmt))
@@ -1790,11 +1798,11 @@ gimple_set_bb (gimple stmt, basic_block
       uid = LABEL_DECL_UID (t);
       if (uid == -1)
 	{
-	  size_t old_len = VEC_length (basic_block, label_to_block_map);
+	  unsigned old_len = VEC_length (basic_block, label_to_block_map);
 	  LABEL_DECL_UID (t) = uid = cfun->cfg->last_label_uid++;
-	  if (old_len <= (size_t) uid)
+	  if (old_len <= (unsigned) uid)
 	    {
-	      size_t new_len = 3 * uid / 2;
+	      unsigned new_len = 3 * uid / 2;

 	      VEC_safe_grow_cleared (basic_block, gc, label_to_block_map,
 				     new_len);
@@ -1853,8 +1861,11 @@ gimple_fold (const_gimple stmt)
 }


-/* Modify the RHS of assignment STMT using the operands in the
-   expression tree EXPR.
+/* Modify the RHS of the assignment pointed-to by GSI using the
+   operands in the expression tree EXPR.
+
+   NOTE: The statement pointed-to by GSI may be reallocated if it
+   did not have enough operand slots.

    This function is useful to convert an existing tree expression into
    the flat representation used for the RHS of a GIMPLE assignment.
@@ -1868,36 +1879,47 @@ gimple_fold (const_gimple stmt)
    expression tree to be built.  */

 void
-gimple_assign_set_rhs_from_tree (gimple stmt, tree expr)
+gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr)
 {
   enum tree_code subcode;
   tree op1, op2;

   extract_ops_from_tree (expr, &subcode, &op1, &op2);
-  gimple_assign_set_rhs_with_ops (stmt, subcode, op1, op2);
+  gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2);
 }


-/* Set the RHS of assignment statement STMT to CODE with operands OP1 and
-   OP2.  */
+/* Set the RHS of assignment statement pointed-to by GSI to CODE with
+   operands OP1 and OP2.
+
+   NOTE: The statement pointed-to by GSI may be reallocated if it
+   did not have enough operand slots.  */

 void
-gimple_assign_set_rhs_with_ops (gimple stmt, enum tree_code code, tree op1,
-			        tree op2)
+gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
+				tree op1, tree op2)
 {
-  size_t num_ops = get_gimple_rhs_num_ops (code);
+  unsigned new_rhs_ops = get_gimple_rhs_num_ops (code);
+  gimple stmt = gsi_stmt (*gsi);

-  /* Reallocate the memory operands vector, if necessary.  */
-  if (get_gimple_rhs_num_ops (gimple_assign_rhs_code (stmt)) != num_ops)
+  /* If the new CODE needs more operands, allocate a new statement.  */
+  if (gimple_num_ops (stmt) < new_rhs_ops + 1)
     {
       tree lhs = gimple_assign_lhs (stmt);
-      gimple_alloc_ops (stmt, num_ops + 1);
+      gimple new_stmt = gimple_alloc (gimple_code (stmt), new_rhs_ops + 1);
+      memcpy (new_stmt, stmt, gimple_size (gimple_code (stmt)));
+      gsi_replace (gsi, new_stmt, true);
+      stmt = new_stmt;
+
+      /* The LHS needs to be reset as this also changes the SSA name
+	 on the LHS.  */
       gimple_assign_set_lhs (stmt, lhs);
     }

+  gimple_set_num_ops (stmt, new_rhs_ops + 1);
   gimple_set_subcode (stmt, code);
   gimple_assign_set_rhs1 (stmt, op1);
-  if (num_ops > 1)
+  if (new_rhs_ops > 1)
     gimple_assign_set_rhs2 (stmt, op2);
 }

@@ -1946,8 +1968,8 @@ gimple
 gimple_copy (gimple stmt)
 {
   enum gimple_code code = gimple_code (stmt);
-  size_t num_ops = gimple_num_ops (stmt);
-  gimple copy = gimple_alloc (code);
+  unsigned num_ops = gimple_num_ops (stmt);
+  gimple copy = gimple_alloc (code, num_ops);
   unsigned i;

   /* Shallow copy all the fields from STMT.  */
@@ -2045,25 +2067,30 @@ gimple_copy (gimple stmt)
   /* Make copy of operands.  */
   if (num_ops > 0)
     {
-      gimple_alloc_ops (copy, num_ops);
       for (i = 0; i < num_ops; i++)
 	gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
-    }

-  /* Clear out SSA operand vectors on COPY.  */
-  if (gimple_has_ops (stmt))
-    {
-      gimple_set_def_ops (copy, NULL);
-      gimple_set_use_ops (copy, NULL);
-      copy->with_ops.addresses_taken = NULL;
-    }
+      /* Clear out SSA operand vectors on COPY.  Note that we cannot
+	 call the API functions for setting addresses_taken, stores
+	 and loads.  These functions free the previous values, and we
+	 cannot do that on COPY as it will affect the original
+	 statement.  */
+      if (gimple_has_ops (stmt))
+	{
+	  gimple_set_def_ops (copy, NULL);
+	  gimple_set_use_ops (copy, NULL);
+	  copy->gsops.opbase.addresses_taken = NULL;
+	}

-  if (gimple_has_mem_ops (stmt))
-    {
-      gimple_set_vdef_ops (copy, NULL);
-      gimple_set_vuse_ops (copy, NULL);
-      stmt->with_mem_ops.stores = NULL;
-      stmt->with_mem_ops.loads = NULL;
+      if (gimple_has_mem_ops (stmt))
+	{
+	  gimple_set_vdef_ops (copy, NULL);
+	  gimple_set_vuse_ops (copy, NULL);
+	  copy->gsmem.membase.stores = NULL;
+	  copy->gsmem.membase.loads = NULL;
+	}
+
+      update_stmt (copy);
     }

   return copy;
@@ -2090,8 +2117,9 @@ gimple_copy_no_def_use (gimple stmt)
   if (code == GIMPLE_PHI)
     {
       unsigned i;
-      size_t size = (sizeof (struct gimple_statement_phi)
-                     + (sizeof (struct phi_arg_d) *
(stmt->gimple_phi.capacity - 1)));
+      unsigned size = (sizeof (struct gimple_statement_phi)
+                     + (sizeof (struct phi_arg_d)
+		        * (stmt->gimple_phi.capacity - 1)));
       gimple copy = ggc_alloc_cleared (size);

       memcpy (copy, stmt, size);
@@ -2100,26 +2128,19 @@ gimple_copy_no_def_use (gimple stmt)
       {
         struct phi_arg_d * arg_ptr = gimple_phi_arg (copy, i);
         arg_ptr->def = unshare_expr (gimple_phi_arg_def (stmt, i));
-        /*
-        arg_ptr->imm_use.prev = &arg_ptr->imm_use;
-        arg_ptr->imm_use.next = &arg_ptr->imm_use;
-        arg_ptr->imm_use.loc.ssa_name = NULL;
-        arg_ptr->imm_use.use = NULL;
-        */
       }

       return copy;
     }
   else
     {
-      size_t num_ops = gimple_num_ops (stmt);
-      gimple copy = gimple_alloc (code);
+      unsigned num_ops = gimple_num_ops (stmt);
+      gimple copy = gimple_alloc (code, num_ops);
       unsigned i;

       memcpy (copy, stmt, gimple_size (code));
       if (num_ops > 0)
       {
-        gimple_alloc_ops (copy, num_ops);
         for (i = 0; i < num_ops; i++)
           gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));

@@ -2140,7 +2161,7 @@ gimple_set_modified (gimple s, bool modi
 {
   if (gimple_has_ops (s))
     {
-      s->with_ops.modified = (unsigned) modifiedp;
+      s->gsbase.modified = (unsigned) modifiedp;

       if (modifiedp
 	  && cfun->gimple_df
@@ -2160,18 +2181,17 @@ gimple_set_modified (gimple s, bool modi
 bool
 gimple_has_side_effects (const_gimple s)
 {
-  size_t i;
+  unsigned i;

   /* We don't have to scan the arguments to check for
      volatile arguments, though, at present, we still
      do a scan to check for TREE_SIDE_EFFECTS.  */
-
   if (gimple_has_volatile_ops (s))
     return true;

   if (is_gimple_call (s))
     {
-      size_t nargs = gimple_call_num_args (s);
+      unsigned nargs = gimple_call_num_args (s);

       if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
         return true;
@@ -2217,11 +2237,11 @@ gimple_has_side_effects (const_gimple s)
 bool
 gimple_rhs_has_side_effects (const_gimple s)
 {
-  size_t i;
+  unsigned i;

   if (is_gimple_call (s))
     {
-      size_t nargs = gimple_call_num_args (s);
+      unsigned nargs = gimple_call_num_args (s);

       if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
         return true;
@@ -2274,7 +2294,7 @@ gimple_rhs_has_side_effects (const_gimpl
 bool
 gimple_could_trap_p (gimple s)
 {
-  size_t i;
+  unsigned i;
   tree t, div = NULL_TREE;
   enum tree_code op;

@@ -2322,7 +2342,7 @@ gimple_could_trap_p (gimple s)
 void
 gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p)
 {
-  size_t i, num_ops = gimple_num_ops (stmt);
+  unsigned i, num_ops = gimple_num_ops (stmt);

   for (i = 0; i < num_ops; i++)
     {
@@ -2372,4 +2392,45 @@ dump_gimple_statistics (void)
 #endif
 }

+
+/* Make SYMS be the set of symbols stored by STMT.  If SYMS is NULL or
+   empty, the storage used is freed up.  */
+
+
+void
+gimple_set_stored_syms (gimple stmt, bitmap syms, bitmap_obstack *obs)
+{
+  gcc_assert (gimple_has_mem_ops (stmt));
+
+  if (syms == NULL)
+    BITMAP_FREE (stmt->gsmem.membase.stores);
+  else
+    {
+      if (stmt->gsmem.membase.stores == NULL)
+	stmt->gsmem.membase.stores = BITMAP_ALLOC (obs);
+
+      bitmap_copy (stmt->gsmem.membase.stores, syms);
+    }
+}
+
+
+/* Deep copy SYMS into the set of symbols loaded by STMT.  If SYMS is
+   NULL or empty, the storage used is freed up.  */
+
+void
+gimple_set_loaded_syms (gimple stmt, bitmap syms, bitmap_obstack *obs)
+{
+  gcc_assert (gimple_has_mem_ops (stmt));
+
+  if (syms == NULL)
+    BITMAP_FREE (stmt->gsmem.membase.loads);
+  else
+    {
+      if (stmt->gsmem.membase.loads == NULL)
+	stmt->gsmem.membase.loads = BITMAP_ALLOC (obs);
+
+      bitmap_copy (stmt->gsmem.membase.loads, syms);
+    }
+}
+
 #include "gt-gimple.h"
Index: gimple.h
===================================================================
--- gimple.h	(revision 136344)
+++ gimple.h	(working copy)
@@ -40,12 +40,14 @@ DEF_VEC_ALLOC_P(gimple_seq,gc);
 DEF_VEC_ALLOC_P(gimple_seq,heap);

 enum gimple_code {
-#define DEFGSCODE(SYM, STRING)	SYM,
+#define DEFGSCODE(SYM, STRING, STRUCT)	SYM,
 #include "gimple.def"
 #undef DEFGSCODE
     LAST_AND_UNUSED_GIMPLE_CODE
 };

+extern const char *const gimple_code_name[];
+
 /* Error out if a gimple tuple is addressed incorrectly.  */
 #if defined ENABLE_GIMPLE_CHECKING
 extern void gimple_check_failed (const_gimple, const char *, int,          \
@@ -236,23 +238,28 @@ typedef struct
 } gimple_stmt_iterator;


-/* Data structure definitions for GIMPLE tuples.  */
+/* Data structure definitions for GIMPLE tuples.  NOTE: word markers
+   are for 64 bit hosts.  */

 struct gimple_statement_base GTY(())
 {
+  /* [ WORD 1 ]
+     Main identifying codes for a tuple.  The SUBCODE field can be
+     used for tuple-specific flags for tuples that do not require
+     subcodes.  Note that SUBCODE should be at least as wide as tree
+     codes, as several tuples store tree codes in there.  */
   ENUM_BITFIELD(gimple_code) code : 16;
   unsigned int subcode : 8;

-  /* NOTE for future expansion.  It would be possible to have 32
-     additional bit flags.  This would avoid wasting the 32bit hole
-     left in this structure on 64bit hosts, but it would make this
-     structure grow an additional word on 32bit hosts.  */
+  /* Nonzero if a warning should not be emitted on this tuple.  */
   unsigned int no_warning	: 1;
+
+  /* Nonzero if this tuple has been visited.  Passes are responsible
+     for clearing this bit before using it.  */
   unsigned int visited		: 1;
+
+  /* Nonzero if this tuple represents a non-temporal move.  */
   unsigned int nontemporal_move	: 1;
-  unsigned int unused_1		: 1;
-  unsigned int unused_2		: 1;
-  unsigned int unused_3		: 1;

   /* Pass local flags.  These flags are free for any pass to use as
      they see fit.  Passes should not assume that these flags contain
@@ -261,59 +268,115 @@ struct gimple_statement_base GTY(())
      gimple_set_plf and gimple_plf for usage.  */
   unsigned int plf		: 2;

-  /* Basic block holding this statement.  */
-  struct basic_block_def *bb;
+  /* Nonzero if this statement has been modified and needs to have its
+     operands rescanned.  */
+  unsigned modified 		: 1;

-  /* Locus information for debug info.  */
+  /* Nonzero if this statement contains volatile operands.  */
+  unsigned has_volatile_ops 	: 1;
+
+  /* Nonzero if this statement contains memory refernces.  */
+  unsigned references_memory_p 	: 1;
+
+  /* UID of this statement.  */
+  unsigned uid;
+
+  /* [ WORD 2 ]
+     Locus information for debug info.  */
   location_t location;

-  /* Lexical block holding this statement.  FIXME, needed?  */
+  /* Number of operands in this tuple.  */
+  unsigned num_ops;
+
+  /* [ WORD 3 ]
+     Basic block holding this statement.  */
+  struct basic_block_def *bb;
+
+  /* [ WORD 4 ]
+     Lexical block holding this statement.  */
   tree block;
-
-  /* Uid of this statement.  */
-  unsigned uid;
 };


-/* Statements that take register operands.  */
+/* Base structure for tuples with operands.  */

-struct gimple_statement_with_ops GTY(())
+struct gimple_statement_with_ops_base GTY(())
 {
+  /* [ WORD  1-4 ]  */
   struct gimple_statement_base gsbase;
-  unsigned modified : 1;
+
+  /* [ WORD 5 ]
+     Symbols whose addresses are taken by this statement (i.e., they
+     appear inside ADDR_EXPR nodes).  */
   bitmap GTY((skip (""))) addresses_taken;

-  /* FIXME tuples.  OP should be amalgamated with DEF_OPS and USE_OPS.
-     This duplication is unnecessary.  */
+  /* [ WORD 6-7 ]
+     SSA operand vectors.  NOTE: It should be possible to
+     amalgamate these vectors with the operand vector OP.  However,
+     the SSA operand vectors are organized differently and contain
+     more information (like immediate use chaining).  */
   struct def_optype_d GTY((skip (""))) *def_ops;
   struct use_optype_d GTY((skip (""))) *use_ops;
+};

-  /* FIXME tuples.  For many tuples, the number of operands can
-     be deduced from the code.  */
-  size_t num_ops;
-  tree * GTY((length ("%h.num_ops"))) op;
+
+/* Statements that take register operands.  */
+
+struct gimple_statement_with_ops GTY(())
+{
+  /* [ WORD 1-7 ]  */
+  struct gimple_statement_with_ops_base opbase;
+
+  /* [ 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];
 };


-/* Statements that take both memory and register operands.  */
+/* Base for statements that take both memory and register operands.  */

-struct gimple_statement_with_memory_ops GTY(())
+struct gimple_statement_with_memory_ops_base GTY(())
 {
-  struct gimple_statement_with_ops with_ops;
-  unsigned has_volatile_ops : 1;
-  unsigned references_memory_p : 1;
+  /* [ WORD 1-7 ]  */
+  struct gimple_statement_with_ops_base opbase;
+
+  /* [ WORD 8-9 ]
+     Vectors for virtual operands.  */
   struct voptype_d GTY((skip (""))) *vdef_ops;
   struct voptype_d GTY((skip (""))) *vuse_ops;
+
+  /* [ WORD 9-10 ]
+     Symbols stored/loaded by this statement.  */
   bitmap GTY((skip (""))) stores;
   bitmap GTY((skip (""))) loads;
 };


+/* Statements that take both memory and register operands.  */
+
+struct gimple_statement_with_memory_ops GTY(())
+{
+  /* [ WORD 1-10 ]  */
+  struct gimple_statement_with_memory_ops_base membase;
+
+  /* [ WORD 11 ]
+     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];
+};
+
+
 /* OpenMP statements (#pragma omp).  */

 struct gimple_statement_omp GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;
+
+  /* [ WORD 5 ]  */
   gimple_seq body;
 };

@@ -322,13 +385,20 @@ struct gimple_statement_omp GTY(())

 struct gimple_statement_bind GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;
+
+  /* [ WORD 5 ]
+     Variables declared in this scope.  */
   tree vars;

-  /* This is different than the ``block'' in gimple_statement_base, which
+  /* [ WORD 6 ]
+     This is different than the ``block'' in gimple_statement_base, which
      is analogous to TREE_BLOCK.  This block is the equivalent of
      BIND_EXPR_BLOCK in tree land.  See gimple-low.c.  */
   tree block;
+
+  /* [ WORD 7 ]  */
   gimple_seq body;
 };

@@ -337,8 +407,13 @@ struct gimple_statement_bind GTY(())

 struct gimple_statement_catch GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;
+
+  /* [ WORD 5 ]  */
   tree types;
+
+  /* [ WORD 6 ]  */
   gimple_seq handler;
 };

@@ -347,15 +422,18 @@ struct gimple_statement_catch GTY(())

 struct gimple_statement_eh_filter GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;

   /* Subcode: EH_FILTER_MUST_NOT_THROW.  A boolean flag analogous to
      the tree counterpart.  */

-  /* Filter types.  */
+  /* [ WORD 5 ]
+     Filter types.  */
   tree types;

-  /* Failure actions.  */
+  /* [ WORD 6 ]
+     Failure actions.  */
   gimple_seq failure;
 };

@@ -364,10 +442,17 @@ struct gimple_statement_eh_filter GTY(()

 struct gimple_statement_phi GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;
-  size_t capacity;
-  size_t nargs;
+
+  /* [ WORD 5 ]  */
+  unsigned capacity;
+  unsigned nargs;
+
+  /* [ WORD 6 ]  */
   tree result;
+
+  /* [ WORD 7 ]  */
   struct phi_arg_d GTY ((length ("%h.nargs"))) args[1];
 };

@@ -376,9 +461,11 @@ struct gimple_statement_phi GTY(())

 struct gimple_statement_resx GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;

-  /* Exception region number.  */
+  /* [ WORD 5 ]
+     Exception region number.  */
   int region;
 };

@@ -387,19 +474,26 @@ struct gimple_statement_resx GTY(())

 struct gimple_statement_try GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;

-  /* Expression to evaluate.  */
+  /* [ WORD 5 ]
+     Expression to evaluate.  */
   gimple_seq eval;

-  /* Cleanup expression.  */
+  /* [ WORD 6 ]
+     Cleanup expression.  */
   gimple_seq cleanup;
 };

 /* Kind of GIMPLE_TRY statements.  */
-enum gimple_try_flags {
-  GIMPLE_TRY_CATCH = 1 << 0,			/* A try/catch.  */
-  GIMPLE_TRY_FINALLY = 1 << 1,		/* A try/finally.  */
+enum gimple_try_flags
+{
+  /* A try/catch.  */
+  GIMPLE_TRY_CATCH = 1 << 0,
+
+  /* A try/finally.  */
+  GIMPLE_TRY_FINALLY = 1 << 1,
   GIMPLE_TRY_KIND = GIMPLE_TRY_CATCH | GIMPLE_TRY_FINALLY,

   /* Analogous to TRY_CATCH_IS_CLEANUP.  */
@@ -410,6 +504,7 @@ enum gimple_try_flags {

 struct gimple_statement_wce GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;

   /* Subcode: CLEANUP_EH_ONLY.  True if the cleanup should only be
@@ -417,29 +512,45 @@ struct gimple_statement_wce GTY(())
 	      scope.  This flag is analogous to the CLEANUP_EH_ONLY flag
 	      in TARGET_EXPRs.  */

-  /* Cleanup expression.  */
+  /* [ WORD 5 ]
+     Cleanup expression.  */
   gimple_seq cleanup;
 };


-/* GIMPLE_ASM */
+/* GIMPLE_ASM  */

 struct gimple_statement_asm GTY(())
 {
-  struct gimple_statement_with_memory_ops with_mem_ops;
-  const char *string;	/* __asm__ statement.  */
-  size_t ni;		/* Number of inputs.  */
-  size_t no;		/* Number of outputs.  */
-  size_t nc;		/* Number of clobbers.  */
+  /* [ WORD 1-10 ]  */
+  struct gimple_statement_with_memory_ops_base membase;
+
+  /* [ WORD 11 ]
+     __asm__ statement.  */
+  const char *string;
+
+  /* [ WORD 12 ]
+       Number of inputs, outputs and clobbers.  */
+  unsigned char ni;
+  unsigned char no;
+  unsigned short nc;
+
+  /* [ WORD 13 ]
+     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];
 };

 /* GIMPLE_OMP_CRITICAL */

 struct gimple_statement_omp_critical GTY(())
 {
+  /* [ WORD 1-5 ]  */
   struct gimple_statement_omp omp;

-  /* Critical section name.  */
+  /* [ WORD 6 ]
+     Critical section name.  */
   tree name;
 };

@@ -448,22 +559,30 @@ struct gimple_statement_omp_critical GTY

 struct gimple_statement_omp_for GTY(())
 {
+  /* [ WORD 1-5 ]  */
   struct gimple_statement_omp omp;
+
+  /* [ WORD 6 ]  */
   tree clauses;

-  /* Index variable.  */
+  /* [ WORD 7 ]
+     Index variable.  */
   tree index;

-  /* Initial value.  */
+  /* [ WORD 8 ]
+     Initial value.  */
   tree initial;

-  /* Final value.  */
+  /* [ WORD 9 ]
+     Final value.  */
   tree final;

-  /* Increment.  */
+  /* [ WORD 10 ]
+     Increment.  */
   tree incr;

-  /* Pre-body evaluated before the loop body begins.  */
+  /* [ WORD 11 ]
+     Pre-body evaluated before the loop body begins.  */
   gimple_seq pre_body;
 };

@@ -472,15 +591,19 @@ struct gimple_statement_omp_for GTY(())

 struct gimple_statement_omp_parallel GTY(())
 {
+  /* [ WORD 1-5 ]  */
   struct gimple_statement_omp omp;

-  /* Clauses.  */
+  /* [ WORD 6 ]
+     Clauses.  */
   tree clauses;

-  /* Child function holding the body of the parallel region.  */
+  /* [ WORD 7 ]
+     Child function holding the body of the parallel region.  */
   tree child_fn;

-  /* Shared data argument.  */
+  /* [ WORD 8 ]
+     Shared data argument.  */
   tree data_arg;
 };

@@ -492,11 +615,14 @@ struct gimple_statement_omp_parallel GTY

 struct gimple_statement_omp_sections GTY(())
 {
+  /* [ WORD 1-5 ]  */
   struct gimple_statement_omp omp;

+  /* [ WORD 6 ]  */
   tree clauses;

-  /* The control variable used for deciding which of the sections to
+  /* [ WORD 7 ]
+     The control variable used for deciding which of the sections to
      execute.  */
   tree control;
 };
@@ -508,8 +634,13 @@ struct gimple_statement_omp_sections GTY

 struct gimple_statement_omp_continue GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;
+
+  /* [ WORD 5 ]  */
   tree control_def;
+
+  /* [ WORD 6 ]  */
   tree control_use;
 };

@@ -517,26 +648,24 @@ struct gimple_statement_omp_continue GTY

 struct gimple_statement_omp_single GTY(())
 {
+  /* [ WORD 1-5 ]  */
   struct gimple_statement_omp omp;
+
+  /* [ WORD 6 ]  */
   tree clauses;
 };


-/* GIMPLE_CHANGE_DYNAMIC_TYPE  */
-
-struct gimple_statement_change_dynamic_type GTY(())
-{
-  struct gimple_statement_with_ops with_ops;
-  tree type;
-};
-
 /* 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.  */

 struct gimple_statement_omp_atomic_load GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;
+
+  /* [ WORD 5-6 ]  */
   tree rhs, lhs;
 };

@@ -545,7 +674,10 @@ struct gimple_statement_omp_atomic_load

 struct gimple_statement_omp_atomic_store GTY(())
 {
+  /* [ WORD 1-4 ]  */
   struct gimple_statement_base gsbase;
+
+  /* [ WORD 5 ]  */
   tree val;
 };

@@ -563,8 +695,8 @@ enum gimple_statement_structure_enum {
 union gimple_statement_d GTY ((desc ("gimple_statement_structure (&%h)")))
 {
   struct gimple_statement_base GTY ((tag ("GSS_BASE"))) gsbase;
-  struct gimple_statement_with_ops GTY ((tag ("GSS_WITH_OPS"))) with_ops;
-  struct gimple_statement_with_memory_ops GTY ((tag
("GSS_WITH_MEM_OPS"))) with_mem_ops;
+  struct gimple_statement_with_ops GTY ((tag ("GSS_WITH_OPS"))) gsops;
+  struct gimple_statement_with_memory_ops GTY ((tag
("GSS_WITH_MEM_OPS"))) gsmem;
   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;
@@ -580,7 +712,6 @@ union gimple_statement_d GTY ((desc ("gi
   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_change_dynamic_type GTY ((tag
("GSS_CHANGE_DYNAMIC_TYPE"))) gimple_change_dynamic_type;
   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;
 };
@@ -591,14 +722,14 @@ gimple gimple_build_assign (tree, tree);
 void extract_ops_from_tree (tree, enum tree_code *, tree *, tree *);
 gimple gimple_build_assign_with_ops (enum tree_code, tree, tree, tree);
 gimple gimple_build_call_vec (tree, VEC(tree, heap) *);
-gimple gimple_build_call (tree, size_t, ...);
+gimple gimple_build_call (tree, unsigned, ...);
 gimple gimple_build_call_from_tree (tree);
 gimple gimple_build_cond (enum tree_code, tree, tree, tree, tree);
 gimple gimple_build_label (tree label);
 gimple gimple_build_goto (tree dest);
 gimple gimple_build_nop (void);
 gimple gimple_build_bind (tree, gimple_seq, tree);
-gimple gimple_build_asm (const char *, size_t, size_t, size_t, ...);
+gimple gimple_build_asm (const char *, unsigned, unsigned, unsigned, ...);
 gimple gimple_build_asm_vec (const char *, VEC(tree,gc) *, VEC(tree,gc) *,
                              VEC(tree,gc) *);
 gimple gimple_build_catch (tree, gimple_seq);
@@ -606,7 +737,7 @@ gimple gimple_build_eh_filter (tree, gim
 gimple gimple_build_try (gimple_seq, gimple_seq, unsigned int);
 gimple gimple_build_wce (gimple_seq);
 gimple gimple_build_resx (int);
-gimple gimple_build_switch (size_t, tree, tree, ...);
+gimple gimple_build_switch (unsigned, tree, tree, ...);
 gimple gimple_build_switch_vec (tree, tree, VEC(tree,heap) *);
 gimple gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
 gimple gimple_build_omp_for (gimple_seq, tree, tree, tree, tree, tree,
@@ -638,8 +769,9 @@ bool gimple_assign_single_p (gimple);
 bool gimple_assign_unary_nop_p (gimple);
 void gimple_set_bb (gimple, struct basic_block_def *);
 tree gimple_fold (const_gimple);
-void gimple_assign_set_rhs_from_tree (gimple, tree);
-void gimple_assign_set_rhs_with_ops (gimple, enum tree_code, tree, tree);
+void gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *, tree);
+void gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *, enum tree_code,
+				     tree, tree);
 tree gimple_get_lhs (gimple);
 void gimple_set_lhs (gimple, tree);
 gimple gimple_copy (gimple);
@@ -905,6 +1037,42 @@ gimple_has_mem_ops (const_gimple g)
   return gimple_code (g) >= GIMPLE_ASSIGN && gimple_code (g) <= GIMPLE_RETURN;
 }

+/* Return the set of addresses taken by statement G.  */
+
+static inline bitmap
+gimple_addresses_taken (const_gimple g)
+{
+  if (gimple_has_ops (g))
+    return g->gsops.opbase.addresses_taken;
+  else
+    return NULL;
+}
+
+
+/* Return a pointer to the set of addresses taken by statement G.  */
+
+static inline bitmap *
+gimple_addresses_taken_ptr (gimple g)
+{
+  if (gimple_has_ops (g))
+    return &g->gsops.opbase.addresses_taken;
+  else
+    return NULL;
+}
+
+
+/* Set B to be the set of addresses taken by statement G.  The
+   previous set is freed.  */
+
+static inline void
+gimple_set_addresses_taken (gimple g, bitmap b)
+{
+  gcc_assert (gimple_has_ops (g));
+  if (g->gsops.opbase.addresses_taken)
+    BITMAP_FREE (g->gsops.opbase.addresses_taken);
+  g->gsops.opbase.addresses_taken = b;
+}
+

 /* Return the set of DEF operands for statement G.  */

@@ -913,7 +1081,7 @@ gimple_def_ops (const_gimple g)
 {
   if (!gimple_has_ops (g))
     return NULL;
-  return g->with_ops.def_ops;
+  return g->gsops.opbase.def_ops;
 }


@@ -923,7 +1091,7 @@ static inline void
 gimple_set_def_ops (gimple g, struct def_optype_d *def)
 {
   gcc_assert (gimple_has_ops (g));
-  g->with_ops.def_ops = def;
+  g->gsops.opbase.def_ops = def;
 }


@@ -934,7 +1102,7 @@ gimple_use_ops (const_gimple g)
 {
   if (!gimple_has_ops (g))
     return NULL;
-  return g->with_ops.use_ops;
+  return g->gsops.opbase.use_ops;
 }


@@ -944,7 +1112,7 @@ static inline void
 gimple_set_use_ops (gimple g, struct use_optype_d *use)
 {
   gcc_assert (gimple_has_ops (g));
-  g->with_ops.use_ops = use;
+  g->gsops.opbase.use_ops = use;
 }


@@ -955,7 +1123,7 @@ gimple_vuse_ops (const_gimple g)
 {
   if (!gimple_has_mem_ops (g))
     return NULL;
-  return g->with_mem_ops.vuse_ops;
+  return g->gsmem.membase.vuse_ops;
 }


@@ -965,7 +1133,7 @@ static inline void
 gimple_set_vuse_ops (gimple g, struct voptype_d *ops)
 {
   gcc_assert (gimple_has_mem_ops (g));
-  g->with_mem_ops.vuse_ops = ops;
+  g->gsmem.membase.vuse_ops = ops;
 }


@@ -976,7 +1144,7 @@ gimple_vdef_ops (const_gimple g)
 {
   if (!gimple_has_mem_ops (g))
     return NULL;
-  return g->with_mem_ops.vdef_ops;
+  return g->gsmem.membase.vdef_ops;
 }


@@ -986,7 +1154,7 @@ static inline void
 gimple_set_vdef_ops (gimple g, struct voptype_d *ops)
 {
   gcc_assert (gimple_has_mem_ops (g));
-  g->with_mem_ops.vdef_ops = ops;
+  g->gsmem.membase.vdef_ops = ops;
 }


@@ -998,7 +1166,7 @@ gimple_loaded_syms (const_gimple g)
 {
   if (!gimple_has_mem_ops (g))
     return NULL;
-  return g->with_mem_ops.loads;
+  return g->gsmem.membase.loads;
 }


@@ -1010,7 +1178,7 @@ gimple_stored_syms (const_gimple g)
 {
   if (!gimple_has_mem_ops (g))
     return NULL;
-  return g->with_mem_ops.stores;
+  return g->gsmem.membase.stores;
 }


@@ -1020,7 +1188,7 @@ gimple_stored_syms (const_gimple g)
 static inline bool
 gimple_modified_p (const_gimple g)
 {
-  return (gimple_has_ops (g)) ? (bool) g->with_ops.modified : false;
+  return (gimple_has_ops (g)) ? (bool) g->gsbase.modified : false;
 }


@@ -1051,7 +1219,7 @@ static inline bool
 gimple_has_volatile_ops (const_gimple stmt)
 {
   if (gimple_has_mem_ops (stmt))
-    return stmt->with_mem_ops.has_volatile_ops;
+    return stmt->gsbase.has_volatile_ops;
   else
     return false;
 }
@@ -1063,7 +1231,7 @@ static inline void
 gimple_set_has_volatile_ops (gimple stmt, bool volatilep)
 {
   if (gimple_has_mem_ops (stmt))
-    stmt->with_mem_ops.has_volatile_ops = (unsigned) volatilep;
+    stmt->gsbase.has_volatile_ops = (unsigned) volatilep;
 }


@@ -1072,7 +1240,7 @@ gimple_set_has_volatile_ops (gimple stmt
 static inline bool
 gimple_references_memory_p (gimple stmt)
 {
-  return gimple_has_mem_ops (stmt) && stmt->with_mem_ops.references_memory_p;
+  return gimple_has_mem_ops (stmt) && stmt->gsbase.references_memory_p;
 }


@@ -1082,7 +1250,7 @@ static inline void
 gimple_set_references_memory (gimple stmt, bool mem_p)
 {
   if (gimple_has_mem_ops (stmt))
-    stmt->with_mem_ops.references_memory_p = (unsigned) mem_p;
+    stmt->gsbase.references_memory_p = (unsigned) mem_p;
 }


@@ -1153,37 +1321,51 @@ gimple_omp_parallel_set_combined_p (gimp
 }


-extern const char *const gimple_code_name[];
+/* Return the number of operands for statement GS.  */

+static inline unsigned
+gimple_num_ops (const_gimple gs)
+{
+  return gs->gsbase.num_ops;
+}

-/* Return the number of operands for statement GS.  FIXME, every
-   GIMPLE statement should know how to reply to this.  */

-static inline size_t
-gimple_num_ops (const_gimple gs)
+/* Set the number of operands for statement GS.  */
+
+static inline void
+gimple_set_num_ops (gimple gs, unsigned num_ops)
 {
-  return (gimple_has_ops (gs)) ? gs->with_ops.num_ops : 0;
+  gs->gsbase.num_ops = num_ops;
 }


 /* Return the array of operands for statement GS.  */

 static inline tree *
-gimple_ops (const_gimple gs)
+gimple_ops (gimple gs)
 {
-  return (gimple_has_ops (gs)) ? gs->with_ops.op : NULL;
+  /* Offset in bytes to the location of the operand vector in every
+     tuple structure.  Defined in gimple.c  */
+  extern size_t const gimple_ops_offset_[];
+
+  if (!gimple_has_ops (gs))
+    return NULL;
+
+  /* All the tuples have their operand vector at the very bottom
+     of the structure.  */
+  return ((tree *) ((char *) gs + gimple_ops_offset_[gimple_code (gs)]));
 }


 /* Return operand I for statement GS.  */

 static inline tree
-gimple_op (const_gimple gs, size_t i)
+gimple_op (const_gimple gs, unsigned i)
 {
   if (gimple_has_ops (gs))
     {
-      gcc_assert (i < gs->with_ops.num_ops);
-      return gs->with_ops.op[i];
+      gcc_assert (i < gimple_num_ops (gs));
+      return gimple_ops (CONST_CAST_GIMPLE (gs))[i];
     }
   else
     return NULL_TREE;
@@ -1192,12 +1374,12 @@ gimple_op (const_gimple gs, size_t i)
 /* Return a pointer to operand I for statement GS.  */

 static inline tree *
-gimple_op_ptr (const_gimple gs, size_t i)
+gimple_op_ptr (const_gimple gs, unsigned i)
 {
   if (gimple_has_ops (gs))
     {
-      gcc_assert (i < gs->with_ops.num_ops);
-      return &gs->with_ops.op[i];
+      gcc_assert (i < gimple_num_ops (gs));
+      return gimple_ops (CONST_CAST_GIMPLE (gs)) + i;
     }
   else
     return NULL;
@@ -1206,23 +1388,15 @@ gimple_op_ptr (const_gimple gs, size_t i
 /* Set operand I of statement GS to OP.  */

 static inline void
-gimple_set_op (gimple gs, size_t i, tree op)
+gimple_set_op (gimple gs, unsigned i, tree op)
 {
-  gcc_assert (gimple_has_ops (gs) && i < gs->with_ops.num_ops);
+  gcc_assert (gimple_has_ops (gs) && i < gimple_num_ops (gs));

   /* Note.  It may be tempting to assert that OP matches
      is_gimple_operand, but that would be wrong.  Different tuples
      accept slightly different sets of tree operands.  Each caller
      should perform its own validation.  */
-  gs->with_ops.op[i] = op;
-}
-
-/* Return the set of symbols that have had their address taken by STMT.  */
-
-static inline bitmap
-gimple_addresses_taken (gimple stmt)
-{
-  return gimple_has_ops (stmt) ? stmt->with_ops.addresses_taken : NULL;
+  gimple_ops (gs)[i] = op;
 }

 /* Return true if GS is a GIMPLE_ASSIGN.  */
@@ -1515,19 +1689,21 @@ gimple_call_set_chain (gimple gs, tree c

 /* Return the number of arguments used by call statement GS.  */

-static inline size_t
+static inline unsigned
 gimple_call_num_args (const_gimple gs)
 {
+  unsigned num_ops;
   GIMPLE_CHECK (gs, GIMPLE_CALL);
-  gcc_assert (gs->with_ops.num_ops >= 3);
-  return gs->with_ops.num_ops - 3;
+  num_ops = gimple_num_ops (gs);
+  gcc_assert (num_ops >= 3);
+  return num_ops - 3;
 }


 /* Return the argument at position INDEX for call statement GS.  */

 static inline tree
-gimple_call_arg (const_gimple gs, size_t index)
+gimple_call_arg (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
   return gimple_op (gs, index + 3);
@@ -1538,7 +1714,7 @@ gimple_call_arg (const_gimple gs, size_t
    statement GS.  */

 static inline tree *
-gimple_call_arg_ptr (const_gimple gs, size_t index)
+gimple_call_arg_ptr (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
   return gimple_op_ptr (gs, index + 3);
@@ -1548,7 +1724,7 @@ gimple_call_arg_ptr (const_gimple gs, si
 /* Set ARG to be the argument at position INDEX for call statement GS.  */

 static inline void
-gimple_call_set_arg (gimple gs, size_t index, tree arg)
+gimple_call_set_arg (gimple gs, unsigned index, tree arg)
 {
   GIMPLE_CHECK (gs, GIMPLE_CALL);
   gcc_assert (is_gimple_operand (arg));
@@ -2068,7 +2244,7 @@ gimple_bind_set_block (gimple gs, tree b

 /* Return the number of input operands for GIMPLE_ASM GS.  */

-static inline size_t
+static inline unsigned
 gimple_asm_ninputs (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
@@ -2078,7 +2254,7 @@ gimple_asm_ninputs (const_gimple gs)

 /* Return the number of output operands for GIMPLE_ASM GS.  */

-static inline size_t
+static inline unsigned
 gimple_asm_noutputs (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
@@ -2088,7 +2264,7 @@ gimple_asm_noutputs (const_gimple gs)

 /* Return the number of clobber operands for GIMPLE_ASM GS.  */

-static inline size_t
+static inline unsigned
 gimple_asm_nclobbers (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
@@ -2099,7 +2275,7 @@ gimple_asm_nclobbers (const_gimple gs)
 /* Return input operand INDEX of GIMPLE_ASM GS.  */

 static inline tree
-gimple_asm_input_op (const_gimple gs, size_t index)
+gimple_asm_input_op (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.ni);
@@ -2109,7 +2285,7 @@ gimple_asm_input_op (const_gimple gs, si
 /* Return a pointer to input operand INDEX of GIMPLE_ASM GS.  */

 static inline tree *
-gimple_asm_input_op_ptr (const_gimple gs, size_t index)
+gimple_asm_input_op_ptr (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.ni);
@@ -2120,7 +2296,7 @@ gimple_asm_input_op_ptr (const_gimple gs
 /* Set IN_OP to be input operand INDEX in GIMPLE_ASM GS.  */

 static inline void
-gimple_asm_set_input_op (gimple gs, size_t index, tree in_op)
+gimple_asm_set_input_op (gimple gs, unsigned index, tree in_op)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.ni);
@@ -2132,7 +2308,7 @@ gimple_asm_set_input_op (gimple gs, size
 /* Return output operand INDEX of GIMPLE_ASM GS.  */

 static inline tree
-gimple_asm_output_op (const_gimple gs, size_t index)
+gimple_asm_output_op (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.no);
@@ -2142,7 +2318,7 @@ gimple_asm_output_op (const_gimple gs, s
 /* Return a pointer to output operand INDEX of GIMPLE_ASM GS.  */

 static inline tree *
-gimple_asm_output_op_ptr (const_gimple gs, size_t index)
+gimple_asm_output_op_ptr (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.no);
@@ -2153,7 +2329,7 @@ gimple_asm_output_op_ptr (const_gimple g
 /* Set OUT_OP to be output operand INDEX in GIMPLE_ASM GS.  */

 static inline void
-gimple_asm_set_output_op (gimple gs, size_t index, tree out_op)
+gimple_asm_set_output_op (gimple gs, unsigned index, tree out_op)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.no);
@@ -2165,7 +2341,7 @@ gimple_asm_set_output_op (gimple gs, siz
 /* Return clobber operand INDEX of GIMPLE_ASM GS.  */

 static inline tree
-gimple_asm_clobber_op (const_gimple gs, size_t index)
+gimple_asm_clobber_op (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.nc);
@@ -2176,7 +2352,7 @@ gimple_asm_clobber_op (const_gimple gs,
 /* Set CLOBBER_OP to be clobber operand INDEX in GIMPLE_ASM GS.  */

 static inline void
-gimple_asm_set_clobber_op (gimple gs, size_t index, tree clobber_op)
+gimple_asm_set_clobber_op (gimple gs, unsigned index, tree clobber_op)
 {
   GIMPLE_CHECK (gs, GIMPLE_ASM);
   gcc_assert (index <= gs->gimple_asm.nc);
@@ -2495,7 +2671,7 @@ gimple_wce_set_cleanup_eh_only (gimple g

 /* Return the maximum number of arguments supported by GIMPLE_PHI GS.  */

-static inline size_t
+static inline unsigned
 gimple_phi_capacity (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_PHI);
@@ -2507,7 +2683,7 @@ gimple_phi_capacity (const_gimple gs)
    be exactly the number of incoming edges for the basic block holding
    GS.  FIXME tuples, this field is useless then.  */

-static inline size_t
+static inline unsigned
 gimple_phi_num_args (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_PHI);
@@ -2547,7 +2723,7 @@ gimple_phi_set_result (gimple gs, tree r
    GIMPLE_PHI GS.  */

 static inline struct phi_arg_d *
-gimple_phi_arg (gimple gs, size_t index)
+gimple_phi_arg (gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_PHI);
   gcc_assert (index <= gs->gimple_phi.capacity);
@@ -2558,7 +2734,7 @@ gimple_phi_arg (gimple gs, size_t index)
    for GIMPLE_PHI GS.  */

 static inline void
-gimple_phi_set_arg (gimple gs, size_t index, struct phi_arg_d * phiarg)
+gimple_phi_set_arg (gimple gs, unsigned index, struct phi_arg_d * phiarg)
 {
   GIMPLE_CHECK (gs, GIMPLE_PHI);
   gcc_assert (index <= gs->gimple_phi.nargs);
@@ -2586,22 +2762,24 @@ gimple_resx_set_region (gimple gs, int r

 /* Return the number of labels associated with the switch statement GS.  */

-static inline size_t
+static inline unsigned
 gimple_switch_num_labels (const_gimple gs)
 {
+  unsigned num_ops;
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
-  gcc_assert (gs->with_ops.num_ops > 1);
-  return gs->with_ops.num_ops - 1;
+  num_ops = gimple_num_ops (gs);
+  gcc_assert (num_ops > 1);
+  return num_ops - 1;
 }


 /* Set NLABELS to be the number of labels for the switch statement GS.  */

 static inline void
-gimple_switch_set_num_labels (gimple g, size_t nlabels)
+gimple_switch_set_num_labels (gimple g, unsigned nlabels)
 {
   GIMPLE_CHECK (g, GIMPLE_SWITCH);
-  g->with_ops.num_ops = nlabels + 1;
+  gimple_set_num_ops (g, nlabels + 1);
 }


@@ -2640,20 +2818,20 @@ gimple_switch_set_index (gimple gs, tree
    labels in a switch statement.  */

 static inline tree
-gimple_switch_label (const_gimple gs, size_t index)
+gimple_switch_label (const_gimple gs, unsigned index)
 {
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
-  gcc_assert (gs->with_ops.num_ops > index + 1);
+  gcc_assert (gimple_num_ops (gs) > index + 1);
   return gimple_op (gs, index + 1);
 }

 /* Set the label number INDEX to LABEL.  0 is always the default label.  */

 static inline void
-gimple_switch_set_label (gimple gs, size_t index, tree label)
+gimple_switch_set_label (gimple gs, unsigned index, tree label)
 {
   GIMPLE_CHECK (gs, GIMPLE_SWITCH);
-  gcc_assert (gs->with_ops.num_ops > index + 1);
+  gcc_assert (gimple_num_ops (gs) > index + 1);
   gcc_assert (label == NULL_TREE || TREE_CODE (label) == CASE_LABEL_EXPR);
   gimple_set_op (gs, index + 1, label);
 }
@@ -3255,7 +3433,7 @@ static inline tree *
 gimple_return_retval_ptr (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_RETURN);
-  gcc_assert (gs->with_ops.num_ops == 1);
+  gcc_assert (gimple_num_ops (gs) == 1);
   return gimple_op_ptr (gs, 0);
 }

@@ -3265,7 +3443,7 @@ static inline tree
 gimple_return_retval (const_gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_RETURN);
-  gcc_assert (gs->with_ops.num_ops == 1);
+  gcc_assert (gimple_num_ops (gs) == 1);
   return gimple_op (gs, 0);
 }

@@ -3276,7 +3454,7 @@ static inline void
 gimple_return_set_retval (gimple gs, tree retval)
 {
   GIMPLE_CHECK (gs, GIMPLE_RETURN);
-  gcc_assert (gs->with_ops.num_ops == 1);
+  gcc_assert (gimple_num_ops (gs) == 1);
   gcc_assert (retval == NULL_TREE
               || TREE_CODE (retval) == RESULT_DECL
 	      || is_gimple_val (retval));
@@ -3332,7 +3510,7 @@ static inline tree
 gimple_cdt_new_type (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
-  return gs->gimple_change_dynamic_type.type;
+  return gimple_op (gs, 1);
 }

 /* Return a pointer to the new type set by GIMPLE_CHANGE_DYNAMIC_TYPE
@@ -3342,7 +3520,7 @@ static inline tree *
 gimple_cdt_new_type_ptr (gimple gs)
 {
   GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
-  return &gs->gimple_change_dynamic_type.type;
+  return gimple_op_ptr (gs, 1);
 }

 /* Set NEW_TYPE to be the type returned by GIMPLE_CHANGE_DYNAMIC_TYPE
@@ -3352,7 +3530,8 @@ static inline void
 gimple_cdt_set_new_type (gimple gs, tree new_type)
 {
   GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
-  gs->gimple_change_dynamic_type.type = new_type;
+  gcc_assert (TREE_CODE_CLASS (TREE_CODE (new_type)) == tcc_type);
+  gimple_set_op (gs, 1, new_type);
 }


Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 136344)
+++ tree-cfg.c	(working copy)
@@ -6138,7 +6138,7 @@ gimple_block_ends_with_call_p (basic_blo
 static bool
 gimple_block_ends_with_condjump_p (const_basic_block bb)
 {
-  gimple stmt = last_stmt ((basic_block) bb);
+  gimple stmt = last_stmt (CONST_CAST_BB (bb));
   return (stmt && gimple_code (stmt) == GIMPLE_COND);
 }

Index: tree-ssa-operands.c
===================================================================
--- tree-ssa-operands.c	(revision 136344)
+++ tree-ssa-operands.c	(working copy)
@@ -74,6 +74,11 @@ along with GCC; see the file COPYING3.
    operand vector for VUSE, then the new vector will also be modified
    such that it contains 'a_5' rather than 'a'.  */

+/* Helper functions from gimple.c.  These are GIMPLE manipulation
+   routines that only the operand scanner should need.  */
+void gimple_set_stored_syms (gimple, bitmap, bitmap_obstack *);
+void gimple_set_loaded_syms (gimple, bitmap, bitmap_obstack *);
+
 /* Structure storing statistics on how many call clobbers we have, and
    how many where avoided.  */

@@ -769,48 +774,6 @@ finalize_ssa_uses (gimple stmt)
 }


-/* Make SYMS be the set of symbols stored by STMT.  If SYMS is NULL or
-   empty, the storage used is freed up.  */
-
-static void
-gimple_set_stored_syms (gimple stmt, bitmap syms)
-{
-  gcc_assert (gimple_has_mem_ops (stmt));
-
-  if (syms == NULL)
-    BITMAP_FREE (stmt->with_mem_ops.stores);
-  else
-    {
-      if (stmt->with_mem_ops.stores == NULL)
-	stmt->with_mem_ops.stores = BITMAP_ALLOC (&operands_bitmap_obstack);
-
-      bitmap_copy (stmt->with_mem_ops.stores, syms);
-    }
-}
-
-
-/* Deep copy SYMS into the set of symbols loaded by STMT.  If SYMS is
-   NULL or empty, the storage used is freed up.  */
-
-static void
-gimple_set_loaded_syms (gimple stmt, bitmap syms)
-{
-  gcc_assert (gimple_has_mem_ops (stmt));
-
-  if (syms == NULL)
-    BITMAP_FREE (stmt->with_mem_ops.loads);
-  else
-    {
-      if (stmt->with_mem_ops.loads == NULL)
-	stmt->with_mem_ops.loads = BITMAP_ALLOC (&operands_bitmap_obstack);
-
-      bitmap_copy (stmt->with_mem_ops.loads, syms);
-    }
-}
-
-
-
-
 /* Takes elements from BUILD_VDEFS and turns them into vdef operands of
    STMT.  */

@@ -822,7 +785,7 @@ finalize_ssa_vdefs (gimple stmt)
   voptype_p old_ops, ptr, last;

   /* Set the symbols referenced by STMT.  */
-  gimple_set_stored_syms (stmt, build_stores);
+  gimple_set_stored_syms (stmt, build_stores, &operands_bitmap_obstack);

   /* If aliases have not been computed, do not instantiate a virtual
      operator on STMT.  Initially, we only compute the SSA form on
@@ -917,7 +880,7 @@ finalize_ssa_vuse_ops (gimple stmt)
   VEC(tree,heap) *new_ops;

   /* Set the symbols referenced by STMT.  */
-  gimple_set_loaded_syms (stmt, build_loads);
+  gimple_set_loaded_syms (stmt, build_loads, &operands_bitmap_obstack);

   /* If aliases have not been computed, do not instantiate a virtual
      operator on STMT.  Initially, we only compute the SSA form on
@@ -2295,12 +2258,12 @@ free_stmt_operands (gimple stmt)
     }

   if (gimple_has_ops (stmt))
-    BITMAP_FREE (stmt->with_ops.addresses_taken);
+    gimple_set_addresses_taken (stmt, NULL);

   if (gimple_has_mem_ops (stmt))
     {
-      gimple_set_stored_syms (stmt, NULL);
-      gimple_set_loaded_syms (stmt, NULL);
+      gimple_set_stored_syms (stmt, NULL, &operands_bitmap_obstack);
+      gimple_set_loaded_syms (stmt, NULL, &operands_bitmap_obstack);
     }
 }

@@ -2342,8 +2305,10 @@ copy_virtual_operands (gimple dest, gimp
   gimple_set_vdef_ops (dest, NULL);
   gimple_set_vuse_ops (dest, NULL);

-  gimple_set_stored_syms (dest, gimple_stored_syms (src));
-  gimple_set_loaded_syms (dest, gimple_loaded_syms (src));
+  gimple_set_stored_syms (dest, gimple_stored_syms (src),
+			  &operands_bitmap_obstack);
+  gimple_set_loaded_syms (dest, gimple_loaded_syms (src),
+			  &operands_bitmap_obstack);

   /* Copy all the VUSE operators and corresponding operands.  */
   dest_vuses = &vuse;
@@ -2512,7 +2477,7 @@ void
 gimple_add_to_addresses_taken (gimple stmt, tree ref)
 {
   gcc_assert (gimple_has_ops (stmt));
-  add_to_addressable_set (ref, &stmt->with_ops.addresses_taken);
+  add_to_addressable_set (ref, gimple_addresses_taken_ptr (stmt));
 }

Attachment: spec2k-comparison.txt
Description: Text document

Attachment: cc1-i-files-comparison.txt
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]