gcc/gcc6-pr68672.patch

300 lines
8.0 KiB
Diff

2016-02-11 Jakub Jelinek <jakub@redhat.com>
PR ipa/68672
* ipa-split.c (split_function): Don't compute/use main_part_return_p.
Compute retval and retbnd early in all cases if split_part_return_p
and return_bb is not EXIT. Remove all clobber stmts and reset
all debug stmts that refer to SSA_NAMEs defined in split part,
except if it is retval, in that case replace the old retval with the
lhs of the call to the split part.
* g++.dg/ipa/pr68672-1.C: New test.
* g++.dg/ipa/pr68672-2.C: New test.
* g++.dg/ipa/pr68672-3.C: New test.
--- gcc/ipa-split.c.jj 2016-02-11 10:50:52.888220581 +0100
+++ gcc/ipa-split.c 2016-02-11 12:46:15.975777652 +0100
@@ -1244,28 +1244,13 @@ split_function (basic_block return_bb, s
args_to_pass.safe_push (arg);
}
- /* See if the split function or the main part will return. */
- bool main_part_return_p = false;
+ /* See if the split function will return. */
bool split_part_return_p = false;
FOR_EACH_EDGE (e, ei, return_bb->preds)
{
if (bitmap_bit_p (split_point->split_bbs, e->src->index))
split_part_return_p = true;
- else
- main_part_return_p = true;
}
- /* The main part also returns if we split on a fallthru edge
- and the split part returns. */
- if (split_part_return_p)
- FOR_EACH_EDGE (e, ei, split_point->entry_bb->preds)
- {
- if (! bitmap_bit_p (split_point->split_bbs, e->src->index)
- && single_succ_p (e->src))
- {
- main_part_return_p = true;
- break;
- }
- }
/* Add return block to what will become the split function.
We do not return; no return block is needed. */
@@ -1279,8 +1264,8 @@ split_function (basic_block return_bb, s
FIXME: Once we are able to change return type, we should change function
to return void instead of just outputting function with undefined return
value. For structures this affects quality of codegen. */
- else if (!split_point->split_part_set_retval
- && (retval = find_retval (return_bb)))
+ else if ((retval = find_retval (return_bb))
+ && !split_point->split_part_set_retval)
{
bool redirected = true;
basic_block new_return_bb = create_basic_block (NULL, 0, return_bb);
@@ -1308,12 +1293,10 @@ split_function (basic_block return_bb, s
}
/* When we pass around the value, use existing return block. */
else
- bitmap_set_bit (split_point->split_bbs, return_bb->index);
-
- /* If the main part doesn't return pretend the return block wasn't
- found for all of the following. */
- if (! main_part_return_p)
- return_bb = EXIT_BLOCK_PTR_FOR_FN (cfun);
+ {
+ bitmap_set_bit (split_point->split_bbs, return_bb->index);
+ retbnd = find_retbnd (return_bb);
+ }
/* If RETURN_BB has virtual operand PHIs, they must be removed and the
virtual operand marked for renaming as we change the CFG in a way that
@@ -1382,6 +1365,44 @@ split_function (basic_block return_bb, s
DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
}
+ /* If return_bb contains any clobbers that refer to SSA_NAMEs
+ set in the split part, remove them. Also reset debug stmts that
+ refer to SSA_NAMEs set in the split part. */
+ if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
+ {
+ gimple_stmt_iterator gsi = gsi_start_bb (return_bb);
+ while (!gsi_end_p (gsi))
+ {
+ tree op;
+ ssa_op_iter iter;
+ gimple *stmt = gsi_stmt (gsi);
+ bool remove = false;
+ if (gimple_clobber_p (stmt) || is_gimple_debug (stmt))
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
+ {
+ basic_block bb = gimple_bb (SSA_NAME_DEF_STMT (op));
+ if (op != retval
+ && bb
+ && bb != return_bb
+ && bitmap_bit_p (split_point->split_bbs, bb->index))
+ {
+ if (is_gimple_debug (stmt))
+ {
+ gimple_debug_bind_reset_value (stmt);
+ update_stmt (stmt);
+ }
+ else
+ remove = true;
+ break;
+ }
+ }
+ if (remove)
+ gsi_remove (&gsi, true);
+ else
+ gsi_next (&gsi);
+ }
+ }
+
/* If the original function is instrumented then it's
part is also instrumented. */
if (with_bounds)
@@ -1499,9 +1520,7 @@ split_function (basic_block return_bb, s
return value into and put call just before it. */
if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
{
- real_retval = retval = find_retval (return_bb);
- retbnd = find_retbnd (return_bb);
-
+ real_retval = retval;
if (real_retval && split_point->split_part_set_retval)
{
gphi_iterator psi;
@@ -1545,6 +1564,28 @@ split_function (basic_block return_bb, s
break;
}
update_stmt (gsi_stmt (bsi));
+ /* Also adjust clobbers and debug stmts in return_bb. */
+ for (bsi = gsi_start_bb (return_bb); !gsi_end_p (bsi);
+ gsi_next (&bsi))
+ {
+ gimple *stmt = gsi_stmt (bsi);
+ if (gimple_clobber_p (stmt)
+ || is_gimple_debug (stmt))
+ {
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ bool update = false;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
+ SSA_OP_USE)
+ if (USE_FROM_PTR (use_p) == real_retval)
+ {
+ SET_USE (use_p, retval);
+ update = true;
+ }
+ if (update)
+ update_stmt (stmt);
+ }
+ }
}
/* Replace retbnd with new one. */
--- gcc/testsuite/g++.dg/ipa/pr68672-1.C.jj 2016-02-11 12:31:27.344497187 +0100
+++ gcc/testsuite/g++.dg/ipa/pr68672-1.C 2016-02-11 12:31:01.000000000 +0100
@@ -0,0 +1,20 @@
+// PR ipa/68672
+// { dg-do compile }
+// { dg-options "-O -finline-small-functions -fpartial-inlining --param=partial-inlining-entry-probability=100" }
+
+void f2 (void *);
+void *a;
+struct C { virtual void m1 (); };
+struct D { C *m2 () { if (a) __builtin_abort (); } };
+D f1 ();
+struct E { int e; ~E () { if (e) f2 (&e); } };
+E *b;
+struct I { virtual void m3 (); };
+
+void
+I::m3 ()
+{
+ if (a)
+ f1 ().m2 ()->m1 ();
+ b->~E ();
+}
--- gcc/testsuite/g++.dg/ipa/pr68672-2.C.jj 2016-02-11 12:33:50.744438948 +0100
+++ gcc/testsuite/g++.dg/ipa/pr68672-2.C 2016-02-11 12:32:50.000000000 +0100
@@ -0,0 +1,54 @@
+// PR ipa/68672
+// { dg-do compile }
+// { dg-options "-O3 --param=partial-inlining-entry-probability=100 -g" }
+
+struct S { ~S () {} };
+S *a;
+int *b;
+void bar ();
+void baz ();
+void fn (int *);
+
+static int
+foo ()
+{
+ S *c = a;
+ if (c)
+ {
+ bar ();
+ if (a)
+ __builtin_abort ();
+ baz ();
+ }
+ int p = *b;
+ if (p)
+ {
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ }
+ c->~S ();
+ int q = 2 * p;
+ int r = 3 * q;
+ S *d = c;
+ return p;
+}
+
+void
+use1 ()
+{
+ foo ();
+}
+
+void
+use2 ()
+{
+ foo ();
+}
+
+void
+use3 ()
+{
+ foo ();
+}
--- gcc/testsuite/g++.dg/ipa/pr68672-3.C.jj 2016-02-11 12:34:02.374272024 +0100
+++ gcc/testsuite/g++.dg/ipa/pr68672-3.C 2016-02-11 12:34:22.337985482 +0100
@@ -0,0 +1,57 @@
+// PR ipa/68672
+// { dg-do compile }
+// { dg-options "-O3 --param=partial-inlining-entry-probability=100 -g" }
+
+struct S { ~S () {} };
+S *a, *e;
+int *b;
+void bar ();
+void baz ();
+void fn (int *);
+void fn2 (S *);
+
+static int
+foo ()
+{
+ S *c = a;
+ if (c)
+ {
+ bar ();
+ if (a)
+ __builtin_abort ();
+ baz ();
+ }
+ int p = *b;
+ S *f = e;
+ if (p)
+ {
+ fn2 (f);
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b); fn (b);
+ }
+ f->~S ();
+ int q = 2 * p;
+ int r = 3 * q;
+ S *d = c;
+ return p;
+}
+
+void
+use1 ()
+{
+ foo ();
+}
+
+void
+use2 ()
+{
+ foo ();
+}
+
+void
+use3 ()
+{
+ foo ();
+}