]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/110924 - fix vop liveness for noreturn const CFG parts
authorRichard Biener <rguenther@suse.de>
Tue, 8 Aug 2023 10:46:42 +0000 (12:46 +0200)
committerRichard Biener <rguenther@suse.de>
Tue, 8 Aug 2023 12:24:12 +0000 (14:24 +0200)
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.

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 [new file with mode: 0644]
gcc/tree-ssa-live.cc
gcc/tree-ssa-live.h
gcc/tree-ssa-sink.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr110924.c b/gcc/testsuite/gcc.dg/torture/pr110924.c
new file mode 100644 (file)
index 0000000..7b39577
--- /dev/null
@@ -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;
+}
index c9c2fdef0e3c11fd609736785b094a37bcb19978..61789fae67d53066c9c6de8afdf798c167af79c7 100644 (file)
@@ -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.  */
index a7604448332c944f202e73c7e463b4bb3b332c7b..d175ad7247e2389b5d46cae03eff9cf0994576f0 100644 (file)
@@ -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
 {
index 6ad9d21589ef053b7e9361c40c44f475efcdd490..a360c5cdd6e8d58c5bb4aa0df20e431ee8f0edc8 100644 (file)
@@ -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);