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]

[lto]: PATCH committed to process ssa gimple.


With this patch it is now possible to process this function:

extern int foo (int);

int foo (int a)
{
return a * 6;
}

By this i mean that the function can be compiled using the command:
./xgcc -c -O2 -flto ../../gccLTO/gcc/test2.c -o test2.o

and the output can be later processed by

./lto1 -O2 test2.o -o test2o.o

and we construct test2o.o without core dumping.

Note the lack of an assertion that the code in test2o.o is correct.

This patch creates a new variable in_lto_p which is true if called from
the lto front end. This is used to gate the passes that would normally
be run before the point where the lto code is written in the first step.

This patch is large because the point where we are both reading and
writing the lto code is after ssa form has been created. This not only
required that ssa form be supported, but required that the cfg be
processed first in order to build the phi function data structures.

Note that while the above program seems to work, the following program
does not.



extern int foo (void);

int foo (void)
{
int a = 2;
return a * 6;
}

the lto pass seems to blow up in mark's code with the message
test.o:0: fatal error: ELF symbol table does not contain ‘a’
compilation terminated.

This is most likely a nit and there are most certainly nits of
equivalent complexity in my code.

At this point, we should be reading and writing enough gimple to compile
c as long as there are no exception regions. As pointed out, while the
code is there, it is grossly undertested. What i do not know is if
enough of the types are being processed to try non trivial examples.

2007-07-13 Kenneth Zadeck <zadeck@naturalbridge.com>

* flags.h (in_lto_p): New flag.
* lto-tree_flags.def (CHANGE_DYNAMIC_TYPE_EXPR, POINTER_PLUS_EXPR):
New tree codes from merge.
* tree.h (init_ssanames): Added cfun parameter.
* lto-function-out.c: (ssa_names_stream, cfg_stream): New streams.
(output_eh_regions): Renamed parameter cfun to fn.
(output_expr_operand): Implemented SSA_NAME and GIMPLE_MODIFY_STMT
cases.
(output_local_vars): Set the local_vars stream locally.
(output_ssa_names, output_cfg, output_phi): New function.
(output_bb): Changed the cfun parameter to fn. Do not put out cfg
locally. Output the phi_functions.
(produce_asm): Add code to support ssa_names and cfg streams.
(lto_static_init): Added GIMPLE_MODIFY_STMT.
(LTO_SET_DEBUGGING_STREAM): New macro.
(output_function): Add code to support ssa_names and cfg streams.
* toplev.c (in_lto_p): Initialize.
* ipa-inline.c (cgraph_gate_ipa_early_inlining): Added test for
in_lto_p.
* lto-tree-tags.def (GIMPLE_MODIFY_STMT, PHI_NODE): New tags.
(LTO_change_dynamic_type_expr, LTO_gimple_modify_stmt,
LTO_phi_node, LTO_pointer_plus_expr): New names.
lto-tags.h (ssa_names_size, cfg_size, debug_ssa_names_size,
debug_cfg_size): New fields in lto_function_header.
(LTO_change_dynamic_type_expr, LTO_gimple_modify_stmt,
LTO_phi_node, LTO_pointer_plus_expr): New fields and renumbered
the rest.
(ssa_names_data, cfg_data): New fields of lto_debug_context.
* ipa.c (flags.h): New include.
(gate_ipa_fun_and_var_visibility): New function for
pass_ipa_function_and_variable_visibility.
* tree-ssa.c (init_tree_ssa): Add fn parameter and replaced refs
to cfun.
* tree-inline.c (initialize_cfun): Ditto.
* tree-optimize.c (gate_all_early_local_passes): Added ref to
in_ltp_p.
(execute_init_datastructures): Added cfun parameter to
init_tree_ssa.
* tree-flow.h (init_tree_ssa): Added struct function parameter.
* Makefile.in (ipa.o): Added FLAGS_H dependency.
* tree-ssanames.c (init_ssanames): Added two parameters. Now
takes struct function and default size.



2007-07-13 Kenneth Zadeck <zadeck@naturalbridge.com>

* lto-read.c (input_list, input_expr_operand): Added struct
function parameter.
(init_cfg, finalize_cfg): Removed function.
(input_expr_operand): Added SSA_NAME and GIMPLE_MODIFY_STMT cases.
(input_labels, input_local_vars): Now takes input_block parameter rather
than
synthsyzing it.
(input_cfg, input_phi, input_ssa_names): New functions.
(input_bb): Now passes in input_blocks. Does not construct cfg
and processes the list of phi functions.
(input_function): Now builds both the cfg and ssa_names table.
(lto_read_function_body): Processes new header fields to construct
streams for the ssa_names and cfg and their debugging.
* lto/lto-lang.c (lto_init): Set in_lto_p.

This has been committed to the lto branch as revision 126627.

Kenny

Index: flags.h
===================================================================
--- flags.h	(revision 126565)
+++ flags.h	(working copy)
@@ -111,6 +111,13 @@ extern int optimize;
 
 extern int optimize_size;
 
+/* True if this is the lto front end.  This is used to disable
+   gimple generation and lowering passes that are normally run on the
+   output of a front end.  These passes must be bypassed for lto since
+   they have already been done before the gimple was written.  */ 
+
+extern bool in_lto_p;
+
 /* Do print extra warnings (such as for uninitialized variables).
    -W/-Wextra.  */
 
Index: lto-tree-flags.def
===================================================================
--- lto-tree-flags.def	(revision 126565)
+++ lto-tree-flags.def	(working copy)
@@ -218,6 +218,9 @@
     START_EXPR_CASE (CEIL_MOD_EXPR)
     END_EXPR_CASE (CEIL_MOD_EXPR)
       
+    START_EXPR_CASE (CHANGE_DYNAMIC_TYPE_EXPR)
+    END_EXPR_CASE (CHANGE_DYNAMIC_TYPE_EXPR)
+
     START_EXPR_CASE (CLEANUP_POINT_EXPR)
     END_EXPR_CASE (CLEANUP_POINT_EXPR)
       
@@ -508,6 +511,9 @@
       
     START_EXPR_CASE (PLUS_EXPR)
     END_EXPR_CASE (PLUS_EXPR)
+
+    START_EXPR_CASE (POINTER_PLUS_EXPR)
+    END_EXPR_CASE (POINTER_PLUS_EXPR)
       
     START_EXPR_CASE (POINTER_TYPE)
       ADD_EXPR_FLAG (static_flag)
Index: tree.h
===================================================================
--- tree.h	(revision 126565)
+++ tree.h	(working copy)
@@ -3695,7 +3695,7 @@ extern void release_phi_node (tree);
 extern void phinodes_print_statistics (void);
 #endif
 
-extern void init_ssanames (void);
+extern void init_ssanames (struct function *, int);
 extern void fini_ssanames (void);
 extern tree make_ssa_name (tree, tree);
 extern tree duplicate_ssa_name (tree, tree);
Index: lto-function-out.c
===================================================================
--- lto-function-out.c	(revision 126565)
+++ lto-function-out.c	(working copy)
@@ -216,12 +216,21 @@ struct output_block
   struct output_stream *named_label_stream;
   /* The stream that contains the string table.  */
   struct output_stream *string_stream;
+  /* The stream that contains the ssa_names table.  */
+  struct output_stream *ssa_names_stream;
+  /* The stream that contains the cfg.  */
+  struct output_stream *cfg_stream;
+
 #ifdef LTO_STREAM_DEBUGGING
-  /* The stream that contains the stream debugging information.  */
+  /* The stream that contains the local decls debugging information.  */
   struct output_stream *debug_decl_stream;
-  /* The stream that contains the stream debugging information.  */
+  /* The stream that contains the labels debugging information.  */
   struct output_stream *debug_label_stream;
-  /* The stream that contains the stream debugging information.  */
+  /* The stream that contains the ssa_names debugging information.  */
+  struct output_stream *debug_ssa_names_stream;
+  /* The stream that contains the cfg debugging information.  */
+  struct output_stream *debug_cfg_stream;
+  /* The stream that contains the gimple debugging information.  */
   struct output_stream *debug_main_stream;
 #endif
 
