On Thu, Sep 10, 2026 at 10:50 PM Andrea Pinski
<[email protected]> wrote:
>
> On Thu, Sep 10, 2026 at 10:17 AM Shivam Gupta <[email protected]> wrote:
> >
> > On Thu, Sep 10, 2026 at 10:45 PM Andrea Pinski
> > <[email protected]> wrote:
> > >
> > > On Thu, Sep 10, 2026 at 2:13 AM Richard Biener
> > > <[email protected]> wrote:
> > > >
> > > > On Mon, Sep 7, 2026 at 3:07 AM Shivam Gupta <[email protected]>
> > > > wrote:
> > > > >
> > > > > is_rshift_by_1 previously checked TYPE_UNSIGNED on the shift
> > > > > statement,
> > > > > preventing signed arithmetic right shifts from being optimized into
> > > > > CLZ
> > > > > calls. However, an arithmetic right shift behaves identically to a
> > > > > logical
> > > > > right shift when the initial operand entering the loop is
> > > > > non-negative.
> > > > >
> > > > > This patch removes the strict TYPE_UNSIGNED requirement from
> > > > > is_rshift_by_1
> > > > > and adds ranger range_on_edge non-negativity checks in
> > > > > number_of_iterations_cltz
> > > > > and number_of_iterations_cltz_complement on the loop preheader edge.
> > > > >
> > > > > PR tree-optimization/125734
> > > > >
> > > > > gcc/ChangeLog:
> > > > >
> > > > > * tree-ssa-loop-niter.cc (is_rshift_by_1): Remove
> > > > > TYPE_UNSIGNED restriction.
> > > > > (number_of_iterations_cltz): Use range_on_edge to check
> > > > > non-negativity of
> > > > > signed preheader input.
> > > > > (number_of_iterations_cltz_complement): Likewise.
> > > > >
> > > > > gcc/testsuite/ChangeLog:
> > > > >
> > > > > * gcc.dg/tree-ssa/pr125734.c: New test.
> > > > >
> > > > > Regression tested on arch64-unknown-linux-gnu.
> > > > >
> > > > > Signed-off-by: Shivam Gupta <[email protected]>
> > > > > ---
> > > > > gcc/testsuite/gcc.dg/tree-ssa/pr125734.c | 32
> > > > > ++++++++++++++++++++++++
> > > > > gcc/tree-ssa-loop-niter.cc | 26 +++++++++++++++++--
> > > > > 2 files changed, 56 insertions(+), 2 deletions(-)
> > > > > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr125734.c
> > > > >
> > > > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr125734.c
> > > > > b/gcc/testsuite/gcc.dg/tree-ssa/pr125734.c
> > > > > new file mode 100644
> > > > > index 000000000..f8d76c459
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125734.c
> > > > > @@ -0,0 +1,32 @@
> > > > > +/* { dg-do compile } */
> > > > > +/* { dg-options "-O2 -fdump-tree-optimized" } */
> > > > > +
> > > > > +int
> > > > > +nlz32 (int b)
> > > > > +{
> > > > > + int c = sizeof(b) * 8;
> > > > > + if (b < 0)
> > > > > + return -1;
> > > > > + while (b != 0)
> > > > > + {
> > > > > + b >>= 1;
> > > > > + c--;
> > > > > + }
> > > > > + return c;
> > > > > +}
> > > > > +
> > > > > +int
> > > > > +nlz32_negative (int b)
> > > > > +{
> > > > > + int c = sizeof(b) * 8;
> > > > > +
> > > > > + while (b != 0)
> > > > > + {
> > > > > + b >>= 1;
> > > > > + c--;
> > > > > + }
> > > > > +
> > > > > + return c;
> > > > > +}
> > > > > +
> > > > > +/* { dg-final { scan-tree-dump-times "\\.CLZ" 1 "optimized" } } */
> > > > > diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
> > > > > index 0c1ebd1c7..3ce3dccfa 100644
> > > > > --- a/gcc/tree-ssa-loop-niter.cc
> > > > > +++ b/gcc/tree-ssa-loop-niter.cc
> > > > > @@ -2313,8 +2313,6 @@ is_lshift_by_1 (gassign *stmt)
> > > > > static bool
> > > > > is_rshift_by_1 (gassign *stmt)
> > > > > {
> > > > > - if (!TYPE_UNSIGNED (TREE_TYPE (gimple_assign_lhs (stmt))))
> > > > > - return false;
> > > > > if (gimple_assign_rhs_code (stmt) == RSHIFT_EXPR
> > > > > && integer_onep (gimple_assign_rhs2 (stmt)))
> > > > > return true;
> > > > > @@ -2482,6 +2480,18 @@ number_of_iterations_cltz (loop_p loop, edge
> > > > > exit,
> > > > >
> > > > > /* We found a match. */
> > > > > tree src = gimple_phi_arg_def (phi, loop_preheader_edge
> > > > > (loop)->dest_idx);
> > > > > +
> > > > > + /* If the type is signed, verify via Ranger on the preheader edge
> > > > > + that the initial value entering the loop is non-negative. */
> > > > > + if (!TYPE_UNSIGNED (TREE_TYPE (src)))
> > > > > + {
> > > > > + int_range_max r (TREE_TYPE (src));
> > > > > + edge e = loop_preheader_edge (loop);
> > > > > + if (!get_range_query (cfun)->range_on_edge (r, e, src)
> > > > > + || !r.nonnegative_p ())
> > > >
> > > > I think you need to fend off r.undefined_p ()?
> > >
> > > Yes that is needed. I always forget what range_on_edge's return value
> > > means; true means the type is supported and not the range would be
> > > undefined.
> > >
> >
> > Do you want me to create a patch for this and regression test that? Or
> > will you be doing a direct push?
>
> Can you create and test the patch? I will push it once it has been tested.
>
Yes, sure, I will send a new patch after testing it. Thanks!
> >
> > > >
> > > > > + return false;
> > > > > + }
> > > > > +
> > > > > int src_precision = TYPE_PRECISION (TREE_TYPE (src));
> > > > >
> > > > > /* Save the original SSA name before preprocessing for ranger
> > > > > queries. */
> > > > > @@ -2641,6 +2651,18 @@ number_of_iterations_cltz_complement (loop_p
> > > > > loop, edge exit,
> > > > >
> > > > > /* We found a match. */
> > > > > tree src = gimple_phi_arg_def (phi, loop_preheader_edge
> > > > > (loop)->dest_idx);
> > > > > +
> > > > > + /* If the type is signed, verify via Ranger on the preheader edge
> > > > > + that the initial value entering the loop is non-negative. */
> > > > > + if (!TYPE_UNSIGNED (TREE_TYPE (src)))
> > > > > + {
> > > > > + int_range_max r (TREE_TYPE (src));
> > > > > + edge e = loop_preheader_edge (loop);
> > > > > + if (!get_range_query (cfun)->range_on_edge (r, e, src)
> > > > > + || !r.nonnegative_p ())
> > > > > + return false;
> > > > > + }
> > > > > +
> > > > > int src_precision = TYPE_PRECISION (TREE_TYPE (src));
> > > > >
> > > > > /* Get the corresponding c[lt]z builtin. */
> > > > > --
> > > > > 2.43.0
> > > > >