Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
Richard.
2019-09-19 Richard Biener <rguenther@suse.de>
PR tree-optimization/91812
* tree-ssa-phiprop.c (propagate_with_phi): Do not replace
volatile loads.
* gcc.dg/torture/pr91812.c: New testcase.
Index: gcc/tree-ssa-phiprop.c
===================================================================
--- gcc/tree-ssa-phiprop.c (revision 275698)
+++ gcc/tree-ssa-phiprop.c (working copy)
@@ -338,8 +338,15 @@ propagate_with_phi (basic_block bb, gphi
&& (!type
|| types_compatible_p
(TREE_TYPE (gimple_assign_lhs (use_stmt)), type))
- /* We cannot replace a load that may throw or is volatile. */
- && !stmt_can_throw_internal (cfun, use_stmt)))
+ /* We cannot replace a load that may throw or is volatile.
+ For volatiles the transform can change the number of
+ executions if the load is inside a loop but the address
+ computations outside (PR91812). We could relax this
+ if we guard against that appropriately. For loads that can
+ throw we could relax things if the moved loads all are
+ known to not throw. */
+ && !stmt_can_throw_internal (cfun, use_stmt)
+ && !gimple_has_volatile_ops (use_stmt)))
continue;
/* Check if we can move the loads. The def stmt of the virtual use
Index: gcc/testsuite/gcc.dg/torture/pr91812.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr91812.c (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr91812.c (working copy)
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized-blocks" } */
+
+unsigned register1;
+unsigned register2;
+
+void busy_wait_for_register (int x)
+{
+ volatile unsigned* ptr;
+ switch(x) {
+ case 0x1111:
+ ptr = ®ister1;
+ break;
+
+ case 0x2222:
+ ptr = ®ister2;
+ break;
+
+ default:
+ return;
+ }
+ while (*ptr) {}
+}
+
+/* { dg-final { scan-tree-dump "loop depth 1" "optimized" } } */