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))))

Reply via email to