[1/2] Add testcases for backward threading to never-executed edges [PR106495]

Message ID 20260902120747.2705241-2-aldy@quesejoda.com
State New
Headers
Series [1/2] Add testcases for backward threading to never-executed edges [PR106495] |

Commit Message

Aldy Hernandez Sept. 2, 2026, 12:07 p.m. UTC
  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
an 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)

OK?

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.
---
 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(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr106495-1.c
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr106495-2.c
  

Comments

Jeff Law Sept. 2, 2026, 12:44 p.m. UTC | #1
On 9/2/26 6:07 AM, Aldy Hernandez wrote:
> 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
> an 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)
>
> OK?
>
> 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.
OK for the trunk.  For once the verbosity of an LLM is useful :-)  I 
might disagree with the "must not be threaded", it's more of a we don't 
want to thread because it triggers hard to fix diagnostics on a likely 
unreachable path, but it's not worth editing.

Jeff
  
Aldy Hernandez Sept. 2, 2026, 12:55 p.m. UTC | #2
On Wed, Sep 02, 2026 at 06:44:35AM -0600, Jeff Law wrote:
> 
> 
> On 9/2/26 6:07 AM, Aldy Hernandez wrote:
> > 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
> > an 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)
> > 
> > OK?
> > 
> > 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.
> OK for the trunk.  For once the verbosity of an LLM is useful :-)  I might

Heh.  I did prune it down a bit before submitting :).

Aldy
  

Patch

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 00000000000..1cd6258540c
--- /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 00000000000..02e7b821de7
--- /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" } } */