After r17-3298-g6cda72b8bd6 removed the abnormal-PHI restriction from
gimple_range_ssa_p, recursive fold evaluation can reach ssa_range_in_phi
for a PHI whose block differs from curr_bb(), making prev_bb() invalid
and find_edge() return NULL.

This causes bootstrap failure on riscv64-unknown-linux-gnu (ICE
compiling glibc locale/programs/ld-collate.c at -O2 during GIMPLE
pass thread), blocking the master branch toolchain build.

This is just a draft — it may not be the right approach and is not
necessarily meant for upstream.  If the original authors have a proper
fix in mind, that should take priority.  However, if they do not have
time soon, this conservative fallback could serve as a stopgap to
avoid leaving the master branch build broken indefinitely.

gcc/ChangeLog:

        PR tree-optimization/126876
        * gimple-range-path.cc (path_range_query::ssa_range_in_phi):
        Fall back to the ranger when the PHI's block != curr_bb().

gcc/testsuite/ChangeLog:

        PR tree-optimization/126876
        * gcc.dg/tree-ssa/ssa-thread-abnormal-phi-3.c: New test.
---
 gcc/gimple-range-path.cc                      | 13 +++++++----
 .../tree-ssa/ssa-thread-abnormal-phi-3.c      | 22 +++++++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-abnormal-phi-3.c

diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index 467e321b8de..b9ad77021da 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -254,12 +254,17 @@ path_range_query::ssa_range_in_phi (vrange &r, gphi *phi)
     }
 
   basic_block bb = gimple_bb (phi);
+
+  // During recursive folding the PHI's block may not be curr_bb().
+  if (bb != curr_bb ())
+    {
+      m_ranger.range_of_expr (r, name, phi);
+      return;
+    }
+
   basic_block prev = prev_bb ();
   edge e_in = find_edge (prev, bb);
-  // The incoming edge the path supplies is never abnormal, so the
-  // argument on it is a valid value for the PHI result even when the
-  // result occurs in an abnormal PHI.
-  gcc_checking_assert (!(e_in->flags & EDGE_ABNORMAL));
+  gcc_checking_assert (e_in && !(e_in->flags & EDGE_ABNORMAL));
   tree arg = PHI_ARG_DEF_FROM_EDGE (phi, e_in);
   // Avoid using the cache for ARGs defined in this block, as
   // that could create an ordering problem.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-abnormal-phi-3.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-abnormal-phi-3.c
new file mode 100644
index 00000000000..ae6b5cea48f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-abnormal-phi-3.c
@@ -0,0 +1,22 @@
+/* PR tree-optimization/126876 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* Reduced from ktextaddons cmark-rc/blocks.c.  */
+
+unsigned char *S_parser_feed_eol;
+char S_parser_feed_end;
+void
+S_parser_feed (unsigned char *buffer)
+{
+  while (buffer)
+    {
+      int chunk_len;
+      for (; S_parser_feed_eol;)
+       chunk_len = S_parser_feed_eol - buffer;
+      buffer += chunk_len;
+      if (S_parser_feed_end)
+       if (*buffer)
+         buffer++;
+    }
+}
-- 
2.52.0

Reply via email to