https://gcc.gnu.org/g:e90e0f66051d338c1950d2cc9e36967552d75c3a
commit r17-4047-ge90e0f66051d338c1950d2cc9e36967552d75c3a Author: Shivam Gupta <[email protected]> Date: Mon Sep 7 06:36:15 2026 +0530 tree-optimization: Recognize CLZ loop for signed non-negative values 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. Regression tested on arch64-unknown-linux-gnu. 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. Signed-off-by: Shivam Gupta <[email protected]> Diff: --- gcc/testsuite/gcc.dg/tree-ssa/pr125734.c | 32 ++++++++++++++++++++++++++++++++ gcc/tree-ssa-loop-niter.cc | 26 ++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) 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 000000000000..f8d76c4599c9 --- /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 fa070bb007c7..dd10e3849497 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 ()) + 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. */
