https://gcc.gnu.org/g:c34d17fe720c2934f8486f38687a4d7def17b5cb

commit r17-5477-gc34d17fe720c2934f8486f38687a4d7def17b5cb
Author: Robin Dapp <[email protected]>
Date:   Fri Sep 18 10:03:13 2026 +0200

    niter: Add helper to compute type bound.
    
    This adds the get_niter_type_bound helper and uses it in
    loop_exits_before_overflow as well as derive_simple_iv_with_niters.
    We can re-use it in subsequent patches for computing nowrap bounds.
    
    gcc/ChangeLog:
    
            * tree-scalar-evolution.cc (derive_simple_iv_with_niters): Use
            new function.
            * tree-ssa-loop-niter.cc (loop_exits_before_overflow): Use new
            function.
            (get_niter_type_bound): New function.
            * tree-ssa-loop-niter.h (get_niter_type_bound): Declare.

Diff:
---
 gcc/tree-scalar-evolution.cc | 20 ++++----------------
 gcc/tree-ssa-loop-niter.cc   | 44 +++++++++++++++++++++++++++-----------------
 gcc/tree-ssa-loop-niter.h    |  1 +
 3 files changed, 32 insertions(+), 33 deletions(-)

diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc
index 4386e288de15..c6efbb9a2aa5 100644
--- a/gcc/tree-scalar-evolution.cc
+++ b/gcc/tree-scalar-evolution.cc
@@ -3259,22 +3259,10 @@ derive_simple_iv_with_niters (tree ev, tree *niters)
      folded only if inner iv won't overflow.  We compute the maximum
      number the inner iv can iterate before overflowing and return the
      simplified affine iv.  */
-  tree delta;
-  init = fold_convert (type, init);
-  step = fold_convert (type, step);
-  ev = build_polynomial_chrec (CHREC_VARIABLE (inner_ev), init, step);
-  if (tree_int_cst_sign_bit (step))
-    {
-      tree bound = lower_bound_in_type (inner_type, inner_type);
-      delta = fold_build2 (MINUS_EXPR, type, init, fold_convert (type, bound));
-      step = fold_build1 (NEGATE_EXPR, type, step);
-    }
-  else
-    {
-      tree bound = upper_bound_in_type (inner_type, inner_type);
-      delta = fold_build2 (MINUS_EXPR, type, fold_convert (type, bound), init);
-    }
-  *niters = fold_build2 (FLOOR_DIV_EXPR, type, delta, step);
+  ev = build_polynomial_chrec (CHREC_VARIABLE (inner_ev),
+                              fold_convert (type, init),
+                              fold_convert (type, step));
+  *niters = get_niter_type_bound (inner_type, init, step);
   return ev;
 }
 
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index 871bd1bdf2a8..cc8f1ead0f9a 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -5394,24 +5394,15 @@ nowrap_type_p (tree type)
   return false;
 }
 
-/* Return true if we can prove LOOP is exited before evolution of induction
-   variable {BASE, STEP} overflows with respect to its type bound.  */
+/* Return an upper bound on the number of times the affine IV {BASE, +, STEP}
+   of type TYPE can step while staying within TYPE's range.  */
 
-static bool
-loop_exits_before_overflow (tree base, tree step,
-                           gimple *at_stmt, class loop *loop)
+tree
+get_niter_type_bound (tree type, tree base, tree step)
 {
-  widest_int niter;
-  struct control_iv *civ;
-  class nb_iter_bound *bound;
-  tree e, delta, step_abs, unsigned_base;
-  tree type = TREE_TYPE (step);
-  tree unsigned_type, valid_niter;
-
-  /* Compute the number of iterations before we reach the bound of the
-     type, and verify that the loop is exited before this occurs.  */
-  unsigned_type = unsigned_type_for (type);
-  unsigned_base = fold_convert (unsigned_type, base);
+  tree unsigned_type = unsigned_type_for (type);
+  tree unsigned_base = fold_convert (unsigned_type, base);
+  tree delta, step_abs;
 
   if (tree_int_cst_sign_bit (step))
     {
@@ -5429,7 +5420,26 @@ loop_exits_before_overflow (tree base, tree step,
       step_abs = fold_convert (unsigned_type, step);
     }
 
-  valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type, delta, step_abs);
+  return fold_build2 (FLOOR_DIV_EXPR, unsigned_type, delta, step_abs);
+}
+
+/* Return true if we can prove LOOP is exited before evolution of induction
+   variable {BASE, STEP} overflows with respect to its type bound.  */
+
+static bool
+loop_exits_before_overflow (tree base, tree step,
+                           gimple *at_stmt, class loop *loop)
+{
+  widest_int niter;
+  struct control_iv *civ;
+  class nb_iter_bound *bound;
+  tree e;
+  tree type = TREE_TYPE (step);
+  tree valid_niter;
+
+  /* Compute the number of iterations before we reach the bound of the
+     type, and verify that the loop is exited before this occurs.  */
+  valid_niter = get_niter_type_bound (type, base, step);
 
   estimate_numbers_of_iterations (loop);
 
diff --git a/gcc/tree-ssa-loop-niter.h b/gcc/tree-ssa-loop-niter.h
index 643ac1d7f7fb..24e458f08db7 100644
--- a/gcc/tree-ssa-loop-niter.h
+++ b/gcc/tree-ssa-loop-niter.h
@@ -52,6 +52,7 @@ extern void estimate_numbers_of_iterations (function *);
 extern void estimate_numbers_of_iterations (class loop *);
 extern bool stmt_dominates_stmt_p (gimple *, gimple *);
 extern bool nowrap_type_p (tree);
+extern tree get_niter_type_bound (tree, tree, tree);
 extern bool scev_probably_wraps_p (tree, tree, tree, gimple *,
                                   class loop *, bool);
 extern void free_numbers_of_iterations_estimates (class loop *);

Reply via email to