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.
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
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;
}