https://gcc.gnu.org/g:728104624f30f8eb9f537a3f91b7bb35e4e3a98c

commit r17-4711-g728104624f30f8eb9f537a3f91b7bb35e4e3a98c
Author: Andrew MacLeod <[email protected]>
Date:   Fri Sep 25 10:19:38 2026 -0400

    Correct inferred range application.
    
    If there is an abnormal outgoing edge in a block, we are not supposed to 
apply
    any inferred ranges from the final statement as being exported from the 
block.
    
    The existing code had the logic incorrect. It was adding ranges if there was
    at least 1 normal edge rather than not adding them if there was at least
    one abnormal edge.
    
    The existing testcase was also flawed in that it was missing the flag to
    test with optimization, which caused it to pass when it should not have.
    
    Assisted-by: Claude Opus 5
    
            PR tree-optimization/126531
            gcc/
            * gimple-range-cache.cc (ranger_cache::apply_inferred_ranges): Do 
not
            update if there are abnormal edges.
    
            gcc/testsuite/
            * g++.dg/pr126531.C: Add optimization flag.

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

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 0535b1661d12..f0b20fae327b 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1947,16 +1947,19 @@ ranger_cache::apply_inferred_ranges (gimple *s)
   if (infer.num () == 0)
     return;
 
-  // Do not update the on-entry cache for block ending stmts.
+  // Do not update the on-entry cache for block ending stmts if there is
+  // an outgoing abnormal edge.  Any outgoing abnormal edge makes the
+  // value unsafe to use.
   if (stmt_ends_bb_p (s))
     {
       edge_iterator ei;
       edge e;
       FOR_EACH_EDGE (e, ei, gimple_bb (s)->succs)
-       if (!(e->flags & (EDGE_ABNORMAL|EDGE_EH)))
-         break;
-      if (e == NULL)
-       update = false;
+       if (e->flags & (EDGE_ABNORMAL|EDGE_EH))
+         {
+           update = false;
+           break;
+         }
     }
 
   infer_oracle ().add_ranges (s, infer);
diff --git a/gcc/testsuite/g++.dg/pr126531.C b/gcc/testsuite/g++.dg/pr126531.C
index 4401dbf8fafe..19e2e2baf1c1 100644
--- a/gcc/testsuite/g++.dg/pr126531.C
+++ b/gcc/testsuite/g++.dg/pr126531.C
@@ -1,4 +1,5 @@
 // { dg-do run }
+// { dg-options "-O2" }
 //
 /* 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));",

Reply via email to