diff options
author | Richard Biener <rguenther@suse.de> | 2024-05-21 09:48:04 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2024-05-21 10:52:02 +0200 |
commit | ec9b8bafe20755d13ab9a1b834b5da79ae972c0e (patch) | |
tree | a021d0a9a725c1c881a1e7de8d8092e42b838997 | |
parent | 9596f6567ce6fdf94227b97ac28d3549f421ef73 (diff) | |
download | gcc-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.c | 16 | ||||
-rw-r--r-- | gcc/tree-ssa-live.cc | 8 |
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 |