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;
 }

Reply via email to