Patchwork [PR,58389] Do not attempt to use reference descriptions associated with removed edges

login
register
mail settings
Submitter Martin Jambor
Date Sept. 12, 2013, 11:49 a.m.
Message ID <20130912114950.GH6732@virgil.suse>
Download mbox | patch
Permalink /patch/274532/
State New
Headers show

Comments

Martin Jambor - Sept. 12, 2013, 11:49 a.m.
Hi,

PR 58389 is another case where the reference removal code, which is
now also called from the edge removal hook, ICEs when inlined edges
are not removed in topological order, which ins not the case when we
are removing unreachable nodes.

I'd like to fix it by the patch below.  When removing an edge which
has a reference descriptor pointing back to it, we set that pointer to
NULL and check for non-NULLness when we want to use it.  Reference
descriptors die only when their allocation pool does so that pointer
is never stale.

Bootstrapped and tested on x86_64-linux, OK for trunk?

Thanks,

Martin


2013-09-11  Martin Jambor  <mjambor@suse.cz>

	PR ipa/58389
	* ipa-prop.c (remove_described_reference): Give up if the edge in the
	reference descriptor is NULL.
	(ipa_edge_removal_hook): If owning a reference descriptor, set its
	edge to NULL.

testsuite/
	* g++.dg/pr58389.C: New test.
Jan Hubicka - Sept. 12, 2013, 12:32 p.m.
> Hi,
> 
> PR 58389 is another case where the reference removal code, which is
> now also called from the edge removal hook, ICEs when inlined edges
> are not removed in topological order, which ins not the case when we
> are removing unreachable nodes.
> 
> I'd like to fix it by the patch below.  When removing an edge which
> has a reference descriptor pointing back to it, we set that pointer to
> NULL and check for non-NULLness when we want to use it.  Reference
> descriptors die only when their allocation pool does so that pointer
> is never stale.
> 
> Bootstrapped and tested on x86_64-linux, OK for trunk?
> 
> Thanks,
> 
> Martin
> 
> 
> 2013-09-11  Martin Jambor  <mjambor@suse.cz>
> 
> 	PR ipa/58389
> 	* ipa-prop.c (remove_described_reference): Give up if the edge in the
> 	reference descriptor is NULL.
> 	(ipa_edge_removal_hook): If owning a reference descriptor, set its
> 	edge to NULL.

OK,
thanks
Honza

Patch

Index: src/gcc/ipa-prop.c
===================================================================
--- src.orig/gcc/ipa-prop.c
+++ src/gcc/ipa-prop.c
@@ -2506,6 +2506,8 @@  remove_described_reference (symtab_node
   struct cgraph_edge *origin;
 
   origin = rdesc->cs;
+  if (!origin)
+    return false;
   to_del = ipa_find_reference ((symtab_node) origin->caller, symbol,
 			       origin->call_stmt, origin->lto_stmt_uid);
   if (!to_del)
@@ -3019,7 +3021,14 @@  ipa_edge_removal_hook (struct cgraph_edg
       struct ipa_jump_func *jf;
       int i;
       FOR_EACH_VEC_ELT (*args->jump_functions, i, jf)
-	try_decrement_rdesc_refcount (jf);
+	{
+	  struct ipa_cst_ref_desc *rdesc;
+	  try_decrement_rdesc_refcount (jf);
+	  if (jf->type == IPA_JF_CONST
+	      && (rdesc = ipa_get_jf_constant_rdesc (jf))
+	      && rdesc->cs == cs)
+	    rdesc->cs = NULL;
+	}
     }
 
   ipa_free_edge_args_substructures (IPA_EDGE_REF (cs));
Index: src/gcc/testsuite/g++.dg/pr58389.C
===================================================================
--- /dev/null
+++ src/gcc/testsuite/g++.dg/pr58389.C
@@ -0,0 +1,54 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+template <typename _RandomAccessIterator, typename _Compare>
+void __insertion_sort(_RandomAccessIterator, _Compare);
+template <typename _RandomAccessIterator, typename _Compare>
+void __final_insertion_sort(_RandomAccessIterator p1, _Compare p2) {
+  _RandomAccessIterator a;
+  if (p1 - a)
+    ;
+  else
+  std:
+  __insertion_sort(0, p2);
+}
+template <typename _RandomAccessIterator, typename _Size, typename _Compare>
+void __introsort_loop(_RandomAccessIterator, _Size, _Compare);
+template <typename _RandomAccessIterator, typename _Compare>
+void sort(_RandomAccessIterator, _RandomAccessIterator p2, _Compare p3) {
+std:
+  __introsort_loop(0, 0, p3);
+  __final_insertion_sort(p2, p3);
+}
+class A {
+public:
+  int m_fn1();
+  void __lg();
+  class B {
+  public:
+    int i;
+    int operator-(B);
+  };
+};
+class C;
+class D {
+public:
+  C *operator->();
+};
+class F {
+  A m_fn1() const;
+  D d_ptr;
+};
+class C {
+  friend F;
+  void m_fn1();
+  A children;
+};
+void qt_notclosestLeaf();
+inline void C::m_fn1() {
+  A::B b, c;
+  if (children.m_fn1()) {
+    sort(c, b, qt_notclosestLeaf);
+  }
+}
+A F::m_fn1() const { const_cast<F *>(this)->d_ptr->m_fn1(); }