The testcase triggers a problem that when an ssa_name was released by simple_dce_from_worklist.  The same name was then used from a cached value i the relation oracle.  This patch modifies release_ssa_name_fn such that when an ssa name is being released, it also clear any current range info.   THis is similar to what is done during reset_flow_sensitive_info ().

This also uncovered a bug in the def chains where clearing the def chain immediately rebuilds it.  This is inadvisable when the name is being released!

Bootstrapped on x86_64-pc-linux-gnu with no new regressions. Pushed.

Andrew


From 0a2afa20f79f4554a3858c8bd831862991d0221d Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <[email protected]>
Date: Mon, 5 Oct 2026 09:46:48 -0400
Subject: [PATCH] Clear range info when freeing an ssa name.

When an ssa name is being released, clear any current range info.  THis
also uncovered a bug in the def chains where clearing the def chain
immediately rebuilds it.  This is inadvisable when the name is being
released!  It also wasn't clearing the import field.

	PR tree-optimization/127719
	gcc
	* gimple-range-gori.cc (range_def_chain::clear): Do not
	recalculate a def chain when it has just been cleared.
	* tree-ssanames.cc (release_ssa_name_fn): Clear range info.

	gcc/testsuite/
	* gcc.dg/pr127719.c: New.
	* g++.dg/pr127729.C: New.
---
 gcc/gimple-range-gori.cc        |  2 +-
 gcc/testsuite/g++.dg/pr127729.C | 56 +++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/pr127719.c | 18 +++++++++++
 gcc/tree-ssanames.cc            |  5 +++
 4 files changed, 80 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/pr127729.C
 create mode 100644 gcc/testsuite/gcc.dg/pr127719.c

diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index d34c2b79a7c..7d62cb18498 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -307,7 +307,7 @@ range_def_chain::clear (tree name)
   m_def_chain[v].ssa1 = 0;
   m_def_chain[v].ssa2 = 0;
   m_def_chain[v].bm = NULL;
-  get_def_chain (name);
+  m_def_chain[v].m_import = NULL;
 }
 
 // Dump what we know for basic block BB to file F.
diff --git a/gcc/testsuite/g++.dg/pr127729.C b/gcc/testsuite/g++.dg/pr127729.C
new file mode 100644
index 00000000000..c28de0f255a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr127729.C
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+enum E {};
+bool getKnownMinValue();
+struct TypeSize {
+  bool Scalable;
+} getSizeInBits_SizeTable;
+extern TypeSize SizeTable[];
+void isKnownGT(TypeSize);
+struct MVT {
+  E SimpleTy;
+} V, LowerFCOPYSIGN___trans_tmp_10;
+E getSizeInBits_e_0;
+static void knownBitsGT(MVT e, MVT VT) {
+  TypeSize __trans_tmp_4, __trans_tmp_1;
+  switch (VT.SimpleTy)
+  case 0:
+  case 2:
+    __trans_tmp_1 = getSizeInBits_SizeTable;
+  switch (e.SimpleTy) {
+  case 0:
+  case 2:
+  case 3:
+    __builtin_unreachable();
+  default:
+    __trans_tmp_4 = SizeTable[e.SimpleTy];
+  }
+  isKnownGT(__trans_tmp_4);
+  isKnownGT(__trans_tmp_1);
+}
+static bool knownBitsLT(MVT e) {
+  switch (getSizeInBits_e_0)
+  case 2:
+    __builtin_unreachable();
+  switch (e.SimpleTy)
+  case 0:
+  case 2:
+  case 3:
+    __builtin_unreachable();
+  TypeSize LHS;
+  if (LHS.Scalable)
+    return getKnownMinValue();
+  return false;
+}
+bool LowerFCOPYSIGN_bl;
+void LowerFCOPYSIGN() {
+  MVT __trans_tmp_12, __trans_tmp_11 = LowerFCOPYSIGN___trans_tmp_10,
+                      __trans_tmp_7 = __trans_tmp_11, VT;
+  LowerFCOPYSIGN_bl = knownBitsLT(__trans_tmp_7);
+  if (LowerFCOPYSIGN_bl)
+    LowerFCOPYSIGN___trans_tmp_10 = V;
+  __trans_tmp_12 = LowerFCOPYSIGN___trans_tmp_10;
+  MVT __trans_tmp_8 = __trans_tmp_12;
+  knownBitsGT(__trans_tmp_8, VT);
+}
diff --git a/gcc/testsuite/gcc.dg/pr127719.c b/gcc/testsuite/gcc.dg/pr127719.c
new file mode 100644
index 00000000000..c1a208f033b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr127719.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short a;
+unsigned b;
+void c() {
+  char d = b;
+  long e = b + (a & 5ull) & 1;
+  if ((unsigned long)b - 2 + e)
+    if (e)
+      __builtin_unreachable();
+  do {
+    d >>= e;
+    if (d)
+      break;
+  } while (1);
+}
+int main() {}
diff --git a/gcc/tree-ssanames.cc b/gcc/tree-ssanames.cc
index 8eac57f42cb..603bdc43098 100644
--- a/gcc/tree-ssanames.cc
+++ b/gcc/tree-ssanames.cc
@@ -692,6 +692,11 @@ release_ssa_name_fn (struct function *fn, tree var)
       int saved_ssa_name_version = SSA_NAME_VERSION (var);
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
+      /* An active range query caches information keyed off both VAR and its
+	 version, communicate that this node is about to be cleared.  */
+      if (fn->x_range_query)
+	fn->x_range_query->reset_range_info (var);
+
       if (MAY_HAVE_DEBUG_BIND_STMTS)
 	insert_debug_temp_for_var_def (NULL, var);
 
-- 
2.55.0

Reply via email to