}
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. */
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;
+ /* Change the vdef/vuse of the clobber to be renamed. */
+ unlink_stmt_vdef (stmt);
+ release_ssa_name (gimple_vdef (stmt));
+ gimple_set_vuse (stmt, gimple_vop (cfun));
+ gimple_set_vdef (stmt, gimple_vop (cfun));
+ gimple_stmt_iterator nogsi = ogsi;
+
+ /* Move to the previous stmt before the move happens. */
+ 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);
--- /dev/null
+/* { 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" } } */
+
--- /dev/null
+/* { 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" } } */
+