https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125513
Bug ID: 125513
Summary: [17 Regression] Missed optimization due to recent
nonnegative changes
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: law at gcc dot gnu.org
Target Milestone: ---
This change:
commit a94d2d065efd35473c113cfb38b87234218341a3 (HEAD)
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]>
Triggered this failure:
Tests that now fail, but worked before (10 tests):
gcc: gcc.target/riscv/rvv/vsetvl/avl_single-65.c -O2 scan-assembler-times
vsetvli 3
The code looks worse to me after the change. If I look at the DOM2 dump
before/after we see:
*** good.c.145t.dom2 Sat May 30 14:49:44 2026
--- bad.c.145t.dom2 Sat May 30 14:49:58 2026
*************** Optimizing statement if (_69 > 0)
*** 123,129 ****
Visiting conditional with predicate: if (_72 > 0)
With known ranges
! _72: [irange] int [0, 2147483645] MASK 0x7ffffffd VALUE 0x0
Predicate evaluates to: DON'T KNOW
LKUP STMT _72 gt_expr 0
--- 123,129 ----
Visiting conditional with predicate: if (_72 > 0)
With known ranges
! _72: [irange] int [-INF, -3][0, 2147483645] MASK 0xfffffffd VALUE 0x0
Predicate evaluates to: DON'T KNOW
LKUP STMT _72 gt_expr 0
*************** LKUP STMT _77 = PHI <_74>
*** 350,356 ****
<<<< STMT _75 = PHI <_72>
Optimizing statement if (_75 > 0)
Replaced '_75' with variable '_72'
! Folding predicate _72 > 0 to 1
0>>> COPY _35 = _72
0>>> COPY _38 = _73
0>>> COPY _71 = _74
--- 350,369 ----
<<<< STMT _75 = PHI <_72>
Optimizing statement if (_75 > 0)
Replaced '_75' with variable '_72'
!
! Visiting conditional with predicate: if (_72 > 0)
!
! With known ranges
! _72: [irange] int [-INF, -3][1, 2147483645] MASK 0xfffffffd VALUE 0x0
!
! Predicate evaluates to: DON'T KNOW
So it looks like before the change we had a narrower range for _72 allowing us
to statically compute _72 > 0 as true. After the change the range is wider and
the test of _72 > 0 remains as well as the false path.