https://gcc.gnu.org/g:2ae9740dde8225371d3791a71b99d52ef686e2cc
commit r17-4840-g2ae9740dde8225371d3791a71b99d52ef686e2cc Author: Richard Biener <[email protected]> Date: Fri Oct 2 16:04:15 2026 +0200 tree-optimization/127693 - missed FRE in loop The following addresses a missed optimization caused by the PR54498 correctness fix. For CFG cycles when get_continuation_for_phi is invoked on a loop PHI with a backedge and abort_on_visited true because we have translated the reference maybe_skip_until will fail because we will definitely hit that PHI again. But the intent was to catch re-visiting actual statements which we will do eventually by visiting the other PHI edges from the caller. So finish the walk at the original PHI latest. This allows the constant 1 to be propagated to the __builtin_constant_p and the bug avoided. PR tree-optimization/127693 * tree-ssa-alias.cc (maybe_skip_until): Stop when reaching the PHI again. * gcc.dg/tree-ssa/ssa-fre-116.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-116.c | 47 +++++++++++++++++++++++++++++ gcc/tree-ssa-alias.cc | 8 +++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-116.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-116.c new file mode 100644 index 000000000000..7f022a3da368 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-116.c @@ -0,0 +1,47 @@ +/* PR127693 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-fre3" } */ + +struct SV { long m_size; }; + +__attribute__((noipa)) +long findString(long from, struct SV needle) +{ + __builtin_abort (); +} + +__attribute__((noipa)) +long findChar(long from) +{ + if (from == 0) + return 1; + return -1; +} + +static long indexOf(struct SV s, long from) +{ + if (__builtin_constant_p(s.m_size) && s.m_size == 1) + return findChar(from); + return findString(from, s); +} + +static int scan(struct SV sought) +{ + long n = sought.m_size; + long idx = -n; + int matched = 0; + while ((idx = indexOf(sought, idx + n)) >= 0) + ++matched; + return matched; +} + +int f(void) { return scan((struct SV){1}); } + +int main() +{ + if (f() != 1) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-not "unreachable" "fre3" } } */ diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc index 7fc87b3b9446..c1e5added30e 100644 --- a/gcc/tree-ssa-alias.cc +++ b/gcc/tree-ssa-alias.cc @@ -3792,8 +3792,12 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb, return true; } - /* Recurse for PHI nodes. */ - if (gphi *phi = dyn_cast <gphi *> (def_stmt)) + /* When we reach the original PHI we are done. TARGET must be + reached via other edges in the caller. */ + if (def_stmt == phi) + return true; + /* Recurse for other PHI nodes. */ + else if (gphi *phi = dyn_cast <gphi *> (def_stmt)) { /* An already visited PHI node ends the walk successfully. */ if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (phi))))
