[gcc r17-3205] Check for abnoraml ranges on full dom search.

Andrew Macleod via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:de2d80d1101e1921d719918d57589ea2668dcc1f

commit r17-3205-gde2d80d1101e1921d719918d57589ea2668dcc1f
Author: Andrew MacLeod <[email protected]>
Date:   Thu Aug 6 14:15:21 2026 -0400

    Check for abnoraml ranges on full dom search.
    
    Inferred ranges are not adde dif the predecessor was an abnormal edge.
    This is extended to finding a taken  abnrmal edge anywhere in the dominator
    search.
    
            PR tree-optimization/126531
            gcc/
            * gimple-range-cache.cc (ranger_cache::range_from_dom): Track
            abnormal edges throughout the dom search.
    
            gcc/testsuite/
            * g++.dg/pr126531.C: New.

Diff:
---
 gcc/gimple-range-cache.cc       | 26 +++++++++++++++++-----
 gcc/testsuite/g++.dg/pr126531.C | 49 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index c5a19c866fb0..a540a10ce588 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1813,11 +1813,28 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb,
   else
     bb = get_immediate_dominator (CDI_DOMINATORS, start_bb);
 
+  bool abnormal_dominator = false;
   // Search until a value is found, pushing blocks which may need calculating.
   for ( ; bb; prev_bb = bb, bb = get_immediate_dominator (CDI_DOMINATORS, bb))
     {
-      // Accumulate any block exit inferred ranges.
-      infer_oracle ().maybe_adjust_range (infer, name, bb);
+      if (has_abnormal_call_or_eh_pred_edge_p (prev_bb))
+	abnormal_dominator = true;
+
+      // find the taken outgoing edge and check if it is abnormal.
+      if (!abnormal_dominator)
+	{
+	  edge e;
+	  edge_iterator ei;
+	  FOR_EACH_EDGE (e, ei, bb->succs)
+	    if (dominated_by_p (CDI_DOMINATORS, prev_bb, e->dest))
+	      {
+		if (e->flags & (EDGE_ABNORMAL | EDGE_EH))
+		  abnormal_dominator = true;
+		break;
+	      }
+	  // Accumulate any block exit inferred ranges.
+	  infer_oracle ().maybe_adjust_range (infer, name, bb);
+	}
 
       // This block has an outgoing range.
       if (gori ().has_edge_range_p (name, bb))
@@ -1904,9 +1921,8 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb,
 	}
     }
 
-  // Apply non-null if appropriate.
-  if (!has_abnormal_call_or_eh_pred_edge_p (start_bb))
-    r.intersect (infer);
+  // Apply any inferred ranges discovered.
+  r.intersect (infer);
 
   if (DEBUG_RANGE_CACHE)
     {
diff --git a/gcc/testsuite/g++.dg/pr126531.C b/gcc/testsuite/g++.dg/pr126531.C
new file mode 100644
index 000000000000..4401dbf8fafe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr126531.C
@@ -0,0 +1,49 @@
+// { dg-do run }
+//
+/* More than 16 bytes, so S is returned in memory.  *p becomes the return slot
+   of the call and GIMPLE keeps a single statement "*p_7(D) = h (k_8(D));",
+   a call that can throw whose store operand infers p != 0.  */
+
+struct S { int a[8]; };
+
+__attribute__((noipa)) S
+h (int k)
+{
+  if (k)
+    throw 1;                    /* Thrown before anything is stored.  */
+  S s = {};
+  s.a[0] = 5;
+  return s;
+}
+
+__attribute__((noipa)) int
+f (S *p, int k)
+{
+  int r = 0;
+  try
+    {
+      *p = h (k);               /* Infers p != 0, but only if it completes.  */
+      r = 1;
+    }
+  catch (...)
+    {
+      if (p == 0)               /* Must not fold: the store never ran.  */
+        r = 12;
+      else
+        r = 2;
+    }
+  return r;
+}
+
+S obj;
+
+int
+main (void)
+{
+  if (f (&obj, 0) != 1)         /* Normal path, p is &obj.  */
+    __builtin_abort ();
+  if (f (0, 1) != 12)           /* h throws, no store, p is null.  */
+    __builtin_abort ();
+  return 0;
+}
+
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.