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

Reply via email to