aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2013-04-08 15:46:00 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2013-04-08 15:46:00 +0200
commitf223bb136269cc62ae94cc5d382e08be53b47acd (patch)
treea3858d5e8ddd0ca9b466d3525480cd3308ad2bfb /gcc
parent4481581f34be81348f36276e290c80d59fbf49c6 (diff)
downloadgcc-f223bb136269cc62ae94cc5d382e08be53b47acd.zip
gcc-f223bb136269cc62ae94cc5d382e08be53b47acd.tar.gz
gcc-f223bb136269cc62ae94cc5d382e08be53b47acd.tar.bz2
re PR c++/34949 (Dead code in empty destructors.)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/g++.dg/opt/vt3.C43
-rw-r--r--gcc/testsuite/g++.dg/opt/vt4.C31
-rw-r--r--gcc/tree-eh.c67
-rw-r--r--gcc/tree-ssa-ccp.c15
6 files changed, 171 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b72dd89..6ee7d9c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e137b85..5eb5f7d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..0cef672
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/vt3.C
@@ -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
index 0000000..c8d04cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/vt4.C
@@ -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 ();
+}
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 973782b..2eb3097 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -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;
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index a64bffc..f298b27 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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;
}