Created attachment 32264 [details] preprocessed source see on https://bugs.launchpad.net/ubuntu/+source/mrpt/+bug/1286343 https://bugzilla.redhat.com/show_bug.cgi?id=1007586 seen on armv7, powerpc, ppc64el. lowering the optimization works around it $ g++ -std=c++11 -c -O3 -g CMetricMapBuilderICP.ii /root/mrpt-1.0.2/libs/slam/src/slam/CMetricMapBuilderICP.cpp:629:1: internal compiler error: Segmentation fault Please submit a full bug report, with preprocessed source if appropriate. Program received signal SIGSEGV, Segmentation fault. 0x0000000010ae517c in ?? () (gdb) bt #0 0x0000000010ae517c in ?? () #1 0x000000001056a0c0 in execute_one_pass(opt_pass*) () #2 0x000000001056ad88 in execute_ipa_pass_list(opt_pass*) () #3 0x000000001032ce28 in compile() () #4 0x000000001032d6cc in finalize_compilation_unit() () #5 0x000000001019017c in cp_write_global_declarations() () #6 0x000000001062b370 in ?? () #7 0x000000001062dafc in toplev_main(int, char**) () #8 0x000000001010ea88 in main ()
Attached code seems to be Power-specific: ... /usr/include/eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h:483:56: error: ‘__builtin_vec_sld’ was not declared in this scope
yes, the first attachment is for powepc64le-linux-gnu
Created attachment 32265 [details] preprocessed source (armv7)
This might have been fixed in trunk already, at least I can't repro for arm-v7a15. My fresh gcc is configured with ~/src/gcc-master/configure --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --target=arm-v7a15-linux-gnueabi --prefix=/home/ygribov/install/gcc-master-arm-full --with-sysroot=/home/ygribov/install/gcc-master-arm-full/arm-v7a15-linux-gnueabi/sys-root/ --disable-libmudflap --disable-libssp --disable-nls --disable-libstdcxx-pch --with-interwork --with-mode=arm --with-fpu=vfpv3 --with-cpu=cortex-a15 --with-tune=cortex-a15 --with-float=softfp --enable-libgomp --enable-poison-system-directories --enable-long-long --enable-threads --enable-languages=c,c++ --enable-shared --with-gnu-as --with-gnu-ld --with-build-time-tools=/home/ygribov/install/gcc-master-arm-full --enable-checking CFLAGS='-g -O0' CXXFLAGS='-g -O0'
Created attachment 32321 [details] pr60419.C This is quite impossible to reduce, at least after 4 days of attempting to delta/creduce reduce this I got only to 132KB. Compile with -m64 -O3 -std=c++11. Anyway, it is reduced enough that it compiles (and ICEs in a different place) with x86_64-linux cc1plus, so also shows a bug in slsr, with -m64 -O3 -std=c++11 -fno-tree-slsr it compiles with x86_64 target though and thus I can't bisect this on x86_64.
The slsr issue is just a pilot error, I've mistakenly used ~ r205NNN compiler in that case, so it looks like an already fixed issue. Anyway, the ICE on ppc64 with the reduced testcase started with r208184 (thus I wonder about the 4.8 regression status), the problem is that getMeanVal function (method?) calls _ZThn8_NK4mrpt5utils16CPosePDFGaussian7getMeanERNS_5poses7CPose2DE thunk that has NULL node->callee (without -fPIC it ICEs in one spot, with -fPIC in another one). node->callees is set to non-NULL in: #0 cgraph_create_edge (caller=<cgraph_node* 0x7ffff0f32148 "_ZThn8_NK4mrpt5utils16CPosePDFGaussian7getMeanERNS_5poses7CPose2DE">, callee=<cgraph_node* 0x7ffff0f32000 "*.LTHUNK0">, call_stmt=<gimple 0x0>, count=0, freq=1000) at ../../gcc/cgraph.c:927 #1 0x00000000008ffe81 in analyze_function ( node=<cgraph_node* 0x7ffff0f32148 "_ZThn8_NK4mrpt5utils16CPosePDFGaussian7getMeanERNS_5poses7CPose2DE">) at ../../gcc/cgraphunit.c:611 #2 0x00000000009010b4 in analyze_functions () at ../../gcc/cgraphunit.c:1017 #3 0x0000000000904979 in finalize_compilation_unit () at ../../gcc/cgraphunit.c:2320 #4 0x000000000068b61d in cp_write_global_declarations () at ../../gcc/cp/decl2.c:4612 #5 0x0000000000d0ee72 in compile_file () at ../../gcc/toplev.c:562 #6 0x0000000000d11015 in do_compile () at ../../gcc/toplev.c:1914 #7 0x0000000000d11180 in toplev_main (argc=8, argv=0x7fffffffe358) at ../../gcc/toplev.c:1990 #8 0x00000000012c0464 in main (argc=8, argv=0x7fffffffe358) at ../../gcc/main.c:36 and cleared again in: #0 cgraph_node_remove_callees (node=<cgraph_node* 0x7ffff0f32148 "_ZThn8_NK4mrpt5utils16CPosePDFGaussian7getMeanERNS_5poses7CPose2DE">) at ../../gcc/cgraph.c:1617 #1 0x0000000000b2dc63 in symtab_remove_unreachable_nodes (before_inlining_p=false, file=0x0) at ../../gcc/ipa.c:493 #2 0x000000000124c93f in ipa_inline () at ../../gcc/ipa-inline.c:2060 #3 0x000000000124d385 in (anonymous namespace)::pass_ipa_inline::execute (this=0x1c73710) at ../../gcc/ipa-inline.c:2412 #4 0x0000000000c299d6 in execute_one_pass (pass=<opt_pass* 0x1c73710 "inline"(53)>) at ../../gcc/passes.c:2229 #5 0x0000000000c2a71b in execute_ipa_pass_list (pass=<opt_pass* 0x1c73710 "inline"(53)>) at ../../gcc/passes.c:2607 #6 0x00000000009042ad in ipa_passes () at ../../gcc/cgraphunit.c:2084 #7 0x000000000090455e in compile () at ../../gcc/cgraphunit.c:2174 #8 0x0000000000904988 in finalize_compilation_unit () at ../../gcc/cgraphunit.c:2329 #9 0x000000000068b61d in cp_write_global_declarations () at ../../gcc/cp/decl2.c:4612 #10 0x0000000000d0ee72 in compile_file () at ../../gcc/toplev.c:562 #11 0x0000000000d11015 in do_compile () at ../../gcc/toplev.c:1914 #12 0x0000000000d11180 in toplev_main (argc=8, argv=0x7fffffffe358) at ../../gcc/toplev.c:1990 #13 0x00000000012c0464 in main (argc=8, argv=0x7fffffffe358) at ../../gcc/main.c:36 At that point the thunk apparently has no callers. But somewhat later it gains one: #0 cgraph_set_edge_callee (e=0x7fffef50a8f0, n=<cgraph_node* 0x7ffff0f32148 "_ZThn8_NK4mrpt5utils16CPosePDFGaussian7getMeanERNS_5poses7CPose2DE">) at ../../gcc/cgraph.c:1080 #1 0x00000000008f74a8 in cgraph_make_edge_direct (edge=0x7fffef50a8f0, callee=<cgraph_node* 0x7ffff0f32148 "_ZThn8_NK4mrpt5utils16CPosePDFGaussian7getMeanERNS_5poses7CPose2DE">) at ../../gcc/cgraph.c:1313 #2 0x0000000000b1f7ae in ipa_make_edge_direct_to_target (ie=0x7fffef50a8f0, target=<function_decl 0x7ffff0fc5a00 _ZThn8_NK4mrpt5utils16CPosePDFGaussian7getMeanERNS_5poses7CPose2DE>) at ../../gcc/ipa-prop.c:2551 #3 0x0000000000b20091 in try_make_edge_direct_virtual_call (ie=0x7fffef50a8f0, jfunc=0x7ffff085b078, new_root_info=0x1e4cce0) at ../../gcc/ipa-prop.c:2799 #4 0x0000000000b201e2 in update_indirect_edges_after_inlining (cs=0x7fffef9baf08, node=<cgraph_node* 0x7ffff0ad58f8 "getMeanVal">, new_edges=0x0) at ../../gcc/ipa-prop.c:2852 #5 0x0000000000b20476 in propagate_info_to_inlined_callees (cs=0x7fffef9baf08, node=<cgraph_node* 0x7ffff0ad58f8 "getMeanVal">, new_edges=0x0) at ../../gcc/ipa-prop.c:2924 #6 0x0000000000b20c3d in ipa_propagate_indirect_call_infos (cs=0x7fffef9baf08, new_edges=0x0) at ../../gcc/ipa-prop.c:3086 #7 0x000000000124e183 in inline_call (e=0x7fffef9baf08, update_original=true, new_edges=0x0, overall_size=0x0, update_overall_summary=true) at ../../gcc/ipa-inline-transform.c:277 #8 0x000000000124c6da in inline_to_all_callers (node=<cgraph_node* 0x7ffff0ad58f8 "getMeanVal">, data=0x7fffffffe024) at ../../gcc/ipa-inline.c:1987 #9 0x00000000008f9a18 in cgraph_for_node_and_aliases (node=<cgraph_node* 0x7ffff0ad58f8 "getMeanVal">, callback= 0x124c5f5 <inline_to_all_callers(cgraph_node*, void*)>, data=0x7fffffffe024, include_overwritable=true) at ../../gcc/cgraph.c:2212 #10 0x000000000124cacc in ipa_inline () at ../../gcc/ipa-inline.c:2118 #11 0x000000000124d385 in (anonymous namespace)::pass_ipa_inline::execute (this=0x1c73710) at ../../gcc/ipa-inline.c:2412 #12 0x0000000000c299d6 in execute_one_pass (pass=<opt_pass* 0x1c73710 "inline"(53)>) at ../../gcc/passes.c:2229 #13 0x0000000000c2a71b in execute_ipa_pass_list (pass=<opt_pass* 0x1c73710 "inline"(53)>) at ../../gcc/passes.c:2607 #14 0x00000000009042ad in ipa_passes () at ../../gcc/cgraphunit.c:2084 #15 0x000000000090455e in compile () at ../../gcc/cgraphunit.c:2174 #16 0x0000000000904988 in finalize_compilation_unit () at ../../gcc/cgraphunit.c:2329 #17 0x000000000068b61d in cp_write_global_declarations () at ../../gcc/cp/decl2.c:4612 #18 0x0000000000d0ee72 in compile_file () at ../../gcc/toplev.c:562 #19 0x0000000000d11015 in do_compile () at ../../gcc/toplev.c:1914 #20 0x0000000000d11180 in toplev_main (argc=8, argv=0x7fffffffe358) at ../../gcc/toplev.c:1990 #21 0x00000000012c0464 in main (argc=8, argv=0x7fffffffe358) at ../../gcc/main.c:36
Honza or Martin, can you please have a look? The #c5 testcase should be reproduceable with a cross to powerpc64-linux.
FYI, since r208573 the reduced ppc64 testcase no longer reproduces, but the #c0 still does.
Created attachment 32382 [details] reduced testcase Here's a reduced testcase that segfaults also on x86_64. markus@x4 tmp % g++ -std=c++11 -c -O2 -c test.ii ASAN:SIGSEGV ================================================================= ==17160==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000010 (pc 0x000000d9b9b7 sp 0x7fff7ac203c0 bp 0x0fffef5840a0 T0) #0 0xd9b9b6 in cgraph_function_node(cgraph_node*, availability*) ../../gcc/gcc/cgraph.c:2966 #1 0x25e6923 in propagate_pure_const ../../gcc/gcc/ipa-pure-const.c:1185 #2 0x25e6923 in propagate ../../gcc/gcc/ipa-pure-const.c:1483 #3 0x25e6923 in execute ../../gcc/gcc/ipa-pure-const.c:1536 #4 0x14b93cd in execute_one_pass(opt_pass*) ../../gcc/gcc/passes.c:2229 #5 0x14badd0 in execute_ipa_pass_list(opt_pass*) ../../gcc/gcc/passes.c:2607 #6 0xdb2bb1 in ipa_passes ../../gcc/gcc/cgraphunit.c:2084 #7 0xdb2bb1 in compile() ../../gcc/gcc/cgraphunit.c:2174 #8 0xdb484a in finalize_compilation_unit() ../../gcc/gcc/cgraphunit.c:2329 #9 0x84561a in cp_write_global_declarations() ../../gcc/gcc/cp/decl2.c:4610 #10 0x16aa252 in compile_file ../../gcc/gcc/toplev.c:562 #11 0x16af0db in do_compile ../../gcc/gcc/toplev.c:1914 #12 0x16af0db in toplev_main(int, char**) ../../gcc/gcc/toplev.c:1990 #13 0x7ff8fae69faf in __libc_start_main (/lib/libc.so.6+0x1ffaf) #14 0x5d9460 (/var/tmp/gcc_sani/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/4.9.0/cc1plus+0x5d9460)
A bit more reduced: markus@x4 tmp % cat test.ii namespace poses { } namespace utils { using namespace poses; } namespace poses { class J { public: J (); virtual void m_fn1 (int &p1, int); }; class I : utils::J { }; class D { public: virtual void m_fn1 (poses::I &) const; void m_fn2 () { I p; m_fn1 (p); } }; class K : utils::J, public utils::D { }; struct F { K *operator->(); }; class N : public K { void m_fn1 (int &p1, int); void m_fn1 (I &) const {} }; class L; struct M { L *operator->(); }; class L { public: F poseChange; }; class G { G (); }; } using namespace utils; M h; G::G () try { N f; f.m_fn2 (); throw; } catch (int) {} void fn1 () { h->poseChange->m_fn2 (); } markus@x4 tmp % g++ -c -O2 test.ii test.ii:68:40: internal compiler error: Segmentation fault
Good job reducing the testcase to something this small! Anyway, Jakub's analysis of what is going on is still correct and all the high level decisions that we do are IMHO correct too. The invocation of symtab_remove_unreachable_symbols that removes the callers is called with before_inlining_p set to false, even though that is not technically right, we are still in the middle of inlining because we are about to inline functions which are called only once. But the comment in function ipa_inline says this is deliberate because it helps to find the functions which are only called once. However, this means that when symtab_remove_unreachable_symbols correctly figures out that we can devirtualize to the offending thunk, it assumes that cannot lead to any further inlining. Because the thunk is keyed in another compilation unit, it decides it only needs to keep the symtab node but not the body. In its terminology, the node is in the "boundary". The way the function cripples these boundary nodes is actually the problem because it removes all callees but not the thunk flag. This leaves us with a thunk with no callee, something that should not happen (and there is even a bit in the call graph verifier that checks it). Later on, we do perform this devirtualization during inlining of functions only called once and connect the crippled thunk to the call graph. The first time we want to follow through it, we segfault. I believe that we do not want to allow thunks with no callees. This would mean changing every user of cgraph_function_node so that it can cope with NULL return value and that is ugly and inconvenient. This leaves us with two options. Either we make symtab_remove_unreachable_symbols keep callees of thunks when it keeps the thunk or we simply clear the thunk_p flag. Given that thunks and aliases are quite similar and we do clear the alias flag, and that this should only ever affect nodes that we are not going to output, I tend to believe the second approach is OK and of course it is much simpler. But before I propose the following fix on the mailing list, I'll try to build some big C++ application with it: diff --git a/gcc/ipa.c b/gcc/ipa.c index 572dba1..164de0d 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -488,6 +488,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) node->definition = false; node->cpp_implicit_alias = false; node->alias = false; + node->thunk.thunk_p = false; node->weakref = false; if (!node->in_other_partition) node->local.local = false;
Slightly more reduced testcase: --- gcc/testsuite/g++.dg/ipa/pr60419.C 2014-03-19 15:57:57.735114622 +0100 +++ gcc/testsuite/g++.dg/ipa/pr60419.C 2014-03-20 10:20:56.245365852 +0100 @@ -0,0 +1,68 @@ +// PR middle-end/60419 +// { dg-do compile } +// { dg-options "-O2" } + +struct J +{ + J (); + virtual void foo (int &, int); +}; + +struct D +{ + virtual void foo (J &) const; + void bar () + { + J p; + foo (p); + } +}; + +struct K : J, public D +{ +}; + +struct F +{ + K *operator->(); +}; + +struct N : public K +{ + void foo (int &, int); + void foo (J &) const {} +}; + +struct L +{ + F l; +}; + +struct M +{ + L *operator->(); +}; + +struct G +{ + G (); +}; + +M h; + +G::G () +try +{ + N f; + f.bar (); + throw; +} +catch (int) +{ +} + +void +baz () +{ + h->l->bar (); +}
The problem with both pasted testcases is that they don't crash 4.7.4. The attached one does.
(In reply to Markus Trippelsdorf from comment #13) > The problem with both pasted testcases is that they don't crash 4.7.4. 4.8.3 of course
So, what about (crashes trunk and 4.8.3) : class J { public: J (); virtual void m_fn1 (int &p1, int); }; template <class TDATA> class D { public: virtual void m_fn1 (TDATA &) const; void m_fn2 () { TDATA p; m_fn1 (p); } }; class I : J { }; class K : J, public D<I> { }; struct F { K *operator->(); }; class N : public K { void m_fn1 (int &p1, int); I mean; void m_fn1 (I &) const {} }; class L; struct M : F { L *operator->(); }; class L : J { public: F poseChange; }; class G { G (); }; M h; G::G () try { N f; f.m_fn2 (); throw; } catch (int) {} void fn1 () { h->poseChange->m_fn2 (); }
I have: --- gcc/testsuite/g++.dg/ipa/pr60419.C 2014-03-19 15:57:57.735114622 +0100 +++ gcc/testsuite/g++.dg/ipa/pr60419.C 2014-03-20 11:13:58.933256068 +0100 @@ -0,0 +1,80 @@ +// PR middle-end/60419 +// { dg-do compile } +// { dg-options "-O2" } + +struct C +{ +}; + +struct I : C +{ + I (); +}; + +struct J +{ + void foo (); + J (); + virtual void foo (int &, int); +}; + +template <class> +struct D +{ + virtual void foo (I &) const; + void bar () + { + I p; + foo (p); + } +}; + +struct K : J, public D<int> +{ +}; + +struct F +{ + K *operator->(); +}; + +struct N : public K +{ + void foo (int &, int); + I n; + void foo (I &) const {} +}; + +struct L : J +{ + F l; +}; + +struct M : F +{ + L *operator->(); +}; + +struct G +{ + G (); +}; + +M h; + +G::G () +try +{ + N f; + f.bar (); + throw; +} +catch (int) +{ +} + +void +baz () +{ + h->l->bar (); +}
Trunk patch posted to the mailing list: http://gcc.gnu.org/ml/gcc-patches/2014-03/msg01078.html 4.8 will need some slightly modified variant, I'm still looking for the best place to reset the flag there.
Author: jamborm Date: Fri Mar 21 12:48:02 2014 New Revision: 208747 URL: http://gcc.gnu.org/viewcvs?rev=208747&root=gcc&view=rev Log: 2014-03-21 Martin Jambor <mjambor@suse.cz> PR ipa/60419 * ipa.c (symtab_remove_unreachable_nodes): Clear thunk flag of nodes in the border. testsuite/ * g++.dg/ipa/pr60419.C: New test. Added: trunk/gcc/testsuite/g++.dg/ipa/pr60419.C Modified: trunk/gcc/ChangeLog trunk/gcc/ipa.c trunk/gcc/testsuite/ChangeLog
Fixed on the trunk so far.
Author: jamborm Date: Wed Mar 26 13:47:46 2014 New Revision: 208844 URL: http://gcc.gnu.org/viewcvs?rev=208844&root=gcc&view=rev Log: 2014-03-26 Martin Jambor <mjambor@suse.cz> PR ipa/60419 * ipa.c (symtab_remove_unreachable_nodes): Clear thunk and alias flags of nodes in the border. testsuite/ * g++.dg/ipa/pr60419.C: New test. Added: branches/gcc-4_8-branch/gcc/testsuite/g++.dg/ipa/pr60419.C Modified: branches/gcc-4_8-branch/gcc/ChangeLog branches/gcc-4_8-branch/gcc/ipa.c branches/gcc-4_8-branch/gcc/testsuite/ChangeLog
Fixed on 4.8 as well.