https://gcc.gnu.org/g:0025ab8747c66ce47dd6705460d5e1b0b5d37d39

commit r17-3859-g0025ab8747c66ce47dd6705460d5e1b0b5d37d39
Author: Aldy Hernandez <[email protected]>
Date:   Tue Sep 1 20:17:36 2026 +0000

    Add testcases for backward threading to never-executed edges [PR106495]
    
    r13-1924-gb9da686470d1c2 avoided threading to probably never executed
    edges but landed without a testcase.  Add two, retroactively.
    
    [This is all AI generated.  I used it to to go back in time, create
    testcases from the original preprocessed source code, further reduce
    it with cvise, and then distill it further to create a minimal
    reproducer for the concept, not the warning.  This allows us to keep
    a reduction of the original testcase, plus a conceptual tiny testcase
    to make sure we don't regress going forward.]
    
    Both FAIL before r13-1924 and PASS with it.
    
    Assisted-by: Claude Fable 5 (Anthropic)
    
    gcc/testsuite/ChangeLog:
    
            PR tree-optimization/106495
            PR tree-optimization/126906
            * gcc.dg/tree-ssa/pr106495-1.c: New test.
            * gcc.dg/tree-ssa/pr106495-2.c: New test.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/pr106495-1.c | 76 ++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr106495-2.c | 27 +++++++++++
 2 files changed, 103 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr106495-1.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr106495-1.c
new file mode 100644
index 000000000000..40a07b48e41a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr106495-1.c
@@ -0,0 +1,76 @@
+/* PR tree-optimization/106495 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Warray-bounds -fdump-tree-threadfull1-details" } */
+
+/* Reduced from PR106495 (attachment 53396, comment #6): the i686 bootstrap
+   broke with -Werror=array-bounds.  The calls to the cold noreturn fancy_abort
+   clobber memory, so m_vec is reloaded for each access; the backward threader
+   can then resolve the m_vec == NULL path, where vec_length () is 0 and the
+   index wraps to 4294967294, and isolate it even though it ends in a probably
+   never executed edge.  Nothing real ever executes the path, but the
+   materialized dead statements drew a bogus -Warray-bounds warning (ilp32
+   only; the threadfull1 scan below discriminates on all targets).
+
+   The PR106495 fix rejects such paths in profitable_path_p: this test FAILs
+   before that commit and PASSes with it.  cvise-reduced from the original .ii
+   file, and then the AI converted the C++ vec templates to plain C.  See
+   pr106495-2.c for a minimal distillation.  */
+
+void fancy_abort (const char *, int, const char *)
+  __attribute__ ((noreturn)) __attribute__ ((cold));
+
+typedef int *basic_block;
+
+unsigned m_num;
+
+struct vec_embed
+{
+  int m_pad;
+  basic_block m_vecdata[];
+};
+
+struct vec
+{
+  struct vec_embed *m_vec;
+};
+
+static inline unsigned
+embed_length (struct vec_embed *v)
+{
+  return m_num;
+}
+
+static inline basic_block
+embed_index (struct vec_embed *v, unsigned ix)
+{
+  if (!(ix < m_num))
+    fancy_abort ("", 9, __FUNCTION__);
+  return v->m_vecdata[ix];     /* { dg-bogus "above array bounds" } */
+}
+
+static inline unsigned
+vec_length (struct vec *v)
+{
+  return v->m_vec ? embed_length (v->m_vec) : 0;
+}
+
+static inline basic_block
+vec_index (struct vec *v, unsigned ix)
+{
+  return embed_index (v->m_vec, ix);
+}
+
+void find_edge (basic_block, basic_block);
+
+struct vec m_path;
+
+void
+profitable_path_p (void)
+{
+  int len1 = vec_length (&m_path);
+  unsigned len2 = vec_length (&m_path);
+  basic_block bb = vec_index (&m_path, len1 - 2);
+  find_edge (vec_index (&m_path, len2 - 1), bb);
+}
+
+/* { dg-final { scan-tree-dump "path leads to probably never executed edge" 
"threadfull1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr106495-2.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr106495-2.c
new file mode 100644
index 000000000000..02e7b821de74
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr106495-2.c
@@ -0,0 +1,27 @@
+/* PR tree-optimization/106495 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdisable-tree-ethread -fdump-tree-threadfull1-details" } 
*/
+
+/* Minimal distillation of pr106495-1.c, pinning the never-executed
+   taken-edge veto (PR105679, PR106495): a resolvable thread whose
+   taken edge is probably never executed and whose destination holds
+   real code (a call to abort, not just __builtin_unreachable) must
+   not be threaded, lest we isolate never-executed paths that the
+   late diagnostic passes then warn about.  Without the r13-1924 veto
+   the 3->4 path threads straight into the abort block.
+   -fdisable-tree-ethread keeps the early threader from resolving the
+   path before profile estimation makes the edge cold.  */
+
+void abort (void);
+int g;
+
+void
+f (int x)
+{
+  if (x < 0)
+    g = 1;
+  if (x < 0)
+    abort ();
+}
+
+/* { dg-final { scan-tree-dump "path leads to probably never executed edge" 
"threadfull1" } } */

Reply via email to