https://gcc.gnu.org/g:a94d2d065efd35473c113cfb38b87234218341a3
commit r17-992-ga94d2d065efd35473c113cfb38b87234218341a3 Author: Andrew Pinski <[email protected]> Date: Wed May 27 21:09:01 2026 -0700 ranger-fold: Don't call into gimple_stmt_nonnegative_p [PR125475] When fold_using_range::fold_stmt comes in with a varying range, it currently calls gimple_stmt_nonnegative_p to see if the value is non-negative. But in the case where it matters (pr33738.C), it will return true always because here we have just an unsigned type. That sets the range to `[0, type_max]`. So instead we should check if the type_min/type_max is not the same as precisionmin/precisionmax and set the range to `[type_min, type_max]` in that case. This fixes a recusion if we change tree_expr_nonnegative_p over to use the ranger and I suspect might it help Ada code too. PR tree-optimization/125475 gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::fold_stmt): Don't call gimple_stmt_nonnegative_p. Instead set the varying range to `[type_min, type_max]` if not the same as the precision. Signed-off-by: Andrew Pinski <[email protected]> Diff: --- gcc/gimple-range-fold.cc | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 149ad5e77476..c3f720a786f6 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -684,12 +684,22 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) else if (is_a<gassign *> (s) && gimple_assign_rhs_code (s) == COND_EXPR) res = range_of_cond_expr (r, as_a<gassign *> (s), src); - // If the result is varying, check for basic nonnegativeness. - // Specifically this helps for now with strict enum in cases like - // g++.dg/warn/pr33738.C. - if (res && r.varying_p () && INTEGRAL_TYPE_P (r.type ()) - && gimple_stmt_nonnegative_p (s)) - r.set_nonnegative (r.type ()); + // If the result is varying, use the type's min/max if either is not + // the same as the full precision min/max. This helps with strict enum + // e.g. `g++.dg/warn/pr33738.C`. + if (res && r.varying_p () && INTEGRAL_TYPE_P (r.type ())) + { + irange &ir = as_a <irange> (r); + tree type = r.type (); + auto typemax = wi::to_wide (TYPE_MAX_VALUE (type)); + auto typemin = wi::to_wide (TYPE_MIN_VALUE (type)); + auto precisionmax = wi::max_value (TYPE_PRECISION (type), + TYPE_SIGN (type)); + auto precisionmin = wi::min_value (TYPE_PRECISION (type), + TYPE_SIGN (type)); + if (typemax != precisionmax || typemin != precisionmin) + ir.set (type, typemin, typemax); + } if (!res) {
