seen with r221076 on powerpc64le-linux-gnu $ g++ -c -g -O3 -fPIC eigenvalue.ii eigenvalue.ii:26:19: warning: direct base 'VirtualMatrice<int>' inaccessible in 'C<int>' due to ambiguity template <> class C<int> : H<Complex>, VirtualMatrice<Complex> { ^ eigenvalue.ii: In member function 'virtual bool C<int>::_ZThn8_NK1CIiE5m_fn1Ei(int) const': eigenvalue.ii:47:1: error: unrecognizable insn: } ^ (call_insn/j 3 2 4 (parallel [ (call (mem:SI (symbol_ref/i:DI ("_ZNK14VirtualMatriceIiE5m_fn1Ei") [flags 0x1] <function_decl 0x3fff9696fdf8 m_fn1>) [0 S4 A8]) (const_int 0 [0])) (use (const_int 0 [0])) (use (reg:SI 65 lr)) (simple_return) ]) eigenvalue.ii:27 -1 (nil) (nil)) eigenvalue.ii:47:1: internal compiler error: in insn_min_length, at config/rs6000/rs6000.md:7813 Please submit a full bug report, with preprocessed source if appropriate. $cat eigenvalue.ii template <class> class A; template <class R> struct VirtualMatrice { virtual bool m_fn1(int) const { return true; } struct B { A<R> x; B(VirtualMatrice *p1, A<R> p2) : x(p2) { p1->m_fn1(0) ?: throw; } }; void operator*(A<R> p1) { B(this, p1); } ~VirtualMatrice(); } ; template <class> class A { public: operator int *(); A(int *, long); }; class G : public A<int> { public: G(long); }; int typedef Complex; template <class> class H : VirtualMatrice<int> {}; template <class> class C; template <> class C<int> : H<Complex>, VirtualMatrice<Complex> { bool m_fn1(int) const { return true; } }; template <class K, class Mat> void DoIdoAction(int, int, A<K> p3, A<K>, A<K>, A<K>, Mat, Mat &p8) { p8 *p3; } class D { typedef int K; class F { int operator()() const; }; }; int D::F::operator()() const { VirtualMatrice<K> *a; VirtualMatrice<K> b, &B = *a; G c(0), g(1); int d, e, f; A<K> h(&g[f], 0), i(&g[e], 0), j(&g[d], 0); DoIdoAction(0, 3, h, i, j, c, b, B); }
This is caused by revision 221040 +2015-02-26 Jan Hubicka <hubicka@ucw.cz> + Martin Liska <mliska@suse.cz> + + PR bootstrap/65150 [snip] #2 0x0000000000bca3fa in _fatal_insn_not_found (insn=insn@entry=0x7ffff6ae4ca8, file=file@entry=0x13852e0 "/src/gcc-current/gcc/config/rs6000/rs6000.md", line=line@entry=7813, function=function@entry=0x139c330 <insn_min_length(rtx_insn*)::__FUNCTION__> "insn_min_length") at /src/gcc-current/gcc/rtl-error.c:118 #3 0x0000000000f1e9f2 in insn_min_length (insn=insn@entry=0x7ffff6ae4ca8) at /src/gcc-current/gcc/config/rs6000/rs6000.md:7813 #4 0x000000000095c8e2 in shorten_branches (first=0x7ffff6ad8038) at /src/gcc-current/gcc/final.c:1221 #5 0x0000000000eea239 in rs6000_output_mi_thunk (file=0x1c37950, thunk_fndecl=<optimised out>, delta=<optimised out>, vcall_offset=<optimised out>, function=<optimised out>) at /src/gcc-current/gcc/config/rs6000/rs6000.c:25835 That's here: /* Run just enough of rest_of_compilation to get the insns emitted. There's not really enough bulk here to make other passes such as instruction scheduling worth while. Note that use_thunk calls assemble_start_function and assemble_end_function. */ insn = get_insns (); shorten_branches (insn);
Hmm, this seems interesting. The revision enabled more merging in ICF. The expansion dies in output MI thunk that is not ICF produced thunk. So only conclussion I can think of is that ICF redirected call in thunk that made the target dependent code go wrong. What is wrong about the insn? Does the declaration of functions differ significantly? Let me see if I can reproduce that in a cross.
Semantic equality hit:bool VirtualMatrice<R>::m_fn1(int) const [with R = int]->virtual bool C<int>::m_fn1(int) const Assembler symbol names:_ZNK14VirtualMatriceIiE5m_fn1Ei->_ZNK1CIiE5m_fn1Ei Wrapper cannot be created because of COMDAT 1 local calls have been redirected. Unified; Function body was removed. I assume the problem is that thunk can not be generated to non-local symbol. I specifically prevent comdat local symbols to be produced because these makes inlining harder. There are couple options. First would be to punt redirection on thunks calls, second would be to produce local alias for thunk calls. I.e. check TARGET_USE_LOCAL_THUNK_ALIAS_P and produce the local alias specifically for thunks. Third would be to produce the local alias always. I guess first is safest - while I plan to turn thunks to use noninterposable alias path, I did not because I fear undocumented target issues. Bettter to not start with these in stage4. I will prepare patch after dinner
> I assume the problem is that thunk can not be generated to non-local symbol. Yes, that is at the root of this problem. The thunk can't be allowed to jump to anything outside the current object file. The pattern is a sibcall_local64 except that the symbol_ref doesn't match rs6000/predicates.md: current_file_function_operand.
Hi, the following (untested) patch should prevent redirection to happen. Index: ipa-icf.c =================================================================== --- ipa-icf.c (revision 221096) +++ ipa-icf.c (working copy) @@ -697,12 +697,22 @@ redirect_all_callers (cgraph_node *n, cg { int nredirected = 0; ipa_ref *ref; + cgraph_edge *e = n->callers; - while (n->callers) + while (e) { - cgraph_edge *e = n->callers; - e->redirect_callee (to); - nredirected++; + /* Redirecting thunks to interposable symbols or symbols in other sections + may not be supported by target output code. Play safe for now and + punt on redirection. */ + if (!e->caller->thunk.thunk_p) + { + struct cgraph_edge *nexte = e->next_callee; + e->redirect_callee (to); + e = nexte; + nredirected++; + } + else + e = e->next_callee; } for (unsigned i = 0; n->iterate_direct_aliases (i, ref);) { @@ -726,6 +736,17 @@ redirect_all_callers (cgraph_node *n, cg return nredirected; } +/* Return true if NODE has thunk. */ + +bool +has_thunk_p (cgraph_node *node, void *) +{ + for (cgraph_edge *e = node->callers; e; e = e->next_caller) + if (e->caller->thunk.thunk_p) + return true; + return false; +} + /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can be applied. */ @@ -907,6 +928,7 @@ sem_function::merge (sem_item *alias_ite return false; } if (!create_wrapper + && !alias->call_for_symbol_and_aliases (has_thunk_p, NULL, true) && !alias->can_remove_if_no_direct_calls_p ()) { if (dump_file)
rev 221098 plus the patch segfaults on the testcase in cgraph_node::function_symbol. node->callees is NULL.
Created attachment 34922 [details] Suggested patch There's fixed version of the patch: 1) If I see correctly, there was error in: struct cgraph_edge *nexte = e->next_callee 2) We should not remove alias if there's a thunk that wasn't redirected 3) gcc_assert must be changed for these cases Patch can run the testcase and survives FF with -O3 and -flto. Regression tests have been running. Martin
r221040 is also possibly causing: ../sysdeps/gnu/siglist.c:77:1: internal compiler error: in address_matters_p, at symtab.c:1908 when building trunk GLIBC (seen with GCC @r221125; same source builds with GCC @r220312).
Paul, I fixed similar bug yesterday, so please check if it works now for you and if not, please make new PR with a preprocessed source.
(In reply to Jan Hubicka from comment #9) > Paul, I fixed similar bug yesterday, so please check if it works now I just built at current SVN trunk (r221126). Filed PR 65287
Martin, your patch passes bootstrap and regression testing on powerpc64-linux.
Author: marxin Date: Tue Mar 3 09:26:20 2015 New Revision: 221134 URL: https://gcc.gnu.org/viewcvs?rev=221134&root=gcc&view=rev Log: Fix PR ipa/65263. PR ipa/65263 * cgraph.c (cgraph_node::has_thunk_p): New function. * cgraph.h (cgraph_node::has_thunk_p: Likewise. * ipa-icf.c (redirect_all_callers): Do not redirect thunks. (sem_function::merge): Assert is changed. * g++.dg/ipa/pr65263.C: New test. Added: trunk/gcc/testsuite/g++.dg/ipa/pr65263.C Modified: trunk/gcc/ChangeLog trunk/gcc/cgraph.c trunk/gcc/cgraph.h trunk/gcc/ipa-icf.c trunk/gcc/testsuite/ChangeLog
Fixed in 5.0.
*** Bug 65278 has been marked as a duplicate of this bug. ***