for some reason I cannot recall, when processing builtin_unreachable calls the final time, edges were stored in a vector by providing the src and dest blocks.

In this case, there was a no-return call which required a block to be split, and thus there was no direct edge between the src and dest when we got to the list.

Corrected by simply providing the edge in the vector instead of endpoints.

bootstrapped on x86_64-pc-linux-gnu with no regressions.

Andrew

From 8dcf4a63cf3f9fcceed9235066055f0ad7ef09ab Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Mon, 24 Aug 2026 13:55:40 -0400
Subject: [PATCH 2/2] Save the edge in remove_unreachable.

Instead of saving the endpoints, save the edge in case blocks are split.

	PR tree-optimization/126999
	gcc/
	* tree-vrp.cc (remove_unreachable::m_list): Change from a std::pair
	to an edge vector.
	(remove_unreachable::maybe_register): Save edge.
	(remove_unreachable::remove): Use the edge.
	(remove_unreachable::remove_and_update_globals): Likewise.

	gcc/testsuite/
	* gcc.dg/pr126999.c: New.
---
 gcc/testsuite/gcc.dg/pr126999.c | 40 +++++++++++++++++++++++++++++++++
 gcc/tree-vrp.cc                 | 20 +++++------------
 2 files changed, 45 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr126999.c

diff --git a/gcc/testsuite/gcc.dg/pr126999.c b/gcc/testsuite/gcc.dg/pr126999.c
new file mode 100644
index 00000000000..e32980beaf3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr126999.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+#include <stdint.h>
+typedef void (*fp_t_2)();
+void *g12;
+uint16_t g22;
+_Bool f19_c11;
+void f3()
+{
+lbl_dead2:
+    goto lbl_dead2;
+}
+void f19()
+{
+    _Bool c0;
+    fp_t_2 fp5;
+    uint16_t v7;
+    _Bool c10 = fp5 = f19;
+lbl_sw1:
+    if (c0) goto lbl_br5;
+    if (f19_c11) goto lbl_br53;
+    if (c10) __builtin_unreachable();
+    return;
+lbl_br5:
+    c0 = 1 == g22;
+    if (c0) goto lbl_sw_def26;
+    if (c10) goto lbl_sw1;
+lbl_bf10:
+    c0 = 0 >= g22;
+    c10 = g12;
+    goto lbl_sw1;
+lbl_sw_def26:
+    fp5 = f3;
+    g22 = v7;
+    goto lbl_bf10;
+lbl_br53:
+    fp5();
+    if (c10) __builtin_unreachable();
+}
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index 6f1e3eb9035..dc8256dc33d 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -93,7 +93,7 @@ public:
   bool remove ();
   bool remove_and_update_globals ();
   bool fully_replaceable (tree name, basic_block bb);
-  vec<std::pair<int, int> > m_list;
+  vec<edge> m_list;
   range_query &m_ranger;
   bool final_p;
   bitmap m_tmp;
@@ -131,7 +131,7 @@ remove_unreachable::maybe_register (gimple *s)
   if (!final_p)
     handle_early (s, e);
   else
-    m_list.safe_push (std::make_pair (e->src->index, e->dest->index));
+    m_list.safe_push (e);
 }
 
 // Return true if all uses of NAME are dominated by block BB.  1 use
@@ -266,12 +266,7 @@ remove_unreachable::remove ()
   unsigned i;
   for (i = 0; i < m_list.length (); i++)
     {
-      auto eb = m_list[i];
-      basic_block src = BASIC_BLOCK_FOR_FN (cfun, eb.first);
-      basic_block dest = BASIC_BLOCK_FOR_FN (cfun, eb.second);
-      if (!src || !dest)
-	continue;
-      edge e = find_edge (src, dest);
+      edge e = m_list[i];
       gimple *s = gimple_outgoing_range_stmt_p (e->src);
       gcc_checking_assert (gimple_code (s) == GIMPLE_COND);
 
@@ -279,7 +274,7 @@ remove_unreachable::remove ()
       if (!name)
 	name = gimple_range_ssa_p (gimple_cond_rhs (s));
       // Check if global value can be set for NAME.
-      if (name && fully_replaceable (name, src))
+      if (name && fully_replaceable (name, e->src))
 	{
 	  value_range r (TREE_TYPE (name));
 	  if (gori_name_on_edge (r, name, e, &m_ranger))
@@ -322,12 +317,7 @@ remove_unreachable::remove_and_update_globals ()
   auto_bitmap all_exports;
   for (i = 0; i < m_list.length (); i++)
     {
-      auto eb = m_list[i];
-      basic_block src = BASIC_BLOCK_FOR_FN (cfun, eb.first);
-      basic_block dest = BASIC_BLOCK_FOR_FN (cfun, eb.second);
-      if (!src || !dest)
-	continue;
-      edge e = find_edge (src, dest);
+      edge e = m_list[i];
       gimple *s = gimple_outgoing_range_stmt_p (e->src);
       gcc_checking_assert (gimple_code (s) == GIMPLE_COND);
 
-- 
2.55.0

Reply via email to