]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/34949 (Dead code in empty destructors.)
authorJakub Jelinek <jakub@gcc.gnu.org>
Mon, 8 Apr 2013 13:46:00 +0000 (15:46 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 8 Apr 2013 13:46:00 +0000 (15:46 +0200)
PR c++/34949
PR c++/50243
* tree-eh.c (optimize_clobbers): Only remove clobbers if bb doesn't
contain anything but clobbers, at most one __builtin_stack_restore,
optionally debug stmts and final resx, and if it has at least one
incoming EH edge.  Don't check for SSA_NAME on LHS of a clobber.
(sink_clobbers): Don't check for SSA_NAME on LHS of a clobber.
Instead of moving clobbers with MEM_REF LHS with SSA_NAME address
which isn't defaut definition, remove them.
(unsplit_eh, cleanup_empty_eh): Use single_{pred,succ}_{p,edge}
instead of EDGE_COUNT comparisons or EDGE_{PRED,SUCC}.
* tree-ssa-ccp.c (execute_fold_all_builtins): Remove clobbers
with MEM_REF LHS with SSA_NAME address.

* g++.dg/opt/vt3.C: New test.
* g++.dg/opt/vt4.C: New test.

From-SVN: r197580

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/vt3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/opt/vt4.C [new file with mode: 0644]
gcc/tree-eh.c
gcc/tree-ssa-ccp.c

index b72dd89f50dda59db27e2ce8bff7c6c94e381d82..6ee7d9c2ef8f73635bed2f7284e15cdbf706ea16 100644 (file)
@@ -1,3 +1,19 @@
+2013-04-08  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/34949
+       PR c++/50243
+       * tree-eh.c (optimize_clobbers): Only remove clobbers if bb doesn't
+       contain anything but clobbers, at most one __builtin_stack_restore,
+       optionally debug stmts and final resx, and if it has at least one
+       incoming EH edge.  Don't check for SSA_NAME on LHS of a clobber.
+       (sink_clobbers): Don't check for SSA_NAME on LHS of a clobber.
+       Instead of moving clobbers with MEM_REF LHS with SSA_NAME address
+       which isn't defaut definition, remove them.
+       (unsplit_eh, cleanup_empty_eh): Use single_{pred,succ}_{p,edge}
+       instead of EDGE_COUNT comparisons or EDGE_{PRED,SUCC}.
+       * tree-ssa-ccp.c (execute_fold_all_builtins): Remove clobbers
+       with MEM_REF LHS with SSA_NAME address.
+
 2013-04-08  Jeff Law  <law@redhat.com>
 
        * gimple.c (canonicalize_cond_expr_cond): Rewrite x ^ y into x != y.
index e137b85657bf45e772b23330686a17afde0a994d..5eb5f7d57430b31a3ddb0bb13cbeb7bdd04207df 100644 (file)
@@ -1,6 +1,13 @@
+2013-04-08  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/34949
+       PR c++/50243
+       * g++.dg/opt/vt3.C: New test.
+       * g++.dg/opt/vt4.C: New test.
+
 2013-04-08  Jeff Law  <law@redhat.com>
 
-       * gcc.dg/tree-ssa/forwprop-25.c: New test
+       * gcc.dg/tree-ssa/forwprop-25.c: New test.
 
 2013-04-08  Richard Biener  <rguenther@suse.de>
 
diff --git a/gcc/testsuite/g++.dg/opt/vt3.C b/gcc/testsuite/g++.dg/opt/vt3.C
new file mode 100644 (file)
index 0000000..0cef672
--- /dev/null
@@ -0,0 +1,43 @@
+// PR c++/34949
+// { dg-do compile }
+// { dg-options "-O3" }
+
+struct E {};
+struct A
+{
+  virtual void a (void *) = 0;
+};
+struct B
+{
+  virtual ~B () {};
+  unsigned int b1;
+  E **b2;
+  A *b3;
+};
+struct C : public B
+{
+  ~C ();
+};
+C::~C ()
+{
+  for (unsigned int i = 0; i < b1; i++)
+    b3->a (b2);
+}
+struct D
+{
+  ~D () {}
+  C d;
+};
+struct F { virtual ~F () {}; };
+struct G { void g (); };
+struct H : public F
+{
+  virtual ~H ();
+  D *h1;
+  G *h2;
+};
+H::~H ()
+{
+  h2->g ();
+  delete h1;
+}
diff --git a/gcc/testsuite/g++.dg/opt/vt4.C b/gcc/testsuite/g++.dg/opt/vt4.C
new file mode 100644 (file)
index 0000000..c8d04cf
--- /dev/null
@@ -0,0 +1,31 @@
+// PR c++/50243
+// { dg-do compile }
+// { dg-options "-O" }
+// { dg-final { scan-assembler-not "_ZTV.A" } }
+
+void foo ();
+
+struct A
+{
+  ~A () { }
+  virtual void a () = 0;
+  virtual void b () = 0;
+  virtual void c () = 0;
+};
+
+struct B : public A
+{
+  ~B () { foo (); }
+  void a () { foo (); }
+  void b () { foo (); }
+  void c () { delete this; }
+};
+
+void
+test ()
+{
+  A *y = new B ();
+  y->a ();
+  y->b ();
+  y->c ();
+}
index 973782ba5a86fd832db34156dbba5d21d01c8d67..2eb309732a6b98815164db6608810acdf04d425a 100644 (file)
@@ -3230,14 +3230,48 @@ static void
 optimize_clobbers (basic_block bb)
 {
   gimple_stmt_iterator gsi = gsi_last_bb (bb);
+  bool any_clobbers = false;
+  bool seen_stack_restore = false;
+  edge_iterator ei;
+  edge e;
+
+  /* Only optimize anything if the bb contains at least one clobber,
+     ends with resx (checked by caller), optionally contains some
+     debug stmts or labels, or at most one __builtin_stack_restore
+     call, and has an incoming EH edge.  */
   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
     {
       gimple stmt = gsi_stmt (gsi);
       if (is_gimple_debug (stmt))
        continue;
-      if (!gimple_clobber_p (stmt)
-         || TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME)
-       return;
+      if (gimple_clobber_p (stmt))
+       {
+         any_clobbers = true;
+         continue;
+       }
+      if (!seen_stack_restore
+         && gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE))
+       {
+         seen_stack_restore = true;
+         continue;
+       }
+      if (gimple_code (stmt) == GIMPLE_LABEL)
+       break;
+      return;
+    }
+  if (!any_clobbers)
+    return;
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    if (e->flags & EDGE_EH)
+      break;
+  if (e == NULL)
+    return;
+  gsi = gsi_last_bb (bb);
+  for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+    {
+      gimple stmt = gsi_stmt (gsi);
+      if (!gimple_clobber_p (stmt))
+       continue;
       unlink_stmt_vdef (stmt);
       gsi_remove (&gsi, true);
       release_defs (stmt);
@@ -3278,8 +3312,7 @@ sink_clobbers (basic_block bb)
        continue;
       if (gimple_code (stmt) == GIMPLE_LABEL)
        break;
-      if (!gimple_clobber_p (stmt)
-         || TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME)
+      if (!gimple_clobber_p (stmt))
        return 0;
       any_clobbers = true;
     }
@@ -3292,11 +3325,27 @@ sink_clobbers (basic_block bb)
   for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
     {
       gimple stmt = gsi_stmt (gsi);
+      tree lhs;
       if (is_gimple_debug (stmt))
        continue;
       if (gimple_code (stmt) == GIMPLE_LABEL)
        break;
       unlink_stmt_vdef (stmt);
+      lhs = gimple_assign_lhs (stmt);
+      /* Unfortunately we don't have dominance info updated at this
+        point, so checking if
+        dominated_by_p (CDI_DOMINATORS, succbb,
+                        gimple_bb (SSA_NAME_DEF_STMT (TREE_OPERAND (lhs, 0)))
+        would be too costly.  Thus, avoid sinking any clobbers that
+        refer to non-(D) SSA_NAMEs.  */
+      if (TREE_CODE (lhs) == MEM_REF
+         && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME
+         && !SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (lhs, 0)))
+       {
+         gsi_remove (&gsi, true);
+         release_defs (stmt);
+         continue;
+       }
       gsi_remove (&gsi, false);
       /* Trigger the operand scanner to cause renaming for virtual
          operands for this statement.
@@ -3737,10 +3786,10 @@ unsplit_eh (eh_landing_pad lp)
   edge e_in, e_out;
 
   /* Quickly check the edge counts on BB for singularity.  */
-  if (EDGE_COUNT (bb->preds) != 1 || EDGE_COUNT (bb->succs) != 1)
+  if (!single_pred_p (bb) || !single_succ_p (bb))
     return false;
-  e_in = EDGE_PRED (bb, 0);
-  e_out = EDGE_SUCC (bb, 0);
+  e_in = single_pred_edge (bb);
+  e_out = single_succ_edge (bb);
 
   /* Input edge must be EH and output edge must be normal.  */
   if ((e_in->flags & EDGE_EH) == 0 || (e_out->flags & EDGE_EH) != 0)
@@ -4142,7 +4191,7 @@ cleanup_empty_eh (eh_landing_pad lp)
       e_out = NULL;
       break;
     case 1:
-      e_out = EDGE_SUCC (bb, 0);
+      e_out = single_succ_edge (bb);
       break;
     default:
       return false;
index a64bffcaec75ef349577965b00e1f75521634a5a..f298b27ad9713cfab3aadbf4068df5e4df9f83c1 100644 (file)
@@ -2396,6 +2396,21 @@ execute_fold_all_builtins (void)
 
           if (gimple_code (stmt) != GIMPLE_CALL)
            {
+             /* Remove all *ssaname_N ={v} {CLOBBER}; stmts,
+                after the last GIMPLE DSE they aren't needed and might
+                unnecessarily keep the SSA_NAMEs live.  */
+             if (gimple_clobber_p (stmt))
+               {
+                 tree lhs = gimple_assign_lhs (stmt);
+                 if (TREE_CODE (lhs) == MEM_REF
+                     && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
+                   {
+                     unlink_stmt_vdef (stmt);
+                     gsi_remove (&i, true);
+                     release_defs (stmt);
+                     continue;
+                   }
+               }
              gsi_next (&i);
              continue;
            }