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.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
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.
---
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-116.c | 47 +++++++++++++++++++++
gcc/tree-ssa-alias.cc | 8 +++-
2 files changed, 53 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-116.c
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 00000000000..7f022a3da36
--- /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 7fc87b3b944..c1e5added30 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))))
--
2.51.0