@@ -934,12 +943,12 @@ output_eh_must_not_throw (void *obv,
 /* Output the existing eh_table to OB.  */
 
 static void
-output_eh_regions (struct output_block *ob, struct function *cfun)
+output_eh_regions (struct output_block *ob, struct function *fn)
 {
-  if (0 && cfun->eh)
+  if (0 && fn->eh)
     {
       output_record_start (ob, NULL, NULL, LTO_eh_table);
-      output_eh_records (ob, cfun,
+      output_eh_records (ob, fn,
 			 output_eh_cleanup,
 			 output_eh_try,
 			 output_eh_catch,
@@ -1104,15 +1113,8 @@ output_expr_operand (struct output_block
       break;
 
     case SSA_NAME:
-      /* FIXME: I am dead sure that this code is wrong for SSA
-	 names. But lto output is currently being done before SSA form
-	 is built so we can just fix it later.  */
       output_record_start (ob, expr, expr, LTO_ssa_name);
-      output_local_decl_ref (ob, SSA_NAME_VAR (expr));
       output_uleb128 (ob, SSA_NAME_VERSION (expr));
-
-      /* Just to make sure that the comment above is headed.  */
-      gcc_unreachable ();
       break;
 
     case CONST_DECL:
@@ -1319,6 +1321,12 @@ output_expr_operand (struct output_block
       }
       break;
 
+    case GIMPLE_MODIFY_STMT:
+      output_record_start (ob, expr, NULL, tag);
+      output_expr_operand (ob, GIMPLE_STMT_OPERAND (expr, 0));
+      output_expr_operand (ob, GIMPLE_STMT_OPERAND (expr, 1));
+      break;
+
     case SWITCH_EXPR:
       {
 	tree label_vec = TREE_OPERAND (expr, 2);
@@ -1391,9 +1399,20 @@ output_local_vars (struct output_block *
 {
   unsigned int index = 0;
 
-#ifdef LTO_STREAM_DEBUGGING
-  lto_debug_context.current_data = ob->debug_decl_stream;
-#endif
+  /* We have found MOST of the local vars by scanning the function.
+     There is always the possibility that there may be some lurking on
+     the fields (such as the two size fields) of the local vars that
+     we must put out.
+
+     The easiest way to get all of this stuff generated is to play
+     pointer games with the streams and reuse the code for putting out
+     the function bodies for putting out the local decls.  It needs to
+     go into a separate stream because the LTO reader will want to
+     process the local variables first, rather than have to back patch
+     them.
+  */
+  struct output_stream *tmp_stream = ob->main_stream;
+  ob->main_stream = ob->local_decl_stream;
 
   while (index < VEC_length (tree, ob->local_decls))
     {
@@ -1457,6 +1476,8 @@ output_local_vars (struct output_block *
 
       LTO_DEBUG_UNDENT()
     }
+
+  ob->main_stream = tmp_stream;
 }
 
 
@@ -1467,10 +1488,6 @@ output_named_labels (struct output_block
 {
   unsigned int index = 0;
 
-#ifdef LTO_STREAM_DEBUGGING
-  lto_debug_context.current_data = ob->debug_label_stream;
-#endif
-
   while (index < VEC_length (tree, ob->named_labels))
     {
       tree decl = VEC_index (tree, ob->named_labels, index++);
@@ -1482,37 +1499,116 @@ output_named_labels (struct output_block
 }
 
 
-/* Output a basic block BB to the main stream in OB for this CFUN.  */
+/* Output all of the active ssa names to the ssa_names stream.  */
+
+static void
+output_ssa_names (struct output_block *ob, struct function *fn)
+{
+  /* Switch streams so we can use output_expr_operand to write the
+     SSA_NAME_VAR.  */
+  struct output_stream *tmp_stream = ob->main_stream;
+  unsigned int i;
+  unsigned int len = VEC_length (tree, SSANAMES (fn));
+
+  ob->main_stream = ob->ssa_names_stream;
+
+  output_uleb128 (ob, len);
+
+  for (i = 1; i < len; i++)
+    {
+      tree ptr = VEC_index (tree, SSANAMES (fn), i);
+
+      if (ptr == NULL_TREE || SSA_NAME_IN_FREE_LIST (ptr))
+	continue;
+
+      output_uleb128 (ob, i);
+      output_expr_operand (ob, SSA_NAME_VAR (ptr));
+    }
+
+  output_uleb128 (ob, 0);
+  ob->main_stream = tmp_stream;
+}
+
+
+/* Output the cfg.  */
+
+static void
+output_cfg (struct output_block *ob, struct function *fn)
+{
+  struct output_stream *tmp_stream = ob->main_stream;
+  basic_block bb;
+
+  ob->main_stream = ob->cfg_stream;
+
+  /* Output the number of the highest basic block.  */
+  LTO_DEBUG_TOKEN ("lastbb")
+  output_uleb128 (ob, last_basic_block_for_function(fn));
+
+  FOR_ALL_BB_FN (bb, fn)
+    {
+      edge_iterator ei;
+      edge e;
+
+      LTO_DEBUG_TOKEN ("bbindex")
+      output_sleb128 (ob, bb->index);
+
+      /* Output the successors and the edge flags.  */
+      LTO_DEBUG_TOKEN ("edgecount")
+      output_uleb128 (ob, EDGE_COUNT (bb->succs));
+      FOR_EACH_EDGE (e, ei, bb->succs)
+	{
+	  LTO_DEBUG_TOKEN ("dest")
+	  output_uleb128 (ob, e->dest->index);
+	  LTO_DEBUG_TOKEN ("eflags")
+	  output_uleb128 (ob, e->flags);
+	}
+    }
+
+  LTO_DEBUG_TOKEN ("bbindex")
+  output_sleb128 (ob, -1);
+  ob->main_stream = tmp_stream;
+}
+
+
+/* Output a phi function to the main stream in OB.  */
+
+static void
+output_phi (struct output_block *ob, tree expr)
+{
+  int len = PHI_NUM_ARGS (expr);
+  int i;
+  
+  output_record_start (ob, expr, NULL, LTO_phi_node);
+  output_uleb128 (ob, SSA_NAME_VERSION (PHI_RESULT (expr)));
+  
+  for (i = 0; i < len; i++)
+    {
+      output_uleb128 (ob, SSA_NAME_VERSION (PHI_ARG_DEF (expr, i)));
+      output_uleb128 (ob, PHI_ARG_EDGE (expr, i)->src->index);
+    }
+}
+
+
+/* Output a basic block BB to the main stream in OB for this FN.  */
 
 static void
-output_bb (struct output_block *ob, basic_block bb, struct function *cfun)
+output_bb (struct output_block *ob, basic_block bb, struct function *fn)
 {
-  edge e;
-  edge_iterator ei;
   block_stmt_iterator bsi = bsi_start (bb);
 
   output_record_start (ob, NULL, NULL,
-		       bsi_end_p (bsi) ? LTO_bb0 : LTO_bb1);
+		       (!bsi_end_p (bsi)) || phi_nodes (bb) ? LTO_bb1 : LTO_bb0);
 
   /* The index of the basic block.  */
   LTO_DEBUG_TOKEN ("bbindex")
   output_uleb128 (ob, bb->index);
 
-  /* Output the successors and the edge flags.  */
-  LTO_DEBUG_TOKEN ("edgecount")
-  output_uleb128 (ob, EDGE_COUNT (bb->succs));
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    {
-      LTO_DEBUG_TOKEN ("dest")
-      output_uleb128 (ob, e->dest->index);
-      LTO_DEBUG_TOKEN ("eflags")
-      output_uleb128 (ob, e->flags);
-    }
-
-  if (!bsi_end_p (bsi))
+  if ((!bsi_end_p (bsi)) || phi_nodes (bb))
     {
       /* Output the statements.  The list of statements is terminated
 	 with a zero.  */
+      tree phi;
+
       for (bsi = bsi_start (bb);
 	   !bsi_end_p (bsi); bsi_next (&bsi))
 	{
@@ -1526,7 +1622,7 @@ output_bb (struct output_block *ob, basi
 	     last region number we set.  */
 	  if (0 && tree_could_throw_p (stmt))
 	    {
-	      int region = lookup_stmt_eh_region_fn (cfun, stmt);
+	      int region = lookup_stmt_eh_region_fn (fn, stmt);
 	      if (region != last_eh_region_seen)
 		{
 		  output_record_start (ob, NULL, NULL,
@@ -1541,7 +1637,17 @@ output_bb (struct output_block *ob, basi
 
       LTO_DEBUG_INDENT_TOKEN ("stmt")
       output_zero (ob);
+
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+	{
+	  LTO_DEBUG_INDENT_TOKEN ("phi")
+	  output_phi (ob, phi);
+	}
+
+      LTO_DEBUG_INDENT_TOKEN ("phi")
+      output_zero (ob);
     }
+
   LTO_DEBUG_UNDENT()
 }
 
@@ -1577,16 +1683,22 @@ produce_asm (struct output_block *ob, tr
 
   function_header.compressed_size = 0;
   function_header.named_label_size = ob->named_label_stream->total_size;
+  function_header.ssa_names_size = ob->ssa_names_stream->total_size;
+  function_header.cfg_size = ob->cfg_stream->total_size;
   function_header.local_decls_size = ob->local_decl_stream->total_size;
   function_header.main_size = ob->main_stream->total_size;
   function_header.string_size = ob->string_stream->total_size;
 #ifdef LTO_STREAM_DEBUGGING
   function_header.debug_decl_size = ob->debug_decl_stream->total_size;
   function_header.debug_label_size = ob->debug_label_stream->total_size;
+  function_header.debug_ssa_names_size = ob->debug_ssa_names_stream->total_size;
+  function_header.debug_cfg_size = ob->debug_cfg_stream->total_size;
   function_header.debug_main_size = ob->debug_main_stream->total_size;
 #else
   function_header.debug_decl_size = -1;
   function_header.debug_label_size = -1;
+  function_header.debug_ssa_names_size = -1;
+  function_header.debug_cfg_size = -1;
   function_header.debug_main_size = -1;
 #endif
 
@@ -1604,8 +1716,7 @@ produce_asm (struct output_block *ob, tr
       out_ref.label = "0";
 #endif
       dw2_asm_output_data (8, out_ref.section, " ");
-      dw2_asm_output_delta (8, out_ref.label,
-			    out_ref.base_label, " ");
+      dw2_asm_output_delta (8, out_ref.label, out_ref.base_label, " ");
     }
 
   /* Write the global type references.  */
@@ -1644,12 +1755,16 @@ produce_asm (struct output_block *ob, tr
   /* Put all of the gimple and the string table out the asm file as a
      block of text.  */
   write_stream (ob->named_label_stream);
+  write_stream (ob->ssa_names_stream);
+  write_stream (ob->cfg_stream);
   write_stream (ob->local_decl_stream);
   write_stream (ob->main_stream);
   write_stream (ob->string_stream);
 #ifdef LTO_STREAM_DEBUGGING
   write_stream (ob->debug_decl_stream);
   write_stream (ob->debug_label_stream);
+  write_stream (ob->debug_ssa_names_stream);
+  write_stream (ob->debug_cfg_stream);
   write_stream (ob->debug_main_stream);
 #endif
 }
@@ -1685,6 +1800,7 @@ lto_static_init (void)
   sbitmap_ones (lto_types_needed_for);
   RESET_BIT (lto_types_needed_for, ASM_EXPR);
   RESET_BIT (lto_types_needed_for, CASE_LABEL_EXPR);
+  RESET_BIT (lto_types_needed_for, GIMPLE_MODIFY_STMT);
   RESET_BIT (lto_types_needed_for, LABEL_DECL);
   RESET_BIT (lto_types_needed_for, LABEL_EXPR);
   RESET_BIT (lto_types_needed_for, MODIFY_EXPR);
@@ -1746,30 +1862,34 @@ lto_static_init_local (void)
 static int function_num;
 #endif
 
-/* Output CFUN.  */
+#ifdef LTO_STREAM_DEBUGGING
+#define LTO_SET_DEBUGGING_STREAM(STREAM,CONTEXT)	\
+{ \
+  ob-> STREAM = xcalloc (1, sizeof (struct output_stream)); \
+  lto_debug_context. CONTEXT = ob-> STREAM; \
+  lto_debug_context.current_data = ob-> STREAM; \
+}
+#else
+#define LTO_SET_DEBUGGING_STREAM(STREAM,CONTEXT)
+#endif
+
+/* Output FN.  */
 
 static void
 output_function (tree function)
 {
-  struct function *this_cfun = DECL_STRUCT_FUNCTION (function);
+  struct function *fn = DECL_STRUCT_FUNCTION (function);
   basic_block bb;
-  struct output_stream *tmp_stream;
-
   struct output_block *ob = xcalloc (1, sizeof (struct output_block));
+
   ob->main_stream = xcalloc (1, sizeof (struct output_stream));
   ob->string_stream = xcalloc (1, sizeof (struct output_stream));
   ob->local_decl_stream = xcalloc (1, sizeof (struct output_stream));
   ob->named_label_stream = xcalloc (1, sizeof (struct output_stream));
+  ob->ssa_names_stream = xcalloc (1, sizeof (struct output_stream));
+  ob->cfg_stream = xcalloc (1, sizeof (struct output_stream));
 #ifdef LTO_STREAM_DEBUGGING
-  ob->debug_decl_stream = xcalloc (1, sizeof (struct output_stream));
-  ob->debug_label_stream = xcalloc (1, sizeof (struct output_stream));
-  ob->debug_main_stream = xcalloc (1, sizeof (struct output_stream));
-  
-  lto_debug_context.out = &debug_out_fun;
-  lto_debug_context.decl_data = ob->debug_decl_stream;
-  lto_debug_context.label_data = ob->debug_label_stream;
-  lto_debug_context.main_data = ob->debug_main_stream;
-  lto_debug_context.current_data = ob->debug_main_stream;
+  lto_debug_context.out = debug_out_fun;
   lto_debug_context.indent = 0;
 #endif
 
@@ -1797,6 +1917,9 @@ output_function (tree function)
 
   /* The unnamed labels must all be negative.  */
   ob->next_unnamed_label_index = -1;
+
+  LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data)
+
   /* Make string 0 be a NULL string.  */
   output_1_stream (ob->string_stream, 0);
 
@@ -1805,38 +1928,27 @@ output_function (tree function)
   output_record_start (ob, NULL, NULL, LTO_function);
 
   /* Output any exception-handling regions.  */
-  output_eh_regions (ob, this_cfun);
-
-  /* Output the number of the highest basic block.  */
-  output_uleb128 (ob, last_basic_block_for_function(this_cfun));
+  output_eh_regions (ob, fn);
 
   /* Output the code for the function.  */
-  FOR_ALL_BB_FN (bb, this_cfun)
-    output_bb (ob, bb, this_cfun);
+  FOR_ALL_BB_FN (bb, fn)
+    output_bb (ob, bb, fn);
 
   /* The terminator for this function.  */
   output_zero (ob);
   LTO_DEBUG_UNDENT()
 
-  /* We have found MOST of the local vars by scanning the function.
-     There is always the possibility that there may be some lurking on
-     the fields (such as the two size fields) of the local vars that
-     we must put out.
+  LTO_SET_DEBUGGING_STREAM (debug_label_stream, label_data)
+  output_named_labels (ob);
 
-     The easiest way to get all of this stuff generated is to play
-     pointer games with the streams and reuse the code for putting out
-     the function bodies for putting out the local decls.  It needs to
-     go into a separate stream because the LTO reader will want to
-     process the local variables first, rather than have to back patch
-     them.
-  */
-  tmp_stream = ob->main_stream;
-  ob->main_stream = ob->local_decl_stream;
-  output_local_vars (ob);
-  ob->main_stream = tmp_stream;
+  LTO_SET_DEBUGGING_STREAM (debug_ssa_names_stream, ssa_names_data)
+  output_ssa_names (ob, fn);
 
-  /* Output the names in the named labels.  */
-  output_named_labels (ob);
+  LTO_SET_DEBUGGING_STREAM (debug_cfg_stream, cfg_data)
+  output_cfg (ob, fn);
+
+  LTO_SET_DEBUGGING_STREAM (debug_decl_stream, decl_data)
+  output_local_vars (ob);
 
   /* Create a file to hold the pickled output of this function.  This
      is a temp standin until we start writing sections.  */
Index: toplev.c
===================================================================
--- toplev.c	(revision 126565)
+++ toplev.c	(working copy)
@@ -222,6 +222,13 @@ int optimize = 0;
 
 int optimize_size = 0;
 
+/* True if this is the lto front end.  This is used to disable
+   gimple generation and lowering passes that are normally run on the
+   output of a front end.  These passes must be bypassed for lto since
+   they have already been done before the gimple was written.  */ 
+
+bool in_lto_p = false;
+
 /* The FUNCTION_DECL for the function currently being compiled,
    or 0 if between functions.  */
 tree current_function_decl;
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 126565)
+++ ipa-inline.c	(working copy)
@@ -1492,6 +1492,7 @@ static bool
 cgraph_gate_ipa_early_inlining (void)
 {
   return (flag_inline_trees && flag_early_inlining
+	  && !in_lto_p
 	  && (flag_branch_probabilities || flag_test_coverage
 	      || profile_arc_flag));
 }
Index: lto-tree-tags.def
===================================================================
--- lto-tree-tags.def	(revision 126565)
+++ lto-tree-tags.def	(working copy)
@@ -70,10 +70,12 @@
   MAP_EXPR_TAG(CONSTRUCTOR, LTO_constructor)
   MAP_EXPR_TAG(FIELD_DECL, LTO_field_decl)
   MAP_EXPR_TAG(FUNCTION_DECL, LTO_function_decl)
+  MAP_EXPR_TAG(GIMPLE_MODIFY_STMT, LTO_gimple_modify_stmt)
   MAP_EXPR_TAG(INTEGER_CST, LTO_integer_cst)
   MAP_EXPR_TAG(LABEL_DECL, LTO_label_decl)
   MAP_EXPR_TAG(LABEL_EXPR, LTO_label_expr)
   MAP_EXPR_TAG(PARM_DECL, LTO_parm_decl)
+  MAP_EXPR_TAG(PHI_NODE, LTO_phi_node)
   MAP_EXPR_TAG(RANGE_EXPR, LTO_range_expr)
   MAP_EXPR_TAG(REAL_CST, LTO_real_cst)
   MAP_EXPR_TAG(RESULT_DECL, LTO_result_decl)
@@ -188,6 +190,7 @@
   SET_NAME (LTO_case_label_expr3, "case_label_expr3")
   SET_NAME (LTO_ceil_div_expr, "ceil_div_expr")
   SET_NAME (LTO_ceil_mod_expr, "ceil_mod_expr")
+  SET_NAME (LTO_change_dynamic_type_expr, "change_dynamic_type_expr")
   SET_NAME (LTO_complex_cst0, "complex_cst0")
   SET_NAME (LTO_complex_cst1, "complex_cst1")
   SET_NAME (LTO_complex_expr, "complex_expr")
@@ -211,6 +214,7 @@
   SET_NAME (LTO_floor_mod_expr, "floor_mod_expr")
   SET_NAME (LTO_function_decl, "function_decl")
   SET_NAME (LTO_ge_expr, "ge_expr")
+  SET_NAME (LTO_gimple_modify_stmt, "gimple_modify_stmt")
   SET_NAME (LTO_goto_expr, "goto_expr")
   SET_NAME (LTO_gt_expr, "gt_expr")
   SET_NAME (LTO_imagpart_expr, "imagpart_expr")
@@ -236,6 +240,8 @@
   SET_NAME (LTO_obj_type_ref, "obj_type_ref")
   SET_NAME (LTO_ordered_expr, "ordered_expr")
   SET_NAME (LTO_parm_decl, "parm_decl")
+  SET_NAME (LTO_phi_node, "phi_node")
+  SET_NAME (LTO_pointer_plus_expr, "pointer_plus_expr")
   SET_NAME (LTO_plus_expr, "plus_expr")
   SET_NAME (LTO_range_expr, "range_expr")
   SET_NAME (LTO_rdiv_expr, "rdiv_expr")
Index: lto-tags.h
===================================================================
--- lto-tags.h	(revision 126565)
+++ lto-tags.h	(working copy)
@@ -45,10 +45,12 @@
    4) global VAR_DECLS.
    5) types.
    6) Names for the labels that have names
-   7) Gimple for local decls.
-   8) Gimple for the function.
-   9) Strings.
-   10-12)Redundant information to aid in debugging the stream.
+   7) The ssa names.
+   8) The control flow graph.
+   9) Gimple for local decls.
+   10)Gimple for the function.
+   11)Strings.
+   12-14)Redundant information to aid in debugging the stream.
       This is only present if the compiler is built with
       LTO_STREAM_DEBUGGING defined.
 
@@ -61,35 +63,39 @@
 /* The is the first part of the record for a function in the .o file.  */
 struct lto_function_header
 {
-  int16_t major_version;      /* LTO_major_version. */
-  int16_t minor_version;      /* LTO_minor_version. */
-  int32_t num_field_decls;    /* Number of FIELD_DECLS.  */
-  int32_t num_fn_decls;       /* Number of FUNCTION_DECLS.  */
-  int32_t num_var_decls;      /* Number of non local VAR_DECLS.  */
-  int32_t num_types;          /* Number of types.  */
-  int32_t num_local_decls;    /* Number of local VAR_DECLS and PARM_DECLS.  */
-  int32_t num_named_labels;   /* Number of labels with names.  */
-  int32_t num_unnamed_labels; /* Number of labels without names.  */
-  int32_t compressed_size;    /* Size compressed or 0 if not compressed.  */
-  int32_t named_label_size;   /* Size of names for named labels.  */
-  int32_t local_decls_size;   /* Size of local par and var decl region. */
-  int32_t main_size;          /* Size of main gimple body of function.  */
-  int32_t string_size;        /* Size of the string table.  */
-  int32_t debug_decl_size;   /* Size of local decl debugging information.  */
-  int32_t debug_label_size;   /* Size of label stream debugging information.  */
-  int32_t debug_main_size;    /* Size of main stream debugging information.  */
+  int16_t major_version;          /* LTO_major_version. */
+  int16_t minor_version;          /* LTO_minor_version. */
+  int32_t num_field_decls;        /* Number of FIELD_DECLS.  */
+  int32_t num_fn_decls;           /* Number of FUNCTION_DECLS.  */
+  int32_t num_var_decls;          /* Number of non local VAR_DECLS.  */
+  int32_t num_types;              /* Number of types.  */
+  int32_t num_local_decls;        /* Number of local VAR_DECLS and PARM_DECLS.  */
+  int32_t num_named_labels;       /* Number of labels with names.  */
+  int32_t num_unnamed_labels;     /* Number of labels without names.  */
+  int32_t compressed_size;        /* Size compressed or 0 if not compressed.  */
+  int32_t named_label_size;       /* Size of names for named labels.  */
+  int32_t ssa_names_size;         /* Size of the SSA_NAMES table.  */
+  int32_t cfg_size;               /* Size of the cfg.  */
+  int32_t local_decls_size;       /* Size of local par and var decl region. */
+  int32_t main_size;              /* Size of main gimple body of function.  */
+  int32_t string_size;            /* Size of the string table.  */
+  int32_t debug_decl_size;        /* Size of local decl debugging information.  */
+  int32_t debug_label_size;       /* Size of label stream debugging information.  */
+  int32_t debug_ssa_names_size;   /* Size of ssa_names stream debugging information.  */
+  int32_t debug_cfg_size;         /* Size of cfg stream debugging information.  */
+  int32_t debug_main_size;        /* Size of main stream debugging information.  */
 };
 
 /* 2-5) THE GLOBAL DECLS AND TYPES.
 
-     The global decls and types are encoded in the same way.  For each
-     entry, there is a pair of words.  The first is the debugging
-     section number and the second is the offset within the section to
-     the entry.
-
-     FIXME: This encoding may change change so that the first word is
-     a label for the debugging section.  This will cause more work for
-     the linker but will make ln -r work properly.
+      The global decls and types are encoded in the same way.  For each
+      entry, there is a pair of words.  The first is the debugging
+      section number and the second is the offset within the section to
+      the entry.
+
+      FIXME: This encoding may change change so that the first word is
+      a label for the debugging section.  This will cause more work for
+      the linker but will make ln -r work properly.
 
    6) THE LABEL NAMES.  
 
@@ -100,7 +106,14 @@ struct lto_function_header
       the negative ones do not.  The positive index can be used to
       find the name in this array.
 
-   7-8) GIMPLE FOR THE LOCAL DECLS AND THE FUNCTION BODY.
+   7) THE ACTIVE SSA NAMES.  
+
+      The SSA_NAME_VERSION in an SSA_NAME in used as an index into
+      this table.
+
+   8) THE CFG. 
+
+   9-10) GIMPLE FOR THE LOCAL DECLS AND THE FUNCTION BODY.
 
      The gimple consists of a set of records.
 
@@ -211,12 +224,12 @@ struct lto_function_header
 			  to terminate the statements and exception
 			  regions within this block.
 
-   9) STRINGS
+   11) STRINGS
 
      String are represented in the table as pairs, a length in ULEB128
      form followed by the data for the string.
 
-   10) STREAM DEBUGGING
+   12) STREAM DEBUGGING
      
      If the preprocessor symbol LTO_STREAM_DEBUGGING is defined, the
      gimple is encoded into .o file as two streams.  The first stream
@@ -275,143 +288,147 @@ struct lto_function_header
 #define LTO_case_label_expr3            0x017
 #define LTO_ceil_div_expr               0x018
 #define LTO_ceil_mod_expr               0x019
+#define LTO_change_dynamic_type_expr    0x01A
 /* 1 if the elements are reals and 0 if the elements are ints.  */
-#define LTO_complex_cst0                0x01A
-#define LTO_complex_cst1                0x01B
-#define LTO_complex_expr                0x01C
-#define LTO_component_ref               0x01D
-#define LTO_compound_expr               0x01E
-#define LTO_cond_expr                   0x01F
-#define LTO_conj_expr                   0x020
-#define LTO_const_decl                  0x021
+#define LTO_complex_cst0                0x01B
+#define LTO_complex_cst1                0x01C
+#define LTO_complex_expr                0x01D
+#define LTO_component_ref               0x01E
+#define LTO_compound_expr               0x01F
+#define LTO_cond_expr                   0x020
+#define LTO_conj_expr                   0x021
+#define LTO_const_decl                  0x022
 /* This form is terminated by a zero.  */
-#define LTO_constructor                 0x022
-#define LTO_constructor_range           0x023
-#define LTO_convert_expr                0x024
-#define LTO_dot_prod_expr               0x025
-#define LTO_eq_expr                     0x026
-#define LTO_exact_div_expr              0x027
-#define LTO_exc_ptr_expr                0x028
-#define LTO_field_decl                  0x029
-#define LTO_filter_expr                 0x02A
-#define LTO_fix_ceil_expr               0x02B
-#define LTO_fix_floor_expr              0x02C
-#define LTO_fix_round_expr              0x02D
-#define LTO_fix_trunc_expr              0x02E
-#define LTO_float_expr                  0x02F
-#define LTO_floor_div_expr              0x030
-#define LTO_floor_mod_expr              0x031
-#define LTO_function_decl               0x032
-#define LTO_ge_expr                     0x033
-#define LTO_goto_expr                   0x034
-#define LTO_gt_expr                     0x035
-#define LTO_imagpart_expr               0x036
-#define LTO_indirect_ref                0x037
-#define LTO_integer_cst                 0x038
-#define LTO_label_decl                  0x039
-#define LTO_label_expr                  0x03A
-#define LTO_le_expr                     0x03B
-#define LTO_lrotate_expr                0x03C
-#define LTO_lshift_expr                 0x03D
-#define LTO_lt_expr                     0x03E
-#define LTO_ltgt_expr                   0x03F
-#define LTO_max_expr                    0x040
-#define LTO_min_expr                    0x041
-#define LTO_minus_expr                  0x042
-#define LTO_misaligned_indirect_ref     0x043
-#define LTO_modify_expr                 0x044
-#define LTO_mult_expr                   0x045
-#define LTO_ne_expr                     0x046
-#define LTO_negate_expr                 0x047
-#define LTO_non_lvalue_expr             0x048
-#define LTO_nop_expr                    0x049
-#define LTO_obj_type_ref                0x04A
-#define LTO_ordered_expr                0x04B
-#define LTO_parm_decl                   0x04C
-#define LTO_plus_expr                   0x04D
-#define LTO_range_expr                  0x04E
-#define LTO_rdiv_expr                   0x04F
-#define LTO_real_cst                    0x050
-#define LTO_realign_load_expr           0x051
-#define LTO_realpart_expr               0x052
-#define LTO_reduc_max_expr              0x053
-#define LTO_reduc_min_expr              0x054
-#define LTO_reduc_plus_expr             0x055
-#define LTO_result_decl                 0x056
+#define LTO_constructor                 0x023
+#define LTO_constructor_range           0x024
+#define LTO_convert_expr                0x025
+#define LTO_dot_prod_expr               0x026
+#define LTO_eq_expr                     0x027
+#define LTO_exact_div_expr              0x028
+#define LTO_exc_ptr_expr                0x029
+#define LTO_field_decl                  0x02A
+#define LTO_filter_expr                 0x02B
+#define LTO_fix_ceil_expr               0x02C
+#define LTO_fix_floor_expr              0x02D
+#define LTO_fix_round_expr              0x02E
+#define LTO_fix_trunc_expr              0x02F
+#define LTO_float_expr                  0x030
+#define LTO_floor_div_expr              0x031
+#define LTO_floor_mod_expr              0x032
+#define LTO_function_decl               0x033
+#define LTO_ge_expr                     0x034
+#define LTO_gimple_modify_stmt          0x035
+#define LTO_goto_expr                   0x036
+#define LTO_gt_expr                     0x037
+#define LTO_imagpart_expr               0x038
+#define LTO_indirect_ref                0x039
+#define LTO_integer_cst                 0x03A
+#define LTO_label_decl                  0x03B
+#define LTO_label_expr                  0x03C
+#define LTO_le_expr                     0x03D
+#define LTO_lrotate_expr                0x03E
+#define LTO_lshift_expr                 0x03F
+#define LTO_lt_expr                     0x040
+#define LTO_ltgt_expr                   0x041
+#define LTO_max_expr                    0x042
+#define LTO_min_expr                    0x043
+#define LTO_minus_expr                  0x044
+#define LTO_misaligned_indirect_ref     0x045
+#define LTO_modify_expr                 0x046
+#define LTO_mult_expr                   0x047
+#define LTO_ne_expr                     0x048
+#define LTO_negate_expr                 0x049
+#define LTO_non_lvalue_expr             0x04A
+#define LTO_nop_expr                    0x04B
+#define LTO_obj_type_ref                0x04C
+#define LTO_ordered_expr                0x04D
+#define LTO_parm_decl                   0x04E
+#define LTO_phi_node                    0x04F
+#define LTO_pointer_plus_expr           0x050
+#define LTO_plus_expr                   0x051
+#define LTO_range_expr                  0x052
+#define LTO_rdiv_expr                   0x053
+#define LTO_real_cst                    0x054
+#define LTO_realign_load_expr           0x055
+#define LTO_realpart_expr               0x056
+#define LTO_reduc_max_expr              0x057
+#define LTO_reduc_min_expr              0x058
+#define LTO_reduc_plus_expr             0x059
+#define LTO_result_decl                 0x05A
 /* Form "return;"  */
-#define LTO_return_expr0                0x057
+#define LTO_return_expr0                0x05B
 /* Form "return x;"  */
-#define LTO_return_expr1                0x058
+#define LTO_return_expr1                0x05C
 /* Form "return x=y;"  */
-#define LTO_return_expr2                0x059
-#define LTO_resx_expr                   0x05A
-#define LTO_round_div_expr              0x05B
-#define LTO_round_mod_expr              0x05C
-#define LTO_rrotate_expr                0x05D
-#define LTO_rshift_expr                 0x05E
-#define LTO_ssa_name                    0x05F
-#define LTO_string_cst                  0x060
+#define LTO_return_expr2                0x05D
+#define LTO_resx_expr                   0x05E
+#define LTO_round_div_expr              0x05F
+#define LTO_round_mod_expr              0x060
+#define LTO_rrotate_expr                0x061
+#define LTO_rshift_expr                 0x062
+#define LTO_ssa_name                    0x063
+#define LTO_string_cst                  0x064
 /* Cases are terminated a zero.  */
-#define LTO_switch_expr                 0x061
-#define LTO_trunc_div_expr              0x062
-#define LTO_trunc_mod_expr              0x063
-#define LTO_truth_and_expr              0x064
-#define LTO_truth_not_expr              0x065
-#define LTO_truth_or_expr               0x066
-#define LTO_truth_xor_expr              0x067
-#define LTO_uneq_expr                   0x068
-#define LTO_unge_expr                   0x069
-#define LTO_ungt_expr                   0x06A
-#define LTO_unle_expr                   0x06B
-#define LTO_unlt_expr                   0x06C
-#define LTO_unordered_expr              0x070
+#define LTO_switch_expr                 0x065
+#define LTO_trunc_div_expr              0x066
+#define LTO_trunc_mod_expr              0x067
+#define LTO_truth_and_expr              0x068
+#define LTO_truth_not_expr              0x069
+#define LTO_truth_or_expr               0x06A
+#define LTO_truth_xor_expr              0x06B
+#define LTO_uneq_expr                   0x06C
+#define LTO_unge_expr                   0x070
+#define LTO_ungt_expr                   0x071
+#define LTO_unle_expr                   0x072
+#define LTO_unlt_expr                   0x073
+#define LTO_unordered_expr              0x074
 /* 1 for static or extern and 0 for local.  */
-#define LTO_var_decl0                   0x071
-#define LTO_var_decl1                   0x072
-#define LTO_vec_cond_expr               0x073
-#define LTO_vec_lshift_expr             0x074
-#define LTO_vec_rshift_expr             0x075
+#define LTO_var_decl0                   0x075
+#define LTO_var_decl1                   0x076
+#define LTO_vec_cond_expr               0x077
+#define LTO_vec_lshift_expr             0x078
+#define LTO_vec_rshift_expr             0x079
 /* 1 if the elements are reals and 0 if the elements are ints.  */
-#define LTO_vector_cst0                 0x076
-#define LTO_vector_cst1                 0x077
-#define LTO_view_convert_expr           0x078
-#define LTO_widen_mult_expr             0x079
-#define LTO_widen_sum_expr              0x07A
-#define LTO_with_size_expr              0x07B
+#define LTO_vector_cst0                 0x07A
+#define LTO_vector_cst1                 0x07B
+#define LTO_view_convert_expr           0x07C
+#define LTO_widen_mult_expr             0x07D
+#define LTO_widen_sum_expr              0x07E
+#define LTO_with_size_expr              0x080
 
 
 /* All of the statement types that do not also appear as
    expressions.  */
-#define LTO_asm_inputs                  0x080
-#define LTO_asm_outputs                 0x081
-#define LTO_asm_clobbers                0x082
-
-#define LTO_function                    0x083
-#define LTO_attribute_list              0x084
-#define LTO_eh_table                    0x085
+#define LTO_asm_inputs                  0x090
+#define LTO_asm_outputs                 0x091
+#define LTO_asm_clobbers                0x092
+
+#define LTO_function                    0x093
+#define LTO_attribute_list              0x094
+#define LTO_eh_table                    0x095
 
 /* Each of these requires 4 variants.  1 and 3 are have_inner and 2
    and 3 are may_contain_throw.  */
-#define LTO_eh_table_cleanup0           0x090
-#define LTO_eh_table_cleanup1           0x091
-#define LTO_eh_table_cleanup2           0x092
-#define LTO_eh_table_cleanup3           0x093
-#define LTO_eh_table_try0               0x094
-#define LTO_eh_table_try1               0x095
-#define LTO_eh_table_try2               0x096
-#define LTO_eh_table_try3               0x097
-#define LTO_eh_table_catch0             0x098
-#define LTO_eh_table_catch1             0x099
-#define LTO_eh_table_catch2             0x09A
-#define LTO_eh_table_catch3             0x09B
-#define LTO_eh_table_allowed0           0x09C
-#define LTO_eh_table_allowed1           0x09D
-#define LTO_eh_table_allowed2           0x09E
-#define LTO_eh_table_allowed3           0x09F
-#define LTO_eh_table_must_not_throw0    0x0A0
-#define LTO_eh_table_must_not_throw1    0x0A1
-#define LTO_eh_table_must_not_throw2    0x0A2
-#define LTO_eh_table_must_not_throw3    0x0A3
+#define LTO_eh_table_cleanup0           0x0A0
+#define LTO_eh_table_cleanup1           0x0A1
+#define LTO_eh_table_cleanup2           0x0A2
+#define LTO_eh_table_cleanup3           0x0A3
+#define LTO_eh_table_try0               0x0A4
+#define LTO_eh_table_try1               0x0A5
+#define LTO_eh_table_try2               0x0A6
+#define LTO_eh_table_try3               0x0A7
+#define LTO_eh_table_catch0             0x0A8
+#define LTO_eh_table_catch1             0x0A9
+#define LTO_eh_table_catch2             0x0AA
+#define LTO_eh_table_catch3             0x0AB
+#define LTO_eh_table_allowed0           0x0AC
+#define LTO_eh_table_allowed1           0x0AD
+#define LTO_eh_table_allowed2           0x0AE
+#define LTO_eh_table_allowed3           0x0AF
+#define LTO_eh_table_must_not_throw0    0x0B0
+#define LTO_eh_table_must_not_throw1    0x0B1
+#define LTO_eh_table_must_not_throw2    0x0B2
+#define LTO_eh_table_must_not_throw3    0x0B3
 
 /* There are 16 variants of the following decl bodies depending on the
    subtrees that may or may not be there in the decl_common part of
@@ -424,9 +441,9 @@ struct lto_function_header
    These next two tags must have their last hex digit be 0. 
 */
 
-#define LTO_local_var_decl_body0        0x0B0
-#define LTO_parm_decl_body0             0x0C0
-#define LTO_last_tag                    0x0D0
+#define LTO_local_var_decl_body0        0x0C0
+#define LTO_parm_decl_body0             0x0D0
+#define LTO_last_tag                    0x0E0
 /* The string that is prepended on the DECL_ASSEMBLER_NAME to make the 
    section name for the function.  */
 #define LTO_SECTION_NAME_PREFIX         ".gnu.lto_"
@@ -470,6 +487,8 @@ struct lto_debug_context
   void * current_data;
   void * decl_data;
   void * label_data;
+  void * ssa_names_data;
+  void * cfg_data;
   void * main_data;
 };
 
Index: ipa.c
===================================================================
--- ipa.c	(revision 126565)
+++ ipa.c	(working copy)
@@ -25,6 +25,7 @@ Software Foundation, 51 Franklin Street,
 #include "cgraph.h"
 #include "tree-pass.h"
 #include "timevar.h"
+#include "flags.h"
 
 /* Fill array order with all nodes with output flag set in the reverse
    topological order.  */
@@ -278,10 +279,17 @@ function_and_variable_visibility (void)
   return 0;
 }
 
+static bool
+gate_ipa_fun_and_var_visibility (void)
+{
+  return !in_lto_p;
+}
+
+
 struct tree_opt_pass pass_ipa_function_and_variable_visibility = 
 {
   "visibility",				/* name */
-  NULL,					/* gate */
+  gate_ipa_fun_and_var_visibility,	/* gate */
   function_and_variable_visibility,	/* execute */
   NULL,					/* sub */
   NULL,					/* next */
Index: tree-ssa.c
===================================================================
--- tree-ssa.c	(revision 126565)
+++ tree-ssa.c	(working copy)
@@ -797,18 +797,18 @@ var_ann_hash (const void *item)
 /* Initialize global DFA and SSA structures.  */
 
 void
-init_tree_ssa (void)
+init_tree_ssa (struct function *fn)
 {
-  cfun->gimple_df = GGC_CNEW (struct gimple_df);
-  cfun->gimple_df->referenced_vars = htab_create_ggc (20, int_tree_map_hash, 
+  fn->gimple_df = GGC_CNEW (struct gimple_df);
+  fn->gimple_df->referenced_vars = htab_create_ggc (20, int_tree_map_hash, 
 				     		      int_tree_map_eq, NULL);
-  cfun->gimple_df->default_defs = htab_create_ggc (20, int_tree_map_hash, 
+  fn->gimple_df->default_defs = htab_create_ggc (20, int_tree_map_hash, 
 				                   int_tree_map_eq, NULL);
-  cfun->gimple_df->var_anns = htab_create_ggc (20, var_ann_hash, 
+  fn->gimple_df->var_anns = htab_create_ggc (20, var_ann_hash, 
 					       var_ann_eq, NULL);
-  cfun->gimple_df->call_clobbered_vars = BITMAP_GGC_ALLOC ();
-  cfun->gimple_df->addressable_vars = BITMAP_GGC_ALLOC ();
-  init_ssanames ();
+  fn->gimple_df->call_clobbered_vars = BITMAP_GGC_ALLOC ();
+  fn->gimple_df->addressable_vars = BITMAP_GGC_ALLOC ();
+  init_ssanames (fn, 0);
   init_phinodes ();
 }
 
Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 126565)
+++ tree-inline.c	(working copy)
@@ -1138,7 +1138,7 @@ initialize_cfun (tree new_fndecl, tree c
 
   if (src_cfun->gimple_df)
     {
-      init_tree_ssa ();
+      init_tree_ssa (cfun);
       cfun->gimple_df->in_ssa_p = true;
       init_ssa_operands ();
     }
Index: tree-optimize.c
===================================================================
--- tree-optimize.c	(revision 126565)
+++ tree-optimize.c	(working copy)
@@ -85,7 +85,7 @@ static bool
 gate_all_early_local_passes (void)
 {
 	  /* Don't bother doing anything if the program has errors.  */
-  return (!errorcount && !sorrycount);
+  return (!errorcount && !sorrycount && !in_lto_p);
 }
 
 struct tree_opt_pass pass_early_local_passes =
@@ -319,7 +319,7 @@ static unsigned int
 execute_init_datastructures (void)
 {
   /* Allocate hash tables, arrays and other structures.  */
-  init_tree_ssa ();
+  init_tree_ssa (cfun);
   return 0;
 }
 
Index: tree-flow.h
===================================================================
--- tree-flow.h	(revision 126565)
+++ tree-flow.h	(working copy)
@@ -864,7 +864,7 @@ typedef bool (*walk_use_def_chains_fn) (
 extern void strict_aliasing_warning_backend (void);
 
 /* In tree-ssa.c  */
-extern void init_tree_ssa (void);
+extern void init_tree_ssa (struct function *);
 extern edge ssa_redirect_edge (edge, basic_block);
 extern void flush_pending_stmts (edge);
 extern bool tree_ssa_useless_type_conversion (tree);
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 126565)
+++ Makefile.in	(working copy)
@@ -2459,7 +2459,7 @@ varpool.o : varpool.c $(CONFIG_H) $(SYST
    $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \
    $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h \
    gt-varpool.h
-ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H)
+ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) $(FLAGS_H) 
 ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h  \
    langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) ipa-prop.h \
    $(TREE_FLOW_H) $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H)
Index: tree-ssanames.c
===================================================================
--- tree-ssanames.c	(revision 126565)
+++ tree-ssanames.c	(working copy)
@@ -68,12 +68,15 @@ unsigned int ssa_name_nodes_reused;
 unsigned int ssa_name_nodes_created;
 #endif
 
-/* Initialize management of SSA_NAMEs.  */
+/* Initialize management of SSA_NAMEs to default SIZE.  If SIZE is
+   zero use default.  */
 
 void
-init_ssanames (void)
+init_ssanames (struct function *the_fun, int size)
 {
-  SSANAMES (cfun) = VEC_alloc (tree, gc, 50);
+  if (size < 50)
+    size = 50;
+  SSANAMES (the_fun) = VEC_alloc (tree, gc, size);
 
   /* Version 0 is special, so reserve the first slot in the table.  Though
      currently unused, we may use version 0 in alias analysis as part of
@@ -82,8 +85,8 @@ init_ssanames (void)
 
      We use VEC_quick_push here because we know that SSA_NAMES has at
      least 50 elements reserved in it.  */
-  VEC_quick_push (tree, SSANAMES (cfun), NULL_TREE);
-  FREE_SSANAMES (cfun) = NULL;
+  VEC_quick_push (tree, SSANAMES (the_fun), NULL_TREE);
+  FREE_SSANAMES (the_fun) = NULL;
 }
 
 /* Finalize management of SSA_NAMEs.  */
Index: lto/lto-read.c
===================================================================
--- lto/lto-read.c	(revision 126565)
+++ lto/lto-read.c	(working copy)
@@ -89,7 +89,7 @@ static void dump_debug_stream (struct in
 #endif
 
 static tree
-input_expr_operand (struct input_block *, struct fun_in *, unsigned int);
+input_expr_operand (struct input_block *, struct fun_in *, struct function *, unsigned int);
 
 
 /* Return the next character of input from IB.  Abort if you
@@ -274,19 +274,19 @@ input_record_start (struct input_block *
 /* Build a tree list stopping when the tag is 0.  */
 
 static tree 
-input_list (struct input_block *ib, struct fun_in *fun_in)
+input_list (struct input_block *ib, struct fun_in *fun_in, struct function *fn)
 {
   unsigned int tag = input_record_start (ib);
   tree first = NULL_TREE;
   if (tag)
     {
-      first = build_tree_list (NULL_TREE, input_expr_operand (ib, fun_in, tag));
+      first = build_tree_list (NULL_TREE, input_expr_operand (ib, fun_in, fn, tag));
       tree next = first;
       tag = input_record_start (ib);
       while (tag)
 	{
 	  TREE_CHAIN (next) 
-	    = build_tree_list (NULL_TREE, input_expr_operand (ib, fun_in, tag));
+	    = build_tree_list (NULL_TREE, input_expr_operand (ib, fun_in, fn, tag));
 	  next = TREE_CHAIN (next);
 	  tag = input_record_start (ib);
 	}
@@ -296,61 +296,6 @@ input_list (struct input_block *ib, stru
   return first;
 }
 
-/* Set up an empty cfg for THIS_FUN with BB_COUNT slots available.  */
-
-static void 
-init_cfg (struct function *this_fun, unsigned int bb_count)
-{
-  init_flow (this_fun);
-  profile_status_for_function (this_fun) = PROFILE_ABSENT;
-  n_basic_blocks_for_function (this_fun) = NUM_FIXED_BLOCKS;
-  last_basic_block_for_function (this_fun) = bb_count;
-  basic_block_info_for_function (this_fun)
-    = VEC_alloc (basic_block, gc, bb_count);
-  VEC_safe_grow (basic_block, gc, basic_block_info, bb_count);
-  memset (VEC_address (basic_block, 
-		       basic_block_info_for_function (this_fun)), 
-	  0, sizeof (basic_block) * bb_count);
-
-  /* Build a mapping of labels to their associated blocks.  */
-  label_to_block_map_for_function (this_fun)
-    = VEC_alloc (basic_block, gc, bb_count);
-  VEC_safe_grow (basic_block, gc, 
-		 label_to_block_map_for_function (this_fun), bb_count);
-  memset (VEC_address (basic_block, 
-		       label_to_block_map_for_function (this_fun)),
-	  0, sizeof (basic_block) * bb_count);
-
-  SET_BASIC_BLOCK_FOR_FUNCTION (this_fun, ENTRY_BLOCK, 
-				ENTRY_BLOCK_PTR_FOR_FUNCTION (this_fun));
-  SET_BASIC_BLOCK_FOR_FUNCTION (this_fun, EXIT_BLOCK, 
-		   EXIT_BLOCK_PTR_FOR_FUNCTION (this_fun));
-}
-
-
-/* Link up the prev_bb and next_bb fields in the cfg.  */
-
-static void 
-finalize_cfg (struct function *this_fun, unsigned int bb_count)
-{
-  unsigned int i;
-  basic_block p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(this_fun);
-
-  for (i=NUM_FIXED_BLOCKS; i<bb_count; i++)
-    {
-      basic_block bb = BASIC_BLOCK_FOR_FUNCTION (this_fun, i);
-      if (bb)
-	{
-	  bb->prev_bb = p_bb;
-	  p_bb->next_bb = bb;
-	  p_bb = bb;
-	}
-    }
-
-  p_bb->next_bb = EXIT_BLOCK_PTR_FOR_FUNCTION(this_fun);
-  EXIT_BLOCK_PTR_FOR_FUNCTION(this_fun)->prev_bb = p_bb;
-}
-
 
 /* Get the label referenced by the next token in IB.  */
 
@@ -444,7 +389,7 @@ process_flags (tree expr, unsigned HOST_
 
 static tree
 input_expr_operand (struct input_block *ib, struct fun_in *fun_in, 
-		    unsigned int tag)
+		    struct function *fn, unsigned int tag)
 {
   enum tree_code code = tag_to_expr[tag];
   tree type = NULL_TREE;
@@ -560,11 +505,11 @@ input_expr_operand (struct input_block *
 	tree op1 = NULL_TREE;
 	
 	if (variant & 0x1)
-	  op0 = input_expr_operand (ib, fun_in, 
+	  op0 = input_expr_operand (ib, fun_in, fn, 
 				    input_record_start (ib));
 
 	if (variant & 0x2)
-	  op1 = input_expr_operand (ib, fun_in, 
+	  op1 = input_expr_operand (ib, fun_in, fn, 
 				    input_record_start (ib));
 
 	result = build3 (code, void_type_node, 
@@ -594,7 +539,7 @@ input_expr_operand (struct input_block *
 		else
 		  {
 		    tree value = 
-		      input_expr_operand (ib, fun_in, ctag);
+		      input_expr_operand (ib, fun_in, fn, ctag);
 		    constructor_elt *elt 
 		      = VEC_quick_push (constructor_elt, vec, NULL);
 		    elt->index = purpose;
@@ -611,6 +556,10 @@ input_expr_operand (struct input_block *
       }
       break;
 
+    case SSA_NAME:
+      result = VEC_index (tree, SSANAMES (fn), input_uleb128 (ib));
+      break;
+
     case CONST_DECL:
       /* Just ignore these, Mark will make them disappear.  */
       break;
@@ -665,9 +614,9 @@ input_expr_operand (struct input_block *
       {
 	tree op0;
 	tree op1;
-	op0 = input_expr_operand (ib, fun_in, 
+	op0 = input_expr_operand (ib, fun_in, fn, 
 				  input_record_start (ib));
-	op1 = input_expr_operand (ib, fun_in, 
+	op1 = input_expr_operand (ib, fun_in, fn,
 				  input_record_start (ib));
   
 	/* Ignore 3 because it can be recomputed.  */
@@ -684,11 +633,11 @@ input_expr_operand (struct input_block *
 
 	/* The call chain.  */
 	if (tag == LTO_call_expr1)
-	  op2 = input_expr_operand (ib, fun_in, 
+	  op2 = input_expr_operand (ib, fun_in, fn, 
 				    input_record_start (ib));
 
 	/* The callee.  */
-	op1 = input_expr_operand (ib, fun_in, 
+	op1 = input_expr_operand (ib, fun_in, fn, 
 				  input_record_start (ib));
 
 	result = build_vl_exp (code, count);
@@ -696,7 +645,7 @@ input_expr_operand (struct input_block *
 	CALL_EXPR_STATIC_CHAIN (result) = op2;
 	for (i = 3; i < count; i++)
 	  TREE_OPERAND (result, i) 
-	    = input_expr_operand (ib, fun_in, 
+	    = input_expr_operand (ib, fun_in, fn, 
 				  input_record_start (ib));
       }
       break;
@@ -710,16 +659,16 @@ input_expr_operand (struct input_block *
 	  {
 	    op1 = input_integer (ib, SIZETYPE);
 	    op2 = input_integer (ib, SIZETYPE);
-	    op0 = input_expr_operand (ib, fun_in, 
+	    op0 = input_expr_operand (ib, fun_in, fn,
 				      input_record_start (ib));
 	  }
 	else
 	  {
-	    op0 = input_expr_operand (ib, fun_in, 
+	    op0 = input_expr_operand (ib, fun_in, fn,
 				      input_record_start (ib));
-	    op1 = input_expr_operand (ib, fun_in, 
+	    op1 = input_expr_operand (ib, fun_in, fn,
 				      input_record_start (ib));
-	    op2 = input_expr_operand (ib, fun_in, 
+	    op2 = input_expr_operand (ib, fun_in, fn,
 				      input_record_start (ib));
 	  }
 	result = build3 (code, type, op0, op1, op2);
@@ -731,9 +680,9 @@ input_expr_operand (struct input_block *
       /* Ignore operands 2 and 3 for ARRAY_REF and ARRAY_RANGE REF
 	 because they can be recomputed.  */
       {
-	tree op0 = input_expr_operand (ib, fun_in, 
+	tree op0 = input_expr_operand (ib, fun_in, fn, 
 				       input_record_start (ib));
-	tree op1 = input_expr_operand (ib, fun_in, 
+	tree op1 = input_expr_operand (ib, fun_in, fn,
 				       input_record_start (ib));
 	result = build4 (code, type, op0, op1, NULL_TREE, NULL_TREE);
       }
@@ -742,10 +691,15 @@ input_expr_operand (struct input_block *
     case ASM_EXPR:
       {
 	tree str = input_string (fun_in, input_uleb128 (ib));
-	tree ins = input_list (ib, fun_in); 
-	tree outs = input_list (ib, fun_in); 
-	tree clobbers = input_list (ib, fun_in);
+	tree ins = input_list (ib, fun_in, fn); 
+	tree outs = input_list (ib, fun_in, fn); 
+	tree clobbers = input_list (ib, fun_in, fn);
+	tree tl;
 	result = build4 (code, void_type_node, str, outs, ins, clobbers);
+
+	for (tl = ASM_OUTPUTS (result); tl; tl = TREE_CHAIN (tl))
+	  if (TREE_CODE (TREE_VALUE (tl)) == SSA_NAME)
+	    SSA_NAME_DEF_STMT (TREE_VALUE (tl)) = result;
       }
       break;
 
@@ -762,15 +716,15 @@ input_expr_operand (struct input_block *
 	  
 	case LTO_return_expr1:
 	  result = build1 (code, NULL_TREE, 
-			   input_expr_operand (ib, fun_in, 
+			   input_expr_operand (ib, fun_in, fn, 
 					       input_record_start (ib)));
 	  break;
 	  
 	case LTO_return_expr2:
 	  {
-	    tree op0 = input_expr_operand (ib, fun_in, 
+	    tree op0 = input_expr_operand (ib, fun_in, fn,
 					   input_record_start (ib));
-	    tree op1 = input_expr_operand (ib, fun_in, 
+	    tree op1 = input_expr_operand (ib, fun_in, fn,
 					   input_record_start (ib));
 	    result = build1 (code, NULL_TREE, 
 			     build2 (MODIFY_EXPR, NULL_TREE, op0, op1));
@@ -779,17 +733,30 @@ input_expr_operand (struct input_block *
 	}
       break;
 
+    case GIMPLE_MODIFY_STMT:
+      {
+	tree op0 = input_expr_operand (ib, fun_in, fn, 
+				       input_record_start (ib));
+	tree op1 = input_expr_operand (ib, fun_in, fn,
+				       input_record_start (ib));
+
+	result = build_gimple_modify_stmt (op0, op1);
+	if (TREE_CODE (op0) == SSA_NAME)
+	  SSA_NAME_DEF_STMT (op0) = result;
+      }
+      break;
+
     case SWITCH_EXPR:
       {
 	unsigned int len = input_uleb128 (ib);
 	unsigned int i;
-	tree op0 = input_expr_operand (ib, fun_in, 
+	tree op0 = input_expr_operand (ib, fun_in, fn, 
 				       input_record_start (ib));
 	tree op2 = make_tree_vec (len);
 	
 	for (i = 0; i < len; ++i)
 	  TREE_VEC_ELT (op2, i) 
-	    = input_expr_operand (ib, fun_in, 
+	    = input_expr_operand (ib, fun_in, fn,
 				  input_record_start (ib));
 	result = build3 (code, NULL_TREE, op0, NULL_TREE, op2);
       }
@@ -809,7 +776,7 @@ input_expr_operand (struct input_block *
 	int len = TREE_CODE_LENGTH (code);
 	int i;
 	for (i = 0; i<len; i++)
-	  ops[i] = input_expr_operand (ib, fun_in, 
+	  ops[i] = input_expr_operand (ib, fun_in, fn, 
 				       input_record_start (ib));
 	switch (len)
 	  {
@@ -858,7 +825,6 @@ input_expr_operand (struct input_block *
     case OMP_RETURN:
     case OMP_SECTIONS:
     case OMP_SINGLE:
-    case SSA_NAME:
     case STRUCT_FIELD_TAG:
     case SYMBOL_MEMORY_TAG:
     case TARGET_MEM_REF:
@@ -933,11 +899,9 @@ input_globals (struct lto_function_heade
    labels from DATA segment SIZE bytes long using FUN_IN.  */
 
 static void 
-input_labels (struct fun_in *fun_in, const char *data, 
-	      unsigned int size, unsigned int named_count, 
-	      unsigned int unnamed_count)
+input_labels (struct fun_in *fun_in, struct input_block *ib, 
+	      unsigned int named_count, unsigned int unnamed_count)
 {
-  struct input_block ib = {data, 0, size};
   unsigned int i;
 
   /* The named and unnamed labels share the same array.  In the lto
@@ -947,7 +911,7 @@ input_labels (struct fun_in *fun_in, con
   fun_in->labels = xcalloc (named_count + unnamed_count, sizeof (tree*));
   for (i = 0; i < named_count; i++)
     {
-      unsigned int name_index = input_uleb128 (&ib);
+      unsigned int name_index = input_uleb128 (ib);
       unsigned int len;
       const char *s = input_string_internal (fun_in, name_index, &len);
       tree name = get_identifier_with_length (s, len);
@@ -963,16 +927,15 @@ input_labels (struct fun_in *fun_in, con
    bytes long using FUN_IN.  */
 
 static void 
-input_local_vars (struct fun_in *fun_in, const char *data, 
-	     unsigned int size, unsigned int count)
+input_local_vars (struct fun_in *fun_in, struct input_block *ib, 
+		  struct function *fn, unsigned int count)
 {
-  struct input_block ib = {data, 0, size};
   unsigned int i;
 
   fun_in->local_decls = xcalloc (count, sizeof (tree*));
   for (i = 0; i < count; i++)
     {
-      unsigned int tag = input_record_start (&ib);
+      unsigned int tag = input_record_start (ib);
       unsigned int variant = tag & 0xF;
       bool is_var = ((tag & 0xFFF0) == LTO_local_var_decl_body0);
 
@@ -984,7 +947,7 @@ input_local_vars (struct fun_in *fun_in,
       int new_line = -1;
       tree result = fun_in->local_decls[i];
 
-      name_index = input_uleb128 (&ib);
+      name_index = input_uleb128 (ib);
       if (name_index)
 	{
 	  unsigned int len;
@@ -994,7 +957,7 @@ input_local_vars (struct fun_in *fun_in,
       else 
 	name = NULL_TREE;
 
-      type = get_type_ref (fun_in, &ib);
+      type = get_type_ref (fun_in, ib);
 
       /* The result may not be NULL here because if any of the
 	 subtrees of some prior local var_decl referenced this local
@@ -1010,46 +973,46 @@ input_local_vars (struct fun_in *fun_in,
       fun_in->local_decls[i] = result;
 
       if (!is_var)
-	DECL_ARG_TYPE (result) = get_type_ref (fun_in, &ib);
+	DECL_ARG_TYPE (result) = get_type_ref (fun_in, ib);
 
       LTO_DEBUG_TOKEN ("flags")
-      flags = input_uleb128 (&ib);
+      flags = input_uleb128 (ib);
 
       /* FIXME: Need to figure out how to set the line number.  */
       if (flags & 0x2)
 	{
 	  unsigned int len;
 	  LTO_DEBUG_TOKEN ("file")
-	  new_file = input_string_internal (fun_in, input_uleb128 (&ib), &len);
+	  new_file = input_string_internal (fun_in, input_uleb128 (ib), &len);
 	}
       if (flags & 0x1)
 	{
 	  LTO_DEBUG_TOKEN ("line")
-	  new_line = input_uleb128 (&ib);
+	  new_line = input_uleb128 (ib);
 	}
 
       LTO_DEBUG_TOKEN ("align")
-      DECL_ALIGN (result) = input_uleb128 (&ib);
+      DECL_ALIGN (result) = input_uleb128 (ib);
       LTO_DEBUG_TOKEN ("size")
       DECL_SIZE (result) 
-	= input_expr_operand (&ib, fun_in, input_record_start (&ib));
+	= input_expr_operand (ib, fun_in, fn, input_record_start (ib));
 
       if (variant & 0x1)
 	{
 	  LTO_DEBUG_TOKEN ("attributes")
           DECL_ATTRIBUTES (result) 
-	    = input_expr_operand (&ib, fun_in, input_record_start (&ib));
+	    = input_expr_operand (ib, fun_in, fn, input_record_start (ib));
 	}
       if (variant & 0x2)
 	DECL_SIZE_UNIT (result) 
-	  = input_expr_operand (&ib, fun_in, input_record_start (&ib));
+	  = input_expr_operand (ib, fun_in, fn, input_record_start (ib));
       if (variant & 0x4)
 	SET_DECL_DEBUG_EXPR (result, 
-			     input_expr_operand (&ib, fun_in, 
-						 input_record_start (&ib)));
+			     input_expr_operand (ib, fun_in, fn, 
+						 input_record_start (ib)));
       if (variant & 0x8)
         DECL_ABSTRACT_ORIGIN (result) 
-	  = input_expr_operand (&ib, fun_in, input_record_start (&ib));
+	  = input_expr_operand (ib, fun_in, fn, input_record_start (ib));
 
       process_flags (result, flags);
       LTO_DEBUG_UNDENT()
@@ -1084,6 +1047,151 @@ make_new_block (struct function *fn, uns
 }
 
 
+/* Set up the cfg for THIS_FUN.  */
+
+static void 
+input_cfg (struct input_block *ib, struct function *fn)
+{
+  unsigned int bb_count;
+  basic_block p_bb;
+  unsigned int i;
+  int index;
+
+  init_flow (fn);
+
+  LTO_DEBUG_TOKEN ("lastbb")
+  bb_count = input_uleb128 (ib);
+
+  profile_status_for_function (fn) = PROFILE_ABSENT;
+  n_basic_blocks_for_function (fn) = bb_count;
+  last_basic_block_for_function (fn) = bb_count;
+  basic_block_info_for_function (fn)
+    = VEC_alloc (basic_block, gc, bb_count);
+  VEC_safe_grow (basic_block, gc, basic_block_info, bb_count);
+  memset (VEC_address (basic_block, 
+		       basic_block_info_for_function (fn)), 
+	  0, sizeof (basic_block) * bb_count);
+
+  /* Build a mapping of labels to their associated blocks.  */
+  label_to_block_map_for_function (fn)
+    = VEC_alloc (basic_block, gc, bb_count);
+  VEC_safe_grow (basic_block, gc, 
+		 label_to_block_map_for_function (fn), bb_count);
+  memset (VEC_address (basic_block, 
+		       label_to_block_map_for_function (fn)),
+	  0, sizeof (basic_block) * bb_count);
+
+  SET_BASIC_BLOCK_FOR_FUNCTION (fn, ENTRY_BLOCK, 
+				ENTRY_BLOCK_PTR_FOR_FUNCTION (fn));
+  SET_BASIC_BLOCK_FOR_FUNCTION (fn, EXIT_BLOCK, 
+		   EXIT_BLOCK_PTR_FOR_FUNCTION (fn));
+
+  LTO_DEBUG_TOKEN ("bbindex")
+  index = input_sleb128 (ib);
+  while (index != -1)
+    {
+      basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
+      unsigned int edge_count;
+
+      if (bb == NULL)
+	bb = make_new_block (fn, index);
+
+      LTO_DEBUG_TOKEN ("edgecount")
+      edge_count = input_uleb128 (ib);
+
+      /* Connect up the cfg.  */
+      for (i = 0; i < edge_count; i++)
+	{
+	  LTO_DEBUG_TOKEN ("dest")
+	    unsigned int dest_index = input_uleb128 (ib);
+	  LTO_DEBUG_TOKEN ("eflags")
+	    unsigned int edge_flags = input_uleb128 (ib);
+	  basic_block dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index);
+	  if (dest == NULL) 
+	    dest = make_new_block (fn, dest_index);
+	  make_edge (bb, dest, edge_flags);
+	}
+
+      LTO_DEBUG_TOKEN ("bbindex")
+      index = input_sleb128 (ib);
+    }
+
+  p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(fn);
+  for (i = NUM_FIXED_BLOCKS; i < bb_count; i++)
+    {
+      basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, i);
+      if (bb)
+	{
+	  bb->prev_bb = p_bb;
+	  p_bb->next_bb = bb;
+	  p_bb = bb;
+	}
+    }
+
+  p_bb->next_bb = EXIT_BLOCK_PTR_FOR_FUNCTION(fn);
+  EXIT_BLOCK_PTR_FOR_FUNCTION(fn)->prev_bb = p_bb;
+}
+
+
+/* Input the next phi function for BB.  */
+
+static tree
+input_phi (struct input_block *ib, basic_block bb, struct function *fn)
+{
+  tree phi_result = VEC_index (tree, SSANAMES (fn), input_uleb128 (ib));
+  int len = EDGE_COUNT (bb->preds);
+  int i;
+  tree result = create_phi_node (phi_result, bb);
+
+  SSA_NAME_DEF_STMT (phi_result) = result;
+
+  for (i = 0; i < len; i++)
+    {
+      tree def = VEC_index (tree, SSANAMES (fn), input_uleb128 (ib));
+      int src_index = input_uleb128 (ib);
+      basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index);
+      
+      edge e = NULL;
+      int j;
+      
+      for (j = 0; j < len; j++)
+	if (EDGE_PRED (bb, j)->src == sbb)
+	  {
+	    e = EDGE_PRED (bb, j);
+	    break;
+	  }
+
+      add_phi_arg (result, def, e); 
+    }
+  return result;
+}
+
+
+/* Read in the ssa_names array from IB.  */
+
+static void
+input_ssa_names (struct fun_in *fun_in, struct input_block *ib, struct function *fn)
+{
+  unsigned int i;
+  int size = input_uleb128 (ib);
+
+  init_tree_ssa (fn);
+  init_ssanames (fn, size);
+  i = input_uleb128 (ib);
+  
+  while (i)
+    {
+      /* Skip over the elements that had been freed.  */
+      while (VEC_length (tree, SSANAMES (fn)) < i)
+	VEC_quick_push (tree, SSANAMES (fn), NULL_TREE);
+
+      make_ssa_name (input_expr_operand (ib, fun_in, fn, input_record_start (ib)), NULL);
+
+      i = input_uleb128 (ib);
+    } 
+}
+
+ 
 /* Read in the next basic block.  */
 
 static void
@@ -1091,34 +1199,12 @@ input_bb (struct input_block *ib, unsign
 	  struct function *fn, struct fun_in *fun_in)
 {
   unsigned int index;
-  unsigned int edge_count;
   basic_block bb;
-  unsigned int i;
   block_stmt_iterator bsi;
 
   LTO_DEBUG_TOKEN ("bbindex")
   index = input_uleb128 (ib);
-  LTO_DEBUG_TOKEN ("edgecount")
-  edge_count = input_uleb128 (ib);
   bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
-  /* There are several reasons why the slot may already have a block.
-     Either it is the entry or exit block or else it was the
-     destination of a block that was created earlier.  */ 
-  if (bb == NULL)
-    make_new_block (fn, index);
-
-  /* Connect up the cfg.  */
-  for (i=0; i<edge_count; i++)
-    {
-      LTO_DEBUG_TOKEN ("dest")
-      unsigned int dest_index = input_uleb128 (ib);
-      LTO_DEBUG_TOKEN ("eflags")
-      unsigned int edge_flags = input_uleb128 (ib);
-      basic_block dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index);
-      if (dest == NULL) 
-	dest = make_new_block (fn, dest_index);
-      make_edge (bb, dest, edge_flags);
-    }
 
   /* LTO_bb1 has stmts, LTO_bb0 does not.  */
   if (tag == LTO_bb0)
@@ -1132,12 +1218,22 @@ input_bb (struct input_block *ib, unsign
   tag = input_record_start (ib);
   while (tag)
     {
-      tree stmt = input_expr_operand (ib, fun_in, tag);
+      tree stmt = input_expr_operand (ib, fun_in, fn, tag);
       bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
       LTO_DEBUG_INDENT_TOKEN ("stmt")
       tag = input_record_start (ib);
       /* FIXME, add code to handle the exception.  */
     }
+
+  LTO_DEBUG_INDENT_TOKEN ("phi")
+  tag = input_record_start (ib);
+  while (tag)
+    {
+      input_phi (ib, bb, fn);
+      LTO_DEBUG_INDENT_TOKEN ("phi")
+      tag = input_record_start (ib);
+    }
+
   LTO_DEBUG_UNDENT()
 }
 
@@ -1146,28 +1242,23 @@ input_bb (struct input_block *ib, unsign
 
 static void
 input_function (tree fn_decl, struct fun_in *fun_in, 
-		const char *data, unsigned int size)
+		struct input_block *ib)
 {
   struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
-  struct input_block ib = {data, 0, size};
-  unsigned int tag = input_record_start (&ib);
-  unsigned int last_bb_index;
+  unsigned int tag = input_record_start (ib);
 
   tree_register_cfg_hooks ();
   gcc_assert (tag == LTO_function);
 
-  input_eh_regions (&ib, fn, fun_in);
+  input_eh_regions (ib, fn, fun_in);
 
-  last_bb_index = input_uleb128 (&ib);
-  init_cfg (fn, last_bb_index);
-  tag = input_record_start (&ib);
+  tag = input_record_start (ib);
   while (tag)
     {
-      input_bb (&ib, tag, fn, fun_in);
-      tag = input_record_start (&ib);
+      input_bb (ib, tag, fn, fun_in);
+      tag = input_record_start (ib);
     }
 
-  finalize_cfg (fn, last_bb_index);
   LTO_DEBUG_UNDENT()
 }
 
@@ -1267,6 +1358,7 @@ lto_static_init_local (void)
 #undef END_EXPR_SWITCH
 
   lto_static_init ();
+  tree_register_cfg_hooks ();
 }
 
 
@@ -1285,32 +1377,43 @@ lto_read_function_body (lto_info_fd *fd,
   struct fun_in fun_in;
   int32_t fields_offset = sizeof (struct lto_function_header); 
   int32_t fns_offset 
-    = fields_offset + 
-    (header->num_field_decls * sizeof (lto_ref));
+    = fields_offset + (header->num_field_decls * sizeof (lto_ref));
   int32_t vars_offset 
-    = fns_offset + 
-    (header->num_fn_decls * sizeof (lto_ref));
+    = fns_offset + (header->num_fn_decls * sizeof (lto_ref));
   int32_t types_offset 
-    = vars_offset + 
-    (header->num_var_decls * sizeof (lto_ref));
-  int32_t named_labels_offset 
-    = types_offset + 
-    (header->num_types * sizeof (lto_ref));
-  int32_t locals_offset = named_labels_offset + header->named_label_size;
-  int32_t main_offset = locals_offset + header->local_decls_size;
+    = vars_offset + (header->num_var_decls * sizeof (lto_ref));
+  int32_t named_label_offset 
+    = types_offset + (header->num_types * sizeof (lto_ref));
+  int32_t ssa_names_offset 
+    = named_label_offset + header->named_label_size;
+  int32_t cfg_offset 
+    = ssa_names_offset + header->ssa_names_size;
+  int32_t local_decls_offset = cfg_offset + header->cfg_size;
+  int32_t main_offset = local_decls_offset + header->local_decls_size;
   int32_t string_offset = main_offset + header->main_size;
 
 #ifdef LTO_STREAM_DEBUGGING
   int32_t debug_decl_offset = string_offset + header->string_size;
   int32_t debug_label_offset = debug_decl_offset + header->debug_decl_size;
-  int32_t debug_main_offset = debug_label_offset + header->debug_label_size;
+  int32_t debug_ssa_names_offset = debug_label_offset + header->debug_label_size;
+  int32_t debug_cfg_offset = debug_ssa_names_offset + header->debug_ssa_names_size;
+  int32_t debug_main_offset = debug_cfg_offset + header->debug_cfg_size;
 
   struct input_block debug_decl 
     = {data + debug_decl_offset, 0, header->debug_decl_size};
   struct input_block debug_label 
     = {data + debug_label_offset, 0, header->debug_label_size};
+  struct input_block debug_ssa_names 
+    = {data + debug_ssa_names_offset, 0, header->debug_ssa_names_size};
+  struct input_block debug_cfg 
+    = {data + debug_cfg_offset, 0, header->debug_cfg_size};
   struct input_block debug_main 
     = {data + debug_main_offset, 0, header->debug_main_size};
+
+  struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
+
+  lto_debug_context.out = debug_out_fun;
+  lto_debug_context.indent = 0;
 #endif
 
   lto_ref *in_field_decls = (lto_ref*)(data + fields_offset);
@@ -1318,13 +1421,18 @@ lto_read_function_body (lto_info_fd *fd,
   lto_ref *in_var_decls   = (lto_ref*)(data + vars_offset);
   lto_ref *in_types       = (lto_ref*)(data + types_offset);
 
-  const char * named_labels = data + named_labels_offset;
-  const char * local_decls  = data + locals_offset;
-  const char * main_gimple  = data + main_offset;
+  struct input_block ib_named_labels 
+    = {data + named_label_offset, 0, header->named_label_size};
+  struct input_block ib_ssa_names 
+    = {data + ssa_names_offset, 0, header->ssa_names_size};
+  struct input_block ib_cfg 
+    = {data + cfg_offset, 0, header->cfg_size};
+  struct input_block ib_local_decls 
+    = {data + local_decls_offset, 0, header->local_decls_size};
+  struct input_block ib_main 
+    = {data + main_offset, 0, header->main_size};
 
 #ifdef LTO_STREAM_DEBUGGING
-  lto_debug_context.out = debug_out_fun;
-  lto_debug_context.indent = 0;
   lto_debug_context.current_data = &debug_label;
 #endif
 
@@ -1342,26 +1450,29 @@ lto_read_function_body (lto_info_fd *fd,
 		in_var_decls, in_types);
 
   fun_in.num_named_labels = header->num_named_labels;
-  input_labels (&fun_in, named_labels, 
-		header->named_label_size, 
+  input_labels (&fun_in, &ib_named_labels, 
 		header->num_named_labels, header->num_unnamed_labels);
 
 #ifdef LTO_STREAM_DEBUGGING
   lto_debug_context.current_data = &debug_decl;
 #endif
-  input_local_vars (&fun_in, local_decls, 
-		    header->local_decls_size, header->num_local_decls);
+  input_local_vars (&fun_in, &ib_local_decls, fn, header->num_local_decls);
 
 #ifdef LTO_STREAM_DEBUGGING
-  lto_debug_context.current_data = &debug_main;
-#if 0
-  dump_debug_stream ((struct input_block *)lto_debug_context.current_data, 
-		     ' ', ' ');
+  lto_debug_context.current_data = &debug_ssa_names;
 #endif
+  input_ssa_names (&fun_in, &ib_ssa_names, fn);
+
+#ifdef LTO_STREAM_DEBUGGING
+  lto_debug_context.current_data = &debug_cfg;
 #endif
+  input_cfg (&ib_cfg, fn);
 
+#ifdef LTO_STREAM_DEBUGGING
+  lto_debug_context.current_data = &debug_main;
+#endif
   /* Set up the struct function.  */
-  input_function (fn_decl, &fun_in, main_gimple, header->main_size);
+  input_function (fn_decl, &fun_in, &ib_main);
 }
 
 
@@ -1375,7 +1486,7 @@ dump_debug_stream (struct input_block *s
   int chars = 0;
   int hit_pos = -1;
   fprintf (stderr, 
-	   "stream failure: looking for '%c' found '%c' at stream->%d\n\n",
+	   "stream failure: looking for a '%c' in the debug stream.\nHowever the data translated into a '%c' at position%d\n\n",
 	   c, b, stream->p);
   
   while (i < stream->len)
Index: lto/lto-lang.c
===================================================================
--- lto/lto-lang.c	(revision 126565)
+++ lto/lto-lang.c	(working copy)
@@ -151,6 +151,7 @@ lto_init (void)
   /* Always operate in unit-at-time mode so that we can defer
      decisions about what to output.  */
   flag_unit_at_a_time = 1;
+  in_lto_p = false;
 
   /* Create the basic integer types.  */
   build_common_tree_nodes (flag_signed_char, 

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