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" } } */
