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] Fixed version of a previous patch


This is an updated version of
http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00900.html that fixes
errors we found in some internal testing. The patch against TOB is
full.patch. The differences from this patch to the previous one is
new.patch.

The new parts are:

*) Make cgraph_remove_unreachable_nodes search all clones for one that
is needed before removing the body. This was causing segmentation
faults in the case that a clone earlier then NODE in the clone list
was needed, but none after it was.
*) Remove old assert from output_node that no longer relevant.
*) If the NODE is not part of SET, don't output inilned_to.
*) Small cleanup on the  assertion that we moved all inlines.
*) Don't consider the caller when deciding whether to move a node or not.

Bootstrapped and regression tested. I also repeated the testing that
found the above issues on the first patch.

With this working, I am more confident to try to bring in some of the
cleanups from the pretty-ipa branch. The removal of the concept of a
master clone in particular.

gcc/
2009-02-19  Rafael Avila de Espindola  <espindola@google.com>

	* ipa.c (cgraph_remove_unreachable_nodes): Search all clones.
	* lto-cgraph.c: Include lto-util.h
	(maybe_redirect_inlined_node): Remove.
	(output_edge): Don't worry about an edge poiting to a node not in know
	by the encoder.
	(output_node): Output the decl number instead of the master node
	number in the case of a clone.
	(output_cgraph_verify_node): Don't check that the master is in the set.
	(output_cgraph): Don't output the current master for each decl. The
	first node output will be the master in ltrans.
	(input_node): If a clone, read the decl number and use that decls'
	master node.
	(input_cgraph_1): Update call to input_node.
	* lto-function-out.c (lto_output): Proces each function once. Don't
	care if the node is the master.

gcc/lto/
2009-02-19  Rafael Avila de Espindola  <espindola@google.com>

	* lto.c (lto_add_inline_clones): Don't add the master clone. Check
	for a decl in the original bitmap, not a node.
	(lto_add_all_inlinees): Remove original nodes that are not needed.
	(lto_scan_statics_in_cgraph_node): Don't care if the node is the master.

gcc/testsuite/
2009-02-19  Rafael Avila de Espindola  <espindola@google.com>

	* gcc.dg/lto/20090218-2_0.c: New.
	* gcc.dg/lto/20090218-2_1.c: New.


Cheers,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047
diff --git a/gcc/ipa.c b/gcc/ipa.c
index dc0b5bc..66c1d6b 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -175,7 +175,10 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		{
 		  struct cgraph_node *clone;
 
-		  for (clone = node->next_clone; clone;
+		  for (clone = node; clone->prev_clone;
+		       clone = clone->prev_clone)
+		    ;
+		  for (; clone;
 		       clone = clone->next_clone)
 		    if (clone->aux)
 		      break;
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 06715dd..0f212eb 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -238,10 +238,7 @@ output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
     }
  
   if (boundary_p)
-    {
-      gcc_assert (!wrote_master_p);
-      tag = LTO_cgraph_unavail_node;
-    }
+    tag = LTO_cgraph_unavail_node;
 
   lto_output_uleb128_stream (ob->main_stream, tag);
   LTO_DEBUG_INDENT (tag);
@@ -313,7 +310,7 @@ output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   lto_output_sleb128_stream (ob->main_stream,
 			     node->global.stack_frame_offset);
   LTO_DEBUG_TOKEN ("inlined_to");
-  if (node->global.inlined_to)
+  if (node->global.inlined_to && !boundary_p)
     {
       ref = lto_cgraph_encoder_lookup (encoder, node->global.inlined_to);
       gcc_assert (ref != LCC_NOT_FOUND);
@@ -407,11 +404,9 @@ output_cgraph (cgraph_node_set set)
       for (edge = node->callees; edge; edge = edge->next_callee)
 	{
 	  struct cgraph_node *callee = edge->callee;
-	  /* We moved all the inlines. */
-	  if (callee->global.inlined_to != NULL)
-	    gcc_assert (cgraph_node_in_set_p (callee, set));
 	  if (!cgraph_node_in_set_p (callee, set))
 	    {
+	      /* We moved all the inlines. */
 	      gcc_assert (!callee->global.inlined_to);
 	      lto_cgraph_encoder_encode (encoder, callee);
 	    }
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index e8e21a1..1235dbc 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -607,7 +607,6 @@ lto_add_all_inlinees (cgraph_node_set set)
       for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
 	{
 	  struct cgraph_node *inlined_to;
-	  struct cgraph_node *caller;
 	  node = csi_node (csi);
 
 	  /* NODE was not inlined. We still need it. */
@@ -615,16 +614,12 @@ lto_add_all_inlinees (cgraph_node_set set)
 	    continue;
 
 	  inlined_to = node->global.inlined_to;
-	  caller = node->callers->caller;
 
 	  /* NODE should have only one caller */
 	  gcc_assert (!node->callers->next_caller);
 
-	  if (!bitmap_bit_p (original_nodes, inlined_to->uid)
-	      || !bitmap_bit_p (original_nodes, caller->uid))
+	  if (!bitmap_bit_p (original_nodes, inlined_to->uid))
 	    {
-	      gcc_assert (!bitmap_bit_p (original_nodes, inlined_to->uid));
-	      gcc_assert (!bitmap_bit_p (original_nodes, caller->uid));
 	      bitmap_clear_bit (original_nodes, node->uid);
 	      cgraph_node_set_remove (set, node);
 	      changed = true;
diff --git a/gcc/ipa.c b/gcc/ipa.c
index dc0b5bc..66c1d6b 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -175,7 +175,10 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		{
 		  struct cgraph_node *clone;
 
-		  for (clone = node->next_clone; clone;
+		  for (clone = node; clone->prev_clone;
+		       clone = clone->prev_clone)
+		    ;
+		  for (; clone;
 		       clone = clone->next_clone)
 		    if (clone->aux)
 		      break;
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 32deb8e..0f212eb 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -52,6 +52,7 @@ Boston, MA 02110-1301, USA.  */
 #include "lto-section-out.h"
 #include "pointer-set.h"
 #include "lto-tree-in.h"
+#include "lto-utils.h"
 
 /* Call-Graph Streamer.
 
@@ -156,35 +157,15 @@ const char * LTO_cgraph_tag_names[LTO_cgraph_last_tag] =
 {"", "avail", "overwrite", "unavail", "edge"};
 #endif
 
-/* Redirect inlined NODE to its master clone if it is not in SET. 
-   Return NODE itself if it is in SET or it is not inlined.  */
-
-static struct cgraph_node *
-maybe_redirect_inlined_node (struct cgraph_node *node, cgraph_node_set set)
-{
-  struct cgraph_node *master_clone;
-
-  if (!cgraph_node_in_set_p (node, set) && node->global.inlined_to != NULL)
-    {
-      master_clone = node->master_clone;
-      gcc_assert (master_clone && master_clone != node);
-      return master_clone;
-    }
-  else
-    return node;
-}
-
 /* Output the cgraph EDGE to OB using ENCODER.  */
 
 static void
 output_edge (struct lto_simple_output_block *ob,
-	     struct cgraph_edge *edge, lto_cgraph_encoder_t encoder,
-	     cgraph_node_set set)
+	     struct cgraph_edge *edge, lto_cgraph_encoder_t encoder)
 {
   unsigned int uid;
   intptr_t ref;
   unsigned HOST_WIDEST_INT flags = 0;
-  struct cgraph_node *callee;
 
   lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_edge);
   LTO_DEBUG_INDENT (LTO_cgraph_edge);
@@ -195,8 +176,7 @@ output_edge (struct lto_simple_output_block *ob,
   lto_output_sleb128_stream (ob->main_stream, ref);
 
   LTO_DEBUG_TOKEN ("callee");
-  callee = maybe_redirect_inlined_node (edge->callee, set);
-  ref = lto_cgraph_encoder_lookup (encoder, callee);
+  ref = lto_cgraph_encoder_lookup (encoder, edge->callee);
   gcc_assert (ref != LCC_NOT_FOUND); 
   lto_output_sleb128_stream (ob->main_stream, ref);
 
@@ -204,13 +184,8 @@ output_edge (struct lto_simple_output_block *ob,
   uid = flag_wpa ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt);
   lto_output_uleb128_stream (ob->main_stream, uid);
 
-  /* If we have redirected an inlined callee outside SET to its master
-     clone, mark edge as not inlined.  */
   LTO_DEBUG_TOKEN ("inline_failed");
-  if (callee != edge->callee)
-    lto_output_uleb128_stream (ob->main_stream, CIF_UNSPECIFIED);
-  else
-    lto_output_uleb128_stream (ob->main_stream, edge->inline_failed);
+  lto_output_uleb128_stream (ob->main_stream, edge->inline_failed);
 
   LTO_DEBUG_TOKEN ("count");
   lto_output_uleb128_stream (ob->main_stream, edge->count);
@@ -226,20 +201,21 @@ output_edge (struct lto_simple_output_block *ob,
 }
 
 
-/* Output the cgraph NODE to OB.  If BOUNDARY_P is true, NODE is a boundary
-   of a cgraph_node_set and we pretend NODE just have a decl and no callees.
-   WRITTEN_NODES are nodes written so far.  */
+/* Output the cgraph NODE to OB. ENCODER is used to find the reference
+   number of NODE->inlined_to. SET is the set of nodes we are writting to
+   the current file. WROTE_MASTER is a bitmap with which nodes had
+   a master (from ltrans perspective) written to the current file. */
 
 static void
 output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
-	     lto_cgraph_encoder_t encoder, cgraph_node_set set)
+	     lto_cgraph_encoder_t encoder, cgraph_node_set set,
+	     bitmap wrote_master)
 {
   unsigned int tag;
   unsigned HOST_WIDEST_INT flags = 0;
-  struct cgraph_node *master_clone = node->master_clone;
   unsigned local, externally_visible, inlinable;
   bool boundary_p = !cgraph_node_in_set_p (node, set);
-  bool clone_p = node->master_clone && node != node->master_clone;
+  bool wrote_master_p = bitmap_bit_p (wrote_master, DECL_UID (node->decl));
   intptr_t ref;
 
   switch (cgraph_function_body_availability (node))
@@ -262,10 +238,7 @@ output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
     }
  
   if (boundary_p)
-    {
-      gcc_assert (!clone_p);
-      tag = LTO_cgraph_unavail_node;
-    }
+    tag = LTO_cgraph_unavail_node;
 
   lto_output_uleb128_stream (ob->main_stream, tag);
   LTO_DEBUG_INDENT (tag);
@@ -297,21 +270,13 @@ output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
       inlinable = 1;
     }
 
-  LTO_DEBUG_TOKEN ("clone_p");
-  lto_output_uleb128_stream (ob->main_stream, clone_p);
+  LTO_DEBUG_TOKEN ("wrote_master_p");
+  lto_output_uleb128_stream (ob->main_stream, wrote_master_p);
 
-  if (clone_p)
-    {
-      intptr_t ref = lto_cgraph_encoder_lookup (encoder, master_clone);
-      LTO_DEBUG_TOKEN ("master");
-      gcc_assert (ref != LCC_NOT_FOUND);
-      lto_output_sleb128_stream (ob->main_stream, ref);
-    }
-  else
-    { 
-      lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
-      LTO_DEBUG_FN_NAME (node->decl);
-    }
+  if (!wrote_master_p)
+    bitmap_set_bit (wrote_master, DECL_UID (node->decl));
+
+  lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
 
   lto_set_flag (&flags, node->lowered);
   lto_set_flag (&flags, node->analyzed);
@@ -345,7 +310,7 @@ output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   lto_output_sleb128_stream (ob->main_stream,
 			     node->global.stack_frame_offset);
   LTO_DEBUG_TOKEN ("inlined_to");
-  if (node->global.inlined_to)
+  if (node->global.inlined_to && !boundary_p)
     {
       ref = lto_cgraph_encoder_lookup (encoder, node->global.inlined_to);
       gcc_assert (ref != LCC_NOT_FOUND);
@@ -379,9 +344,8 @@ output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
    master_clone nodes or nodes that have no function bodies.  */
 
 static void
-output_cgraph_verify_node (cgraph_node_set set, struct cgraph_node *node)
+output_cgraph_verify_node (struct cgraph_node *node)
 {
-  struct cgraph_node *master_clone;
   switch (cgraph_function_body_availability (node))
     {
     case AVAIL_UNSET:
@@ -395,13 +359,6 @@ output_cgraph_verify_node (cgraph_node_set set, struct cgraph_node *node)
     case AVAIL_OVERWRITABLE:
     case AVAIL_AVAILABLE:
     case AVAIL_LOCAL:
-      master_clone = cgraph_master_clone (node, false);
-      if  (node != master_clone
-	   && !cgraph_node_in_set_p (master_clone, set))
-	{
-	  fprintf (stderr, "found clone with no master\n.");
-	  gcc_assert (0);
-	}
       break;
     }
 }
@@ -414,7 +371,7 @@ output_cgraph_verify_node (cgraph_node_set set, struct cgraph_node *node)
 static void
 output_cgraph (cgraph_node_set set)
 {
-  struct cgraph_node *node, *callee, *master_clone;
+  struct cgraph_node *node;
   struct lto_simple_output_block *ob 
     = lto_create_simple_output_block (LTO_section_cgraph);
   cgraph_node_set_iterator csi;
@@ -422,6 +379,12 @@ output_cgraph (cgraph_node_set set)
   lto_cgraph_encoder_t encoder = lto_cgraph_encoder_new ();
   int i, n_nodes;
 
+  /* The decls for which we have written a master node. Note the the node
+     we select as master might not be the current master. In fact, the
+     current master might not be in the current file at all! That is
+     not a problem, since any of the clones can be the master. */
+  bitmap wrote_master = lto_bitmap_alloc ();
+
 #ifdef LTO_STREAM_DEBUGGING
   lto_debug_context.tag_names = LTO_cgraph_tag_names;
   lto_debug_context.stream_name = "cgraph";
@@ -431,26 +394,22 @@ output_cgraph (cgraph_node_set set)
   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
     {
       node = csi_node (csi);
-      /* Make sure master clone appears before other clones.  */
-      master_clone = node->master_clone;
-      if (master_clone != NULL && master_clone != node) 
-	{
-	  gcc_assert (cgraph_node_in_set_p (master_clone, set));
-	  lto_cgraph_encoder_encode (encoder, master_clone);
-	}
-	lto_cgraph_encoder_encode (encoder, node);
+      lto_cgraph_encoder_encode (encoder, node);
     }
 
-  /* Go over all the nodes again to include callees that are not in SET.
-     For inlined callee that are not in the set, redirect the edge to 
-     its master clone.  */
+  /* Go over all the nodes again to include callees that are not in SET. */
   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
     {
       node = csi_node (csi);
       for (edge = node->callees; edge; edge = edge->next_callee)
 	{
-	  callee = maybe_redirect_inlined_node (edge->callee, set);
-	  lto_cgraph_encoder_encode (encoder, callee);
+	  struct cgraph_node *callee = edge->callee;
+	  if (!cgraph_node_in_set_p (callee, set))
+	    {
+	      /* We moved all the inlines. */
+	      gcc_assert (!callee->global.inlined_to);
+	      lto_cgraph_encoder_encode (encoder, callee);
+	    }
 	}
     }
 
@@ -460,17 +419,18 @@ output_cgraph (cgraph_node_set set)
     {
       node = lto_cgraph_encoder_deref (encoder, i);
 #ifdef ENABLE_CHECKING
-      output_cgraph_verify_node (set, node);
+      output_cgraph_verify_node (node);
 #endif
-      output_node (ob, node, encoder, set);
+      output_node (ob, node, encoder, set, wrote_master);
     }
+  lto_bitmap_free (wrote_master);
 
   /* Go over the nodes in SET again to write edges.  */
   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
     {
       node = csi_node (csi);
       for (edge = node->callees; edge; edge = edge->next_callee)
-	output_edge (ob, edge, encoder, set);
+	output_edge (ob, edge, encoder);
     }
 
   lto_output_uleb128_stream (ob->main_stream, 0);
@@ -523,8 +483,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
 static struct cgraph_node *
 input_node (struct lto_file_decl_data* file_data,
 	    struct lto_input_block *ib,
-	    enum LTO_cgraph_tags tag,
-	    VEC(cgraph_node_ptr, heap) *nodes)
+	    enum LTO_cgraph_tags tag)
 {
   tree fn_decl;
   struct cgraph_node *node, *master_clone;
@@ -532,7 +491,7 @@ input_node (struct lto_file_decl_data* file_data,
   int stack_size = 0;
   int self_insns = 0;
   unsigned decl_index;
-  bool clone_p;
+  bool wrote_master_p;
   int estimated_stack_size = 0;
   int stack_frame_offset = 0;
   int ref = LCC_NOT_FOUND;
@@ -540,23 +499,22 @@ input_node (struct lto_file_decl_data* file_data,
   int estimated_growth = 0;
   bool inlined = false;
 
-  LTO_DEBUG_TOKEN ("clone_p");
-  clone_p = lto_input_uleb128 (ib);
+  LTO_DEBUG_TOKEN ("wrote_master_p");
+  wrote_master_p = lto_input_uleb128 (ib);
 
-  if (clone_p)
+  decl_index = lto_input_uleb128 (ib);
+  fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
+
+  if (wrote_master_p)
     {
-      LTO_DEBUG_TOKEN ("master");
-      master_clone = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib));
+      /* Cannot use cgraph_master_clone in here. Fails assert that
+	 cgraph_function_flags_ready is true. */
+      master_clone = cgraph_node (fn_decl)->master_clone;
       gcc_assert (master_clone);
       node = cgraph_clone_input_node (master_clone);
     }
   else
-    {
-      decl_index = lto_input_uleb128 (ib);
-      fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
-      LTO_DEBUG_FN_NAME (fn_decl);
-      node = cgraph_node (fn_decl);
-    }
+    node = cgraph_node (fn_decl);
 
   LTO_DEBUG_TOKEN ("flags");
   flags = lto_input_uleb128 (ib);
@@ -723,7 +681,7 @@ input_cgraph_1 (struct lto_file_decl_data* file_data,
         input_edge (ib, nodes);
       else 
 	{
-	  node = input_node (file_data, ib, tag, nodes);
+	  node = input_node (file_data, ib, tag);
 	  gcc_assert (node);
 	  gcc_assert (node->decl);
 	  VEC_safe_push (cgraph_node_ptr, heap, nodes, node);
diff --git a/gcc/lto-function-out.c b/gcc/lto-function-out.c
index d983405..09030c4 100644
--- a/gcc/lto-function-out.c
+++ b/gcc/lto-function-out.c
@@ -2272,16 +2272,16 @@ lto_output (cgraph_node_set set)
   struct cgraph_node *node;
   struct lto_out_decl_state *decl_state;
   cgraph_node_set_iterator csi;
+  bitmap output = lto_bitmap_alloc ();
 
   lto_static_init_local ();
 
-  /* Process only the functions with bodies and only process the master
-     ones of them.  */
   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
     {
       node = csi_node (csi);
-      if (node->analyzed && cgraph_is_master_clone (node, false))
+      if (node->analyzed && !bitmap_bit_p (output, DECL_UID (node->decl)))
 	{
+	  bitmap_set_bit (output, DECL_UID (node->decl));
 	  decl_state = lto_new_out_decl_state ();
 	  lto_push_out_decl_state (decl_state);
 	  if (!flag_wpa)
@@ -2293,6 +2293,7 @@ lto_output (cgraph_node_set set)
 	  lto_record_function_out_decl_state (node->decl, decl_state);
 	}
     }
+  lto_bitmap_free (output);
 }
 
 struct ipa_opt_pass pass_ipa_lto_gimple_out =
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 05a0d40..1235dbc 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -558,32 +558,23 @@ finish:
 
 static void
 lto_add_inline_clones (cgraph_node_set set, struct cgraph_node *node,
-		       bitmap original_nodes, bitmap inlined_decls)
+		       bitmap original_decls, bitmap inlined_decls)
 {
-   struct cgraph_node *master_clone, *callee;
+   struct cgraph_node *callee;
    struct cgraph_edge *edge;
 
-   /* NODE must be an inlined clone.  Add both its master clone and node
-      itself to SET and mark the decls as inlined.  */
-   if (!bitmap_bit_p (original_nodes, node->uid))
-     {
-	master_clone = cgraph_master_clone (node, false);
-	gcc_assert (master_clone != NULL && master_clone != node);
-	if (!cgraph_node_in_set_p (master_clone, set))
-	  {
-	    cgraph_node_set_add (set, master_clone);
-	    bitmap_set_bit (inlined_decls, DECL_UID (node->decl));
-	  }
-	cgraph_node_set_add (set, node);
-     }
-   
+   cgraph_node_set_add (set, node);
+
+   if (!bitmap_bit_p (original_decls, DECL_UID (node->decl)))
+     bitmap_set_bit (inlined_decls, DECL_UID (node->decl));
+
    /* Check to see if NODE has any inlined callee.  */
    for (edge = node->callees; edge != NULL; edge = edge->next_callee)
      {
 	callee = edge->callee;
 	if (callee->global.inlined_to != NULL)
-	    lto_add_inline_clones (set, callee, original_nodes,
-				   inlined_decls);
+	  lto_add_inline_clones (set, callee, original_decls,
+				 inlined_decls);
      }
 }
 
@@ -597,21 +588,54 @@ lto_add_all_inlinees (cgraph_node_set set)
   cgraph_node_set_iterator csi;
   struct cgraph_node *node;
   bitmap original_nodes = lto_bitmap_alloc ();
+  bitmap original_decls = lto_bitmap_alloc ();
   bitmap inlined_decls = lto_bitmap_alloc();
+  bool changed;
 
   /* We are going to iterate SET will adding to it, mark all original
      nodes so that we only add node inlined to original nodes.  */
   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
-    bitmap_set_bit (original_nodes, csi_node (csi)->uid);
+    {
+      bitmap_set_bit (original_nodes, csi_node (csi)->uid);
+      bitmap_set_bit (original_decls, DECL_UID (csi_node (csi)->decl));
+    }
+
+  /* Some of the original nodes might not be needed anymore.  Remove them. */
+  do
+    {
+      changed = false;
+      for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+	{
+	  struct cgraph_node *inlined_to;
+	  node = csi_node (csi);
+
+	  /* NODE was not inlined. We still need it. */
+	  if (!node->global.inlined_to)
+	    continue;
+
+	  inlined_to = node->global.inlined_to;
+
+	  /* NODE should have only one caller */
+	  gcc_assert (!node->callers->next_caller);
+
+	  if (!bitmap_bit_p (original_nodes, inlined_to->uid))
+	    {
+	      bitmap_clear_bit (original_nodes, node->uid);
+	      cgraph_node_set_remove (set, node);
+	      changed = true;
+	    }
+	}
+    } while (changed);
 
   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
     {
       node = csi_node (csi);
       if (bitmap_bit_p (original_nodes, node->uid))
-	lto_add_inline_clones (set, node, original_nodes, inlined_decls);
+	lto_add_inline_clones (set, node, original_decls, inlined_decls);
     }
 
   lto_bitmap_free (original_nodes);
+  lto_bitmap_free (original_decls);
   return inlined_decls;
 }
 
@@ -741,8 +765,7 @@ lto_scan_statics_in_cgraph_node (struct cgraph_node *node,
   struct lto_in_decl_state *state;
   
   /* Return if NODE has no function body or is not the master clone. */
-  if (!node->analyzed
-      || (node->master_clone != NULL && node->master_clone != node))
+  if (!node->analyzed)
     return;
   
   /* Return if the DECL of nodes has been visited before.  */
diff --git a/gcc/testsuite/gcc.dg/lto/20090218-2_0.c b/gcc/testsuite/gcc.dg/lto/20090218-2_0.c
new file mode 100644
index 0000000..8857e7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/20090218-2_0.c
@@ -0,0 +1,3 @@
+void emit_push_insn () {
+  set_mem_alias_set ();
+}
diff --git a/gcc/testsuite/gcc.dg/lto/20090218-2_1.c b/gcc/testsuite/gcc.dg/lto/20090218-2_1.c
new file mode 100644
index 0000000..119fbe4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/20090218-2_1.c
@@ -0,0 +1,19 @@
+typedef struct {
+} mem_attrs;
+int main(void)
+{
+  return 0;
+}
+void *malloc(unsigned long size);
+void *memcpy(void *dest, const void *src, unsigned long n);
+static mem_attrs * get_mem_attrs () {
+  void **slot;
+  *slot = malloc (3);
+  memcpy (*slot, 0, 3);
+}
+void set_mem_attributes () {
+  get_mem_attrs ();
+}
+void set_mem_alias_set () {
+  get_mem_attrs ();
+}

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