https://gcc.gnu.org/g:952e145796da0f4dc96c42fdcabd75c8293d516c
commit r16-5555-g952e145796da0f4dc96c42fdcabd75c8293d516c Author: Andrew Pinski <[email protected]> Date: Thu Nov 20 22:39:48 2025 -0800 phiprop: Allow non-trapping loads to be proped back into the loop First the testcase for PR60183 is no longer testing that we don't prop into the loops for possible trapping cases. This adds phiprop-4.c that tests that. Second we can prop back into loops if we know the load will not trap. This adds that check. phiprop-3.c tests that. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/60183 gcc/ChangeLog: * tree-ssa-phiprop.cc (propagate_with_phi): Allow known non-trapping loads to happen back into the loop. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/phiprop-3.c: New test. * gcc.dg/tree-ssa/phiprop-4.c: New test. Signed-off-by: Andrew Pinski <[email protected]> Diff: --- gcc/testsuite/gcc.dg/tree-ssa/phiprop-3.c | 25 +++++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/phiprop-4.c | 26 ++++++++++++++++++++++++++ gcc/tree-ssa-phiprop.cc | 14 ++++++++++---- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phiprop-3.c b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-3.c new file mode 100644 index 000000000000..59e95613c8c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-3.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiprop1-details" } */ + +/* PR tree-optimization/60183 */ + +unsigned char c; +extern unsigned char d; +int j = 2; + +unsigned long +foo (void) +{ + unsigned char *y = &c; + int i; + unsigned w = 0; + for (i = 0; i < j; i++) + { + w = *y; + y = &d; + } + return w; +} +/* the load from c/d does not trap so we should able to remove the phi. */ +/* { dg-final { scan-tree-dump "Removing dead stmt:" "phiprop1"} } */ +/* { dg-final { scan-tree-dump "Inserting PHI for result of load" "phiprop1"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phiprop-4.c b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-4.c new file mode 100644 index 000000000000..ceb03edac74f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phiprop-4.c @@ -0,0 +1,26 @@ +/* { dg-do compile { target { weak_undefined } } } */ +/* { dg-options "-O1 -fdump-tree-phiprop1-details" } */ +/* { dg-add-options weak_undefined } */ + +/* PR tree-optimization/60183 */ + +unsigned char c; +extern unsigned char d __attribute__((weak)); +int j = 2; + +unsigned long +foo (void) +{ + unsigned char *y = &c; + int i; + unsigned w = 0; + for (i = 0; i < j; i++) + { + w = *y; + y = &d; + } + return w; +} +/* the load from d can trap so this should not cause a phiprop. */ +/* { dg-final { scan-tree-dump-not "Removing dead stmt:" "phiprop1"} } */ +/* { dg-final { scan-tree-dump-not "Inserting PHI for result of load" "phiprop1"} } */ diff --git a/gcc/tree-ssa-phiprop.cc b/gcc/tree-ssa-phiprop.cc index 897bd583ea78..124d06c81911 100644 --- a/gcc/tree-ssa-phiprop.cc +++ b/gcc/tree-ssa-phiprop.cc @@ -271,6 +271,7 @@ propagate_with_phi (basic_block bb, gphi *vphi, gphi *phi, return false; tree up_vuse = NULL_TREE; + bool canpossible_trap = false; /* Check if we can "cheaply" dereference all phi arguments. */ FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE) { @@ -289,7 +290,11 @@ propagate_with_phi (basic_block bb, gphi *vphi, gphi *phi, arg = gimple_assign_rhs1 (def_stmt); } if (TREE_CODE (arg) == ADDR_EXPR) - ; + { + tree decl = TREE_OPERAND (arg, 0); + if (!canpossible_trap) + canpossible_trap = tree_could_trap_p (decl); + } /* When we have an SSA name see if we previously encountered a dereference of it. */ else if (TREE_CODE (arg) == SSA_NAME @@ -335,9 +340,10 @@ propagate_with_phi (basic_block bb, gphi *vphi, gphi *phi, calculate_dominance_info (CDI_POST_DOMINATORS); /* Only replace loads in blocks that post-dominate the PHI node. That - makes sure we don't end up speculating loads. */ - if (!dominated_by_p (CDI_POST_DOMINATORS, - bb, gimple_bb (use_stmt))) + makes sure we don't end up speculating trapping loads. */ + if (canpossible_trap + && !dominated_by_p (CDI_POST_DOMINATORS, + bb, gimple_bb (use_stmt))) continue; /* Check whether this is a load of *ptr. */
