]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/115220 - fix store sinking virtual operand constraints
authorRichard Biener <rguenther@suse.de>
Mon, 27 May 2024 07:40:19 +0000 (09:40 +0200)
committerRichard Biener <rguenther@suse.de>
Mon, 27 May 2024 10:45:35 +0000 (12:45 +0200)
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.

gcc/testsuite/gcc.dg/torture/pr115220.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr115226.c [new file with mode: 0644]
gcc/tree-ssa-sink.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr115220.c b/gcc/testsuite/gcc.dg/torture/pr115220.c
new file mode 100644 (file)
index 0000000..e7b5da6
--- /dev/null
@@ -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 (file)
index 0000000..9a0bc7c
--- /dev/null
@@ -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;
+}
index b0fe871cf1ea2a28b8e92f686fb5f8e69a565bf0..8c551e42a4d2fac856ae8bfa4911d6cb331409bc 100644 (file)
@@ -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;
 }