]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/119274 - improve VN optimistic dominance query
authorRichard Biener <rguenther@suse.de>
Fri, 14 Mar 2025 09:01:20 +0000 (10:01 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 14 Mar 2025 11:06:54 +0000 (12:06 +0100)
The following improves how VN performs its dominance queries to
determine availability, exploiting edges considered unreachable.
The function already contains code to handle the leader block
forking the CFG, but that looks like a situation that won't
help the dominance query ever.  The following adds handling
of the more useful case where this block forwards to a CFG
merge with the forwarder being the only executable entry.

This helps optimizing the code so the spurious array diagnostic
does no longer appear.

PR tree-optimization/119274
* tree-ssa-sccvn.cc (dominated_by_p_w_unex): Handle the
top block being the only executable forwarder to a CFG
merge.

* g++.dg/opt/pr119274.C: New testcase.

gcc/testsuite/g++.dg/opt/pr119274.C [new file with mode: 0644]
gcc/tree-ssa-sccvn.cc

diff --git a/gcc/testsuite/g++.dg/opt/pr119274.C b/gcc/testsuite/g++.dg/opt/pr119274.C
new file mode 100644 (file)
index 0000000..79b4061
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Wall" }
+
+#include <cstdlib>
+#include <vector>
+
+typedef std::vector<int> v1;
+
+static
+void drop_inplace(v1 & c, size_t len)
+{
+  if (len <= c.size())
+    c[len-1] = 0;  /* { dg-bogus "outside array bounds" } */
+}
+
+void func()
+{
+  v1 vec1{1,2,3,4,5,6};
+  drop_inplace(vec1, 10);
+}
index 5a8c7c3aa10b991ff6298e9ba50b8b9ef97ec967..40c38fa020a6353ee14d4c7a04a2c9458f6f48a6 100644 (file)
@@ -5169,6 +5169,34 @@ dominated_by_p_w_unex (basic_block bb1, basic_block bb2, bool allow_back)
            }
        }
     }
+  /* Iterate to the single successor of bb2 with only a single executable
+     incoming edge.  */
+  else if (EDGE_COUNT (bb2->succs) == 1
+          && EDGE_COUNT (single_succ (bb2)->preds) > 1)
+    {
+      edge prede = NULL;
+      FOR_EACH_EDGE (e, ei, single_succ (bb2)->preds)
+       if ((e->flags & EDGE_EXECUTABLE)
+           || (!allow_back && (e->flags & EDGE_DFS_BACK)))
+         {
+           if (prede)
+             {
+               prede = NULL;
+               break;
+             }
+           prede = e;
+         }
+      /* We might actually get to a query with BB2 not visited yet when
+        we're querying for a predicated value.  */
+      if (prede && prede->src == bb2)
+       {
+         bb2 = prede->dest;
+
+         /* Re-do the dominance check with changed bb2.  */
+         if (dominated_by_p (CDI_DOMINATORS, bb1, bb2))
+           return true;
+       }
+    }
 
   /* We could now iterate updating bb1 / bb2.  */
   return false;