[gcc r17-3171] Improve tree_expr_nonnegative_p by using the ranger [PR111959]

Andrea Pinski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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" } } */
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.