Hi, PR 58106 happens because the reference description duplication code cannot deal with existence of master_nodes of recursive inlining. It did not put rdescs pertaining to edges going out of these nodes to the lookup linked list (because they do not seem to be inlined into anything) but the remapping of "not-this-edge" rdesc pointers looked for them there - and also need to consider that the rdesc edge caller is not inlined into anything to find them.
So this patch puts all rdesc clones to the lookup linked list and updates the search criteria and fixes the issue. I have looked at how often we duplicate rdescs and we do it very rarely, 26 times in whole SPEC 2006 at -Ofast for example. This is expected because we create them only constant jump functions with addresses of functions. In order to build a long lookup list which could potentially be a compile time hog, such an edge would need to be inlined and we'd have to inline its caller massively, the length grows linearly with the number of inline clones and the number of searches as well. Bootstrapped and tested on x86_64-linux, OK for trunk? Thanks, Martin 2013-08-27 Martin Jambor <mjam...@suse.cz> PR ipa/58106 * ipa-prop.c (ipa_edge_duplication_hook): Always put new rdesc to the linked list. When finding the correct duplicate, also consider also the caller in additon to its inlined_to node. testsuite/ * gcc.dg/ipa/pr58106.c: New test. Index: src/gcc/ipa-prop.c =================================================================== --- src.orig/gcc/ipa-prop.c +++ src/gcc/ipa-prop.c @@ -2964,11 +2964,8 @@ ipa_edge_duplication_hook (struct cgraph = (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool); dst_rdesc->cs = dst; dst_rdesc->refcount = src_rdesc->refcount; - if (dst->caller->global.inlined_to) - { - dst_rdesc->next_duplicate = src_rdesc->next_duplicate; - src_rdesc->next_duplicate = dst_rdesc; - } + dst_rdesc->next_duplicate = src_rdesc->next_duplicate; + src_rdesc->next_duplicate = dst_rdesc; dst_jf->value.constant.rdesc = dst_rdesc; } else @@ -2983,9 +2980,14 @@ ipa_edge_duplication_hook (struct cgraph for (dst_rdesc = src_rdesc->next_duplicate; dst_rdesc; dst_rdesc = dst_rdesc->next_duplicate) - if (dst_rdesc->cs->caller->global.inlined_to - == dst->caller->global.inlined_to) - break; + { + struct cgraph_node *top; + top = dst_rdesc->cs->caller->global.inlined_to + ? dst_rdesc->cs->caller->global.inlined_to + : dst_rdesc->cs->caller; + if (dst->caller->global.inlined_to == top) + break; + } gcc_assert (dst_rdesc); dst_jf->value.constant.rdesc = dst_rdesc; } Index: src/gcc/testsuite/gcc.dg/ipa/pr58106.c =================================================================== --- /dev/null +++ src/gcc/testsuite/gcc.dg/ipa/pr58106.c @@ -0,0 +1,50 @@ +/* PR 58106 testcase. Verify that redsc chain creating and lookup works with + recursive inlining and master clone creation. */ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +typedef struct rtx_def *rtx; +enum rtx_code { + LAST_AND_UNUSED_RTX_CODE}; +extern const char * const rtx_format[((int) LAST_AND_UNUSED_RTX_CODE)]; +struct rtx_def { + enum rtx_code code; +}; +typedef int (*rtx_function) (rtx *, void *); +extern int for_each_rtx (rtx *, rtx_function, void *); +int +replace_label (rtx *x, void *data) +{ + rtx l = *x; + if (l == (rtx) 0) + { + { + rtx new_c, new_l; + for_each_rtx (&new_c, replace_label, data); + } + } +} +static int +for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data) +{ + int result, i, j; + const char *format = (rtx_format[(int) (((enum rtx_code) (exp)->code))]); + rtx *x; + for (; format[n] != '\0'; n++) + { + switch (format[n]) + { + case 'e': + result = (*f) (x, data); + { + result = for_each_rtx_1 (*x, i, f, data); + } + } + } +} +int +for_each_rtx (rtx *x, rtx_function f, void *data) +{ + int i; + return for_each_rtx_1 (*x, i, f, data); +}