------- Comment #2 from hubicka at gcc dot gnu dot org 2010-09-17 01:05 ------- OK, problem is that we both devirtualize and clone the destination function. Then when producing clone, we run into: cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node, gimple old_stmt, tree old_call, gimple new_stmt) { tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fndecl (new_stmt) : 0;
/* We are seeing indirect calls, then there is nothing to update. */ if (!new_call && !old_call) return; /* See if we turned indirect call into direct call or folded call to one builtin into different bultin. */ if (old_call != new_call) { struct cgraph_edge *e = cgraph_edge (node, old_stmt); struct cgraph_edge *ne = NULL; gcov_type count; int frequency; int loop_nest; if (e) { /* See if the edge is already there and has the correct callee. It might be so because of indirect inlining has already updated it. */ if (new_call && e->callee && e->callee->decl == new_call) return; /* Otherwise remove edge and create new one; we can't simply redirect since function has changed, so inline plan and other information attached to edge is invalid. */ and kill the inline plan. This code is intended to handle bulitins, I guess we will need to look out if the decl can be redirected to decl in the function. Honza -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45621