https://gcc.gnu.org/g:5af52562e3fb59bcecaa25ef834424e7f7076400

commit r17-3171-g5af52562e3fb59bcecaa25ef834424e7f7076400
Author: Andrea Pinski <[email protected]>
Date:   Thu Aug 6 20:03:46 2026 -0700

    Improve tree_expr_nonnegative_p by using the ranger [PR111959]
    
    When I was looking into fixing tree_expr_nonnegative_p not to be recusive,
    we should have tree_expr_nonnegative_p use the ranger.
    I also didn't realize I wrote this patch before so this is
    the updated version of the already approved:
    https://gcc.gnu.org/pipermail/gcc-patches/2023-October/634205.html
    Updated for the review comments.
    
    Note testsuite/g++.dg/ipa/pure-const-3.C testcase will always fail as we can
    use the fact the argument is always non-negative in many different places 
now.
    Since there is no way to test it, let's remove the testcase.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
    Changes since v1:
    * Use get_range_query instead of the global range.
    Update the wording on pr80776-1.c testcase and add new testcase without dom.
    
            PR tree-optimization/111959
    
    gcc/ChangeLog:
    
            * fold-const.cc (tree_single_nonnegative_p): Use the range to see
            if the SSA_NAME was nonnegative.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/pr80776-1.c: xfail and update comment.
            * gcc.dg/pr80776-1a.c: New test.
            * gcc.dg/tree-ssa/forwprop-44.c: New test.
            * g++.dg/ipa/pure-const-3.C: Remove.
    
    Signed-off-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/fold-const.cc                           | 13 +++++++++++++
 gcc/testsuite/g++.dg/ipa/pure-const-3.C     |  6 ------
 gcc/testsuite/gcc.dg/pr80776-1.c            | 15 +++++----------
 gcc/testsuite/gcc.dg/pr80776-1a.c           | 26 ++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/forwprop-44.c | 14 ++++++++++++++
 5 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index c15a6b7804dc..420e3185a2af 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -14693,6 +14693,19 @@ tree_single_nonnegative_p (tree t, int depth)
       return RECURSE (TREE_OPERAND (t, 1)) && RECURSE (TREE_OPERAND (t, 2));
 
     case SSA_NAME:
+      /* For integral types, query the range if possible. */
+      if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
+       {
+         int_range_max r;
+         get_range_query (cfun)->range_of_expr (r, t);
+         if (!r.undefined_p () && !r.varying_p())
+           {
+             if (r.nonnegative_p ())
+               return true;
+             if (r.nonpositive_p () && !range_includes_zero_p (r))
+               return false;
+           }
+       }
       /* Limit the depth of recursion to avoid quadratic behavior.
         This is expected to catch almost all occurrences in practice.
         If this code misses important cases that unbounded recursion
diff --git a/gcc/testsuite/g++.dg/ipa/pure-const-3.C 
b/gcc/testsuite/g++.dg/ipa/pure-const-3.C
deleted file mode 100644
index 62d355b4ce7e..000000000000
--- a/gcc/testsuite/g++.dg/ipa/pure-const-3.C
+++ /dev/null
@@ -1,6 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O2 -fno-ipa-vrp -fdump-tree-optimized -fno-tree-ccp 
-fdisable-tree-evrp -fdisable-tree-vrp1 -fdisable-tree-vrp2 -fno-thread-jumps 
-fno-tree-dominator-opts"  } */
-
-#include "pure-const-3.h"
-
-/* { dg-final { scan-tree-dump "barvar"  "optimized"  } } */
diff --git a/gcc/testsuite/gcc.dg/pr80776-1.c b/gcc/testsuite/gcc.dg/pr80776-1.c
index b9bce62d9820..20a8b68b7500 100644
--- a/gcc/testsuite/gcc.dg/pr80776-1.c
+++ b/gcc/testsuite/gcc.dg/pr80776-1.c
@@ -18,14 +18,9 @@ Foo (void)
   if (! (0 <= i && i <= 999999))
     __builtin_unreachable ();
 
-  /* Legacy evrp sets the range of i to [0, MAX] *before* the first 
conditional,
-     and to [0,999999] *before* the second conditional.  This is because both
-     evrp and VRP use trickery to set global ranges when this particular use of
-     a __builtin_unreachable is in play (see uses of
-     assert_unreachable_fallthru_edge_p).
-
-     Setting these ranges at the definition site, causes VRP to remove the
-     unreachable code altogether, leaving the following sprintf unguarded.  
This
-     causes the bogus warning below.  */
-  sprintf (number, "%d", i); /* { dg-bogus "writing" "" } */
+  /* DOM does not handle unreachable in a decent way and sets the range for
+     i to be to [0,INF] rather than what VRP would do as [0,99999].
+     Causing the warning to show up.  VRP does not update the range since the 
default
+     from an argument.  See PR 126704. */
+  sprintf (number, "%d", i); /* { dg-bogus "writing" "" { xfail *-*-* } } */
 }
diff --git a/gcc/testsuite/gcc.dg/pr80776-1a.c 
b/gcc/testsuite/gcc.dg/pr80776-1a.c
new file mode 100644
index 000000000000..d811ca3a254d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr80776-1a.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wformat-overflow -fno-tree-dominator-opts" } */
+
+extern __inline __attribute__ ((__always_inline__)) __attribute__ 
((__gnu_inline__)) __attribute__ ((__artificial__)) int
+__attribute__ ((__nothrow__ , __leaf__)) sprintf (char *__restrict __s, const 
char *__restrict __fmt, ...)
+{
+  return __builtin___sprintf_chk (__s, 2 - 1,
+                                 __builtin_object_size (__s, 2 > 1), __fmt, 
__builtin_va_arg_pack ());
+}
+char number[sizeof "999999"];
+int somerandom (void);
+void
+Foo (void)
+{
+  int i = somerandom ();
+  if (! (0 <= i))
+    __builtin_unreachable ();
+  if (! (0 <= i && i <= 999999))
+    __builtin_unreachable ();
+
+  /* DOM does not handle unreachable in a decent way and sets the range for
+     i to be to [0,INF] rather than what VRP would do as [0,99999].
+     Causing the warning to show up.  VRP does not update the range since the 
default
+     from an argument.  */
+  sprintf (number, "%d", i); /* { dg-bogus "writing" "" } */
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-44.c 
b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-44.c
new file mode 100644
index 000000000000..50b74fa0753a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-44.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* PR tree-optimization/111959 */
+
+int divbypow2(int a, int b)
+{
+  if (a & ~0xff) __builtin_unreachable();
+  return a / (1<<b);
+}
+
+/* divbypow2 should be able to optimize to just a/b as a is known to be always 
positive. */
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
+/* { dg-final { scan-tree-dump-not " << " "optimized" } } */
+/* { dg-final { scan-tree-dump-times " >> " 1 "optimized" } } */

Reply via email to