The following makes sure the virtual operand updating when sinking stores works for the case we ignore paths to kills. The final sink location might not post-dominate the original stmt location which would require inserting of a virtual PHI which we do not support.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/115220 PR tree-optimization/115226 * tree-ssa-sink.cc (statement_sink_location): When ignoring paths to kills when sinking stores make sure the final sink location is still post-dominated by the original one. Otherwise we'd need to insert a PHI node to merge virtual operands. * gcc.dg/torture/pr115220.c: New testcase. * gcc.dg/torture/pr115226.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr115220.c | 14 ++++++++++++++ gcc/testsuite/gcc.dg/torture/pr115226.c | 15 +++++++++++++++ gcc/tree-ssa-sink.cc | 12 +++++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr115220.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr115226.c diff --git a/gcc/testsuite/gcc.dg/torture/pr115220.c b/gcc/testsuite/gcc.dg/torture/pr115220.c new file mode 100644 index 00000000000..e7b5da6ba42 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr115220.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-additional-options "--param logical-op-non-short-circuit=0" } */ + +extern char **environ; +static char ***p_environ = &environ; +int +_setenv_r (const char *name, const char *value) +{ + register char *C; + int offset; + for (C = (*p_environ)[offset]; (*C = *name++) && *C != '='; ++C); + for (*C++ = '='; (*C++ = *value++) != 0;); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr115226.c b/gcc/testsuite/gcc.dg/torture/pr115226.c new file mode 100644 index 00000000000..9a0bc7c9b6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr115226.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +extern void c(); +int a, b; +int main() { + while (b) { + int d, e = 0, *f = &a; + *f = 1; + e = 1 >> d ? : 1 << d; + if (e) + a = 0; + c(); + } + return 0; +} diff --git a/gcc/tree-ssa-sink.cc b/gcc/tree-ssa-sink.cc index b0fe871cf1e..8c551e42a4d 100644 --- a/gcc/tree-ssa-sink.cc +++ b/gcc/tree-ssa-sink.cc @@ -467,11 +467,17 @@ statement_sink_location (gimple *stmt, basic_block frombb, if (!sinkbb) return false; - sinkbb = select_best_block (frombb, sinkbb, stmt); - if (sinkbb == frombb) + basic_block bestbb = select_best_block (frombb, sinkbb, stmt); + if (bestbb == frombb + /* When we sink a store make sure there's not a path to any of + the possibly skipped killing defs as that wrecks the virtual + operand update, requiring inserting of a PHI node. */ + || (gimple_vdef (stmt) + && bestbb != sinkbb + && !dominated_by_p (CDI_POST_DOMINATORS, bestbb, sinkbb))) return false; - *togsi = gsi_after_labels (sinkbb); + *togsi = gsi_after_labels (bestbb); return true; } -- 2.35.3