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.

Reply via email to