From: Robin Dapp <[email protected]>

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.
---
 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 279ff46474e..b9acdbe9135 100644
--- a/gcc/tree-scalar-evolution.cc
+++ b/gcc/tree-scalar-evolution.cc
@@ -3239,22 +3239,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 0c1ebd1c7d5..fe179b69b05 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -5357,24 +5357,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))
     {
@@ -5392,7 +5383,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 643ac1d7f7f..24e458f08db 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 *);
-- 
2.54.0

Reply via email to