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.  */

Reply via email to