https://gcc.gnu.org/g:f9fbb47987efc8b5261e4cc36613c928a8693493
commit r15-850-gf9fbb47987efc8b5261e4cc36613c928a8693493 Author: Richard Biener <rguent...@suse.de> Date: Mon May 27 09:40:19 2024 +0200 tree-optimization/115220 - fix store sinking virtual operand constraints 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. 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. Diff: --- 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(-) 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; }