Command line: $ g++ -O2 -fipa-cp-clone -flto -nostdlib -r file1.cpp file2.cpp Compiler output: $ g++ -O2 -fipa-cp-clone -flto -nostdlib -r file1.cpp file2.cpp lto1: error: inlined_to pointer is set but no predecessors found _ZN1S2v1Ev.constprop.1/6(-1) @0x7f44a7e9eac0 (asm: _ZN1S2v1Ev.constprop.1) (inline copy in foo/0) (clone of _ZN1S2v1Ev.constprop.1/1) availability:local analyzed 13 time, 12 benefit 4 size, 3 benefit reachable body local finalized inlinable called by: calls: v2/5 (1.00 per call) References: var:s (addr) Refering this function: lto1: internal compiler error: verify_cgraph_node failed Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. lto-wrapper: /mnt/svn/gcc-trunk/binary-164077-lto-fortran-checking-yes-rtl-df/bin/g++ returned 1 exit status collect2: lto-wrapper returned 1 exit status Tested revisions:
Created attachment 21757 [details] archive with reduced testcase $ g++ -O2 -fipa-cp-clone -flto -nostdlib -r file1.cpp file2.cpp ----- file1.cpp ----- #include "header.h" void foo () { s.v1 (); s.m (); } --------------------- ----- file2.cpp ----- #include "header.h" void S::v1 () { v2 (); } void S::m () { v1 (); } --------------------- ----- header.h ----- struct S { void m (); virtual void v1 (); virtual void v2 (); }; extern S s; -------------------- I pressed "Commit" too early, so there is the rest: Tested revisions: r164077 - crash r164096 - crash r161659 - OK
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
testing patch.
Created attachment 21818 [details] proposed patch
Any update?
The testing went fine, I just wanted to give more tought if some cheaper self testing can be made instead of keeping clone info and then forgot about the patch. Will re-test and commit.
Author: hubicka Date: Fri Oct 15 01:20:55 2010 New Revision: 165492 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=165492 Log: PR middle-end/45621 * g++.dg/lto/pr45621.h : New. * g++.dg/lto/pr45621_0.C: New. * g++.dg/lto/pr45621_1.C: New. * cgraph.c (cgraph_update_edges_for_call_stmt_node): When new call is redirected to clone, be happy. * cgraph.h (cgraph node): Enable former_clone_of unconditinally. * cgraphunit.c (verify_cgraph_node, cgraph_materialize_clone): Handle former_clone_of unconditinally. Added: trunk/gcc/testsuite/g++.dg/lto/pr45621.h trunk/gcc/testsuite/g++.dg/lto/pr45621_0.C trunk/gcc/testsuite/g++.dg/lto/pr45621_1.C Modified: trunk/gcc/ChangeLog trunk/gcc/cgraph.c trunk/gcc/cgraph.h trunk/gcc/cgraphunit.c trunk/gcc/testsuite/ChangeLog
Fixed.