aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-05-21 09:48:04 +0200
committerRichard Biener <rguenther@suse.de>2024-05-21 10:52:02 +0200
commitec9b8bafe20755d13ab9a1b834b5da79ae972c0e (patch)
treea021d0a9a725c1c881a1e7de8d8092e42b838997
parent9596f6567ce6fdf94227b97ac28d3549f421ef73 (diff)
downloadgcc-ec9b8bafe20755d13ab9a1b834b5da79ae972c0e.zip
gcc-ec9b8bafe20755d13ab9a1b834b5da79ae972c0e.tar.gz
gcc-ec9b8bafe20755d13ab9a1b834b5da79ae972c0e.tar.bz2
tree-optimization/115149 - VOP live and missing PHIs
The following fixes a bug in vop-live get_live_in which was using NULL to indicate the first processed edge but at the same time using it for the case the live-in virtual operand cannot be computed. The following fixes this, avoiding sinking a load to a place where we'd have to insert virtual PHIs to make the virtual operand SSA web OK. PR tree-optimization/115149 * tree-ssa-live.cc (virtual_operand_live::get_live_in): Explicitly track the first processed edge. * gcc.dg/pr115149.c: New testcase.
-rw-r--r--gcc/testsuite/gcc.dg/pr115149.c16
-rw-r--r--gcc/tree-ssa-live.cc8
2 files changed, 22 insertions, 2 deletions
diff --git a/gcc/testsuite/gcc.dg/pr115149.c b/gcc/testsuite/gcc.dg/pr115149.c
new file mode 100644
index 0000000..9f6bc97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr115149.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-inline -fno-tree-vrp -fno-ipa-sra -fno-tree-dce -fno-tree-ch" } */
+
+int a, c, e, f, g, h[1], i;
+static int j(int b) { return 0; }
+static void k(int d) {}
+int main()
+{
+ if (h[0])
+ while (1) {
+ k(f && j(i && (h[g] = e)));
+ while (a)
+ c ^= 1;
+ }
+ return 0;
+}
diff --git a/gcc/tree-ssa-live.cc b/gcc/tree-ssa-live.cc
index e6ae551..60dfc05 100644
--- a/gcc/tree-ssa-live.cc
+++ b/gcc/tree-ssa-live.cc
@@ -1675,14 +1675,18 @@ virtual_operand_live::get_live_in (basic_block bb)
edge_iterator ei;
edge e;
tree livein = NULL_TREE;
+ bool first = true;
FOR_EACH_EDGE (e, ei, bb->preds)
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 (first)
+ {
+ livein = get_live_out (e->src);
+ first = false;
+ }
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