diff mbox

[PR,59736] Fix an IPA-CP issue with de-speculation

Message ID 20140117171902.GJ23848@virgil.suse
State New
Headers show

Commit Message

Martin Jambor Jan. 17, 2014, 5:19 p.m. UTC
Hi,

in PR 59736, IPA-CP stumples on an already removed call graph edge.
The reason is that it keeps an internal linked list of edge clones
which can however now be corrupted by cgraph de-speculation machinery
which can decide to remove an edge.

In order to fix this, I made the linked-list bi-directional and added
a remove hook that fixes it up if need be.

Bootstrapped and tedted on x86_64-linux.  Unfortunately, I don't have
a simple testcase (the smallest I have is a 8.3K multidetla reduced
mess).  OK for trunk anyway?

Thanks,

Martin


2014-01-17  Martin Jambor  <mjambor@suse.cz>

	PR ipa/59736
	* ipa-cp.c (prev_edge_clone): New variable.
	(grow_next_edge_clone_vector): Renamed to grow_edge_clone_vectors.
	Also resize prev_edge_clone vector.
	(ipcp_edge_duplication_hook): Also update prev_edge_clone.
	(ipcp_edge_removal_hook): New function.
	(ipcp_driver): Register ipcp_edge_removal_hook.

Comments

Jan Hubicka Jan. 17, 2014, 5:27 p.m. UTC | #1
> Hi,
> 
> in PR 59736, IPA-CP stumples on an already removed call graph edge.
> The reason is that it keeps an internal linked list of edge clones
> which can however now be corrupted by cgraph de-speculation machinery
> which can decide to remove an edge.
> 
> In order to fix this, I made the linked-list bi-directional and added
> a remove hook that fixes it up if need be.
> 
> Bootstrapped and tedted on x86_64-linux.  Unfortunately, I don't have
> a simple testcase (the smallest I have is a 8.3K multidetla reduced
> mess).  OK for trunk anyway?
> 
> Thanks,
> 
> Martin
> 
> 
> 2014-01-17  Martin Jambor  <mjambor@suse.cz>
> 
> 	PR ipa/59736
> 	* ipa-cp.c (prev_edge_clone): New variable.
> 	(grow_next_edge_clone_vector): Renamed to grow_edge_clone_vectors.
> 	Also resize prev_edge_clone vector.
> 	(ipcp_edge_duplication_hook): Also update prev_edge_clone.
> 	(ipcp_edge_removal_hook): New function.
> 	(ipcp_driver): Register ipcp_edge_removal_hook.

OK,
thanks!
Honza
diff mbox

Patch

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index a6a44e6..10fa4b6 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -2321,13 +2321,17 @@  ipcp_discover_new_direct_edges (struct cgraph_node *node,
    edge. */
 
 static vec<cgraph_edge_p> next_edge_clone;
+static vec<cgraph_edge_p> prev_edge_clone;
 
 static inline void
-grow_next_edge_clone_vector (void)
+grow_edge_clone_vectors (void)
 {
   if (next_edge_clone.length ()
       <=  (unsigned) cgraph_edge_max_uid)
     next_edge_clone.safe_grow_cleared (cgraph_edge_max_uid + 1);
+  if (prev_edge_clone.length ()
+      <=  (unsigned) cgraph_edge_max_uid)
+    prev_edge_clone.safe_grow_cleared (cgraph_edge_max_uid + 1);
 }
 
 /* Edge duplication hook to grow the appropriate linked list in
@@ -2335,13 +2339,34 @@  grow_next_edge_clone_vector (void)
 
 static void
 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
-			    __attribute__((unused)) void *data)
+			    void *)
 {
-  grow_next_edge_clone_vector ();
-  next_edge_clone[dst->uid] = next_edge_clone[src->uid];
+  grow_edge_clone_vectors ();
+
+  struct cgraph_edge *old_next = next_edge_clone[src->uid];
+  if (old_next)
+    prev_edge_clone[old_next->uid] = dst;
+  prev_edge_clone[dst->uid] = src;
+
+  next_edge_clone[dst->uid] = old_next;
   next_edge_clone[src->uid] = dst;
 }
 
+/* Hook that is called by cgraph.c when an edge is removed.  */
+
+static void
+ipcp_edge_removal_hook (struct cgraph_edge *cs, void *)
+{
+  grow_edge_clone_vectors ();
+
+  struct cgraph_edge *prev = prev_edge_clone[cs->uid];
+  struct cgraph_edge *next = next_edge_clone[cs->uid];
+  if (prev)
+    next_edge_clone[prev->uid] = next;
+  if (next)
+    prev_edge_clone[next->uid] = prev;
+}
+
 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a
    parameter with the given INDEX.  */
 
@@ -3568,13 +3593,17 @@  static unsigned int
 ipcp_driver (void)
 {
   struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
+  struct cgraph_edge_hook_list *edge_removal_hook_holder;
   struct topo_info topo;
 
   ipa_check_create_node_params ();
   ipa_check_create_edge_args ();
-  grow_next_edge_clone_vector ();
+  grow_edge_clone_vectors ();
   edge_duplication_hook_holder =
     cgraph_add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL);
+  edge_removal_hook_holder =
+    cgraph_add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
+
   ipcp_values_pool = create_alloc_pool ("IPA-CP values",
 					sizeof (struct ipcp_value), 32);
   ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources",
@@ -3600,6 +3629,7 @@  ipcp_driver (void)
   /* Free all IPCP structures.  */
   free_toporder_info (&topo);
   next_edge_clone.release ();
+  cgraph_remove_edge_removal_hook (edge_removal_hook_holder);
   cgraph_remove_edge_duplication_hook (edge_duplication_hook_holder);
   ipa_free_all_structures_after_ipa_cp ();
   if (dump_file)