tree-optimization/110924 - fix vop liveness for noreturn const CFG parts
Checks
Commit Message
The virtual operand live problem used by sinking assumes we have
virtual uses at each end point of the CFG but as shown in the PR
this isn't true for parts for example ending in __builtin_unreachable.
The following removes the optimization made possible by this and
now requires marking backedges.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
PR tree-optimization/110924
* tree-ssa-live.h (virtual_operand_live): Update comment.
* tree-ssa-live.cc (virtual_operand_live::get_live_in): Remove
optimization, look at each predecessor.
* tree-ssa-sink.cc (pass_sink_code::execute): Mark backedges.
* gcc.dg/torture/pr110924.c: New testcase.
---
gcc/testsuite/gcc.dg/torture/pr110924.c | 23 ++++++++++++++++++
gcc/tree-ssa-live.cc | 32 ++++++++++++++-----------
gcc/tree-ssa-live.h | 3 ++-
gcc/tree-ssa-sink.cc | 1 +
4 files changed, 44 insertions(+), 15 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr110924.c
new file mode 100644
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+
+int a[1], b, c, d, e, f, g;
+void h(int i, int j) {
+ int *k = 0;
+ if (*k)
+ h(0, 0);
+ g = i && d;
+}
+int main() {
+ if (c)
+ goto l;
+ if (!a)
+ while (1) {
+ f = 1;
+ while (f)
+ h(b && main(), e);
+ while (1)
+ ;
+ l:;
+ }
+ return 0;
+}
@@ -1676,23 +1676,27 @@ virtual_operand_live::get_live_in (basic_block bb)
if (!liveout)
init ();
- /* Since we don't have a virtual PHI we can now pick any of the
- incoming edges liveout value. All returns from the function have
- a virtual use forcing generation of virtual PHIs. */
+ /* Since we don't have a virtual PHI and we don't know whether there's
+ a downstream virtual use (and thus PHIs are inserted where necessary)
+ we now have to check each incoming edge live-out. */
edge_iterator ei;
edge e;
+ tree livein = NULL_TREE;
FOR_EACH_EDGE (e, ei, bb->preds)
- if (liveout[e->src->index])
- {
- if (EDGE_PRED (bb, 0) != e)
- liveout[EDGE_PRED (bb, 0)->src->index] = liveout[e->src->index];
- return liveout[e->src->index];
- }
-
- /* Since virtuals are in SSA form at most the immediate dominator can
- contain the definition of the live version. Skipping to that deals
- with CFG cycles as well. */
- return get_live_out (get_immediate_dominator (CDI_DOMINATORS, bb));
+ if (e->flags & EDGE_DFS_BACK)
+ /* We can ignore backedges since if there's a def there it would
+ have forced a PHI in the source because it also acts as use
+ downstream. */
+ continue;
+ else if (!livein)
+ livein = get_live_out (e->src);
+ else if (get_live_out (e->src) != livein)
+ /* When there's no virtual use downstream this indicates a point
+ where we'd insert a PHI merging the different live virtual
+ operands. */
+ return NULL_TREE;
+
+ return livein;
}
/* Compute live-out of BB. */
@@ -332,7 +332,8 @@ make_live_on_entry (tree_live_info_p live, basic_block bb , int p)
/* On-demand virtual operand global live analysis. There is at most
a single virtual operand live at a time, the following computes and
caches the virtual operand live at the exit of a basic block
- supporting related live-in and live-on-edge queries. */
+ supporting related live-in and live-on-edge queries. It requires
+ up-to-date marked backedges. */
class virtual_operand_live
{
@@ -822,6 +822,7 @@ pass_sink_code::execute (function *fun)
/* Arrange for the critical edge splitting to be undone if requested. */
unsigned todo = unsplit_edges ? TODO_cleanup_cfg : 0;
connect_infinite_loops_to_exit ();
+ mark_dfs_back_edges (fun);
memset (&sink_stats, 0, sizeof (sink_stats));
calculate_dominance_info (CDI_DOMINATORS);