[PATCH v2 1/5] niter: Add helper to compute type bound.
Robin Dapp <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
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 cd99cbe86ce..80f24ec86a5 100644 --- a/gcc/tree-scalar-evolution.cc +++ b/gcc/tree-scalar-evolution.cc @@ -3247,22 +3247,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