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 <mjam...@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. 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(); }