Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
Richard. 2019-09-19 Richard Biener <rguent...@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" } } */