Hi! This is yet another occurrence of the bug that we drop lhs on noreturn calls even when it actually should not be dropped (if it has addressable type or if it is a variable length type).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-01-30 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/79267 * value-prof.c (gimple_ic): Only drop lhs for noreturn calls if should_remove_lhs_p is true. * g++.dg/opt/pr79267.C: New test. --- gcc/value-prof.c.jj 2017-01-01 12:45:38.000000000 +0100 +++ gcc/value-prof.c 2017-01-30 12:30:47.179820533 +0100 @@ -1358,7 +1358,8 @@ gimple_ic (gcall *icall_stmt, struct cgr dcall_stmt = as_a <gcall *> (gimple_copy (icall_stmt)); gimple_call_set_fndecl (dcall_stmt, direct_call->decl); dflags = flags_from_decl_or_type (direct_call->decl); - if ((dflags & ECF_NORETURN) != 0) + if ((dflags & ECF_NORETURN) != 0 + && should_remove_lhs_p (gimple_call_lhs (dcall_stmt))) gimple_call_set_lhs (dcall_stmt, NULL_TREE); gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT); --- gcc/testsuite/g++.dg/opt/pr79267.C.jj 2017-01-30 12:36:07.605516857 +0100 +++ gcc/testsuite/g++.dg/opt/pr79267.C 2017-01-30 12:35:51.000000000 +0100 @@ -0,0 +1,69 @@ +// PR tree-optimization/79267 +// { dg-do compile } +// { dg-options "-O3" } + +struct A { A (int); }; +struct B +{ + virtual void av () = 0; + void aw (); + void h () { av (); aw (); } +}; +template <class T> struct G : B +{ + T ba; + G (int, T) : ba (0) {} + void av () { ba (0); } +}; +struct I +{ + B *bc; + template <class j, class T> I (j, T) try { G<T> (0, 0); } catch (...) {} + ~I () { bc->h (); } +}; +template <class M> struct C { typedef M *i; }; +template <class M> struct J +{ + J (); + template <class O, class T> J (O, T p2) : be (0, p2) {} + typename C<M>::i operator-> (); + I be; +}; +struct H : A { H () : A (0) {} }; +struct D { J<int> d; void q (); }; +template <typename = int> class bs; +int z; + +void +foo (int p1, int *, int) +{ + if (p1 == 0) + throw H (); +} + +D bar (); +template <typename T> struct L +{ + struct K { K (int); void operator() (int *) { bar ().q (); } }; + static J<T> bp () { bq (0); } + template <typename br> static void bq (br) { J<T> (0, K (0)); } +}; +struct F +{ + virtual J<int> x (int) { foo (0, 0, 0); J<bs<> > (L<bs<> >::bp ()); } +}; + +void +baz () +{ + if (z) + { + J<F> d, e; + d->x (0); + e->x (0); + } + J<F> v, i, j; + v->x (0); + i->x (0); + j->x (0); +} Jakub