aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-05-27 09:40:19 +0200
committerRichard Biener <rguenther@suse.de>2024-05-27 12:45:35 +0200
commitf9fbb47987efc8b5261e4cc36613c928a8693493 (patch)
treedead92a1281a37db15cfad5fe697772bf9aaf758
parentf6c5f836df44196a7cd3b206af5bb29df6c7c225 (diff)
downloadgcc-f9fbb47987efc8b5261e4cc36613c928a8693493.zip
gcc-f9fbb47987efc8b5261e4cc36613c928a8693493.tar.gz
gcc-f9fbb47987efc8b5261e4cc36613c928a8693493.tar.bz2
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.
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr115220.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr115226.c15
-rw-r--r--gcc/tree-ssa-sink.cc12
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 0000000..e7b5da6
--- /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 0000000..9a0bc7c
--- /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 b0fe871..8c551e4 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;
}