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
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" } } */
--
2.53.0