After outlinining the bbs for function splitting, we move the clobbers that
were in the
last bb to be after the newly calling function.
This allows for stack location sharing and more when the non split out part is
inlined
into another function.
This also fixes some of the warnings about dangling-pointers because
the clobbers are now correctly handled while function splitting.
The testcases test for the cases where the dangling-pointers pointer
warnings would show up too.
Note only end of storage clobbers in this case.
Bootstrapped and tested on x86_64-linux-gnu.
PR tree-optimization/110091
gcc/ChangeLog:
* ipa-split.cc (split_function): Find the bb
which is used for return in the outlined function.
Move the clobbers that are at the end of that bb
to be after the new call.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/pr110091-3.c: New test.
* gcc.dg/tree-ssa/pr110091-4.c: New test.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/ipa-split.cc | 48 ++++++++++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c | 38 +++++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c | 34 +++++++++++++++
3 files changed, 120 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c
diff --git a/gcc/ipa-split.cc b/gcc/ipa-split.cc
index 3185830609d..aae4cf9e151 100644
--- a/gcc/ipa-split.cc
+++ b/gcc/ipa-split.cc
@@ -1470,8 +1470,31 @@ split_function (basic_block return_bb, class split_point
*split_point,
}
else
break;
+
+ /* Find the old return bb, it might contain some clobbers
+ which we want to copy back after the call. */
+ basic_block old_return = nullptr;
+ if (split_part_return_p)
+ {
+ bool one_return_bb = true;
+ FOR_EACH_EDGE (e, ei, return_bb->preds)
+ if (bitmap_bit_p (split_point->split_bbs, e->src->index))
+ {
+ if (old_return != nullptr)
+ {
+ one_return_bb = false;
+ break;
+ }
+ old_return = e->src;
+ }
+ if (!one_return_bb)
+ old_return = nullptr;
+ }
+
call_bb->count = split_point->count;
e = split_block (split_point->entry_bb, last_stmt);
+ if (old_return == e->src)
+ old_return = e->dest;
remove_edge (e);
/* Produce the call statement. */
@@ -1713,6 +1736,31 @@ split_function (basic_block return_bb, class split_point
*split_point,
gsi_insert_after (&gsi, ret, GSI_NEW_STMT);
}
}
+
+ /* Move the clobbers from the old return bb to after the call. */
+ if (old_return)
+ {
+ gimple_stmt_iterator ngsi = gsi_last_bb (call_bb);
+ gsi_next (&ngsi);
+ for (gimple_stmt_iterator ogsi = gsi_last_bb (old_return);
+ !gsi_end_p (ogsi); )
+ {
+ gimple *stmt = *ogsi;
+ if (is_gimple_debug (stmt))
+ {
+ gsi_prev (&ogsi);
+ continue;
+ }
+ if (!gimple_clobber_p (stmt, CLOBBER_STORAGE_END))
+ break;
+ gimple_set_vuse (stmt, gimple_vop (cfun));
+ gimple_set_vdef (stmt, gimple_vop (cfun));
+ gimple_stmt_iterator nogsi = ogsi;
+ gsi_prev (&ogsi);
+ gsi_move_before (&nogsi, &ngsi, GSI_NEW_STMT);
+ update_stmt (stmt);
+ }
+ }
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
compute_fn_summary (node, true);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c
new file mode 100644
index 00000000000..532b138655f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fdump-tree-optimized -fdump-tree-sink1-details" }
*/
+/* PR tree-optimization/110091 */
+/* The clobbers are after the outlined code */
+
+struct tEntry
+{
+ int value;
+};
+int *out;
+
+extern int otherfunc(struct tEntry *);
+extern void anotherfunc(int val);
+
+void bar()
+{
+ struct tEntry entry1 = { 0 };
+ struct tEntry entry2 = { 0 };
+
+ if (otherfunc(&entry2) != 0)
+ return;
+ if (otherfunc(&entry1) != 0)
+ return;
+ if (out)
+ *out = entry2.value; /* { dg-bogus "dangling pointer to" } */
+ anotherfunc(5);
+}
+
+void foo()
+{
+ bar();
+}
+
+/* There should be 2 CLOBBERs, 1 for each: entry1 and entry2 as they have been
"sinked". */
+/* { dg-final { scan-tree-dump-times "CLOBBER\\\(eos\\\)" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump "sinking common stores with same value to
entry2" "sink1" } } */
+/* { dg-final { scan-tree-dump "sinking common stores with same value to
entry1" "sink1" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c
new file mode 100644
index 00000000000..e2ce19b0e83
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -O2 -fdump-tree-optimized -fdump-tree-sink1-details" }
*/
+/* PR tree-optimization/110091 */
+/* The clobbers are after the outlined code */
+
+struct tEntry
+{
+ int value;
+};
+int *out;
+
+extern int otherfunc(struct tEntry *);
+extern void anotherfunc(int val);
+
+void bar()
+{
+ struct tEntry entry = { 0 };
+
+ if (otherfunc(&entry) != 0)
+ return;
+ if (out)
+ *out = entry.value; /* { dg-bogus "dangling pointer to" } */
+ anotherfunc(5);
+}
+
+void foo()
+{
+ bar();
+}
+
+/* There should be 2 CLOBBERs, 1 for entry as they have been "sinked" and one
for the inlined version. */
+/* { dg-final { scan-tree-dump-times "CLOBBER\\\(eos\\\)" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump "sinking common stores with same value to
entry" "sink1" } } */
+
--
2.43.0