aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-niter.c
diff options
context:
space:
mode:
authorEdward Smith-Rowland <3dw4rd@verizon.net>2017-07-20 14:54:44 +0000
committerEdward Smith-Rowland <3dw4rd@verizon.net>2017-07-20 14:54:44 +0000
commit3acaf2e51caf356a9afc763cfd70b91d1ab094b5 (patch)
treef13b1087143457ae5c053b6ec3b664c2aaeab169 /gcc/tree-ssa-loop-niter.c
parentc4d46197c5fe4461da59ce027bc68306c43186b0 (diff)
Merged revisions r232323 through r250392 to the branch
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/tr29124@250393 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r--gcc/tree-ssa-loop-niter.c170
1 files changed, 115 insertions, 55 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index e67cd930946..e0107c28dfb 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1142,8 +1142,12 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
tree niter_type = TREE_TYPE (step);
tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step);
tree tmod;
- tree assumption = boolean_true_node, bound;
- tree type1 = (POINTER_TYPE_P (type)) ? sizetype : type;
+ mpz_t mmod;
+ tree assumption = boolean_true_node, bound, noloop;
+ bool ret = false, fv_comp_no_overflow;
+ tree type1 = type;
+ if (POINTER_TYPE_P (type))
+ type1 = sizetype;
if (TREE_CODE (mod) != INTEGER_CST)
return false;
@@ -1151,51 +1155,96 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
tmod = fold_convert (type1, mod);
+ mpz_init (mmod);
+ wi::to_mpz (mod, mmod, UNSIGNED);
+ mpz_neg (mmod, mmod);
+
/* If the induction variable does not overflow and the exit is taken,
- then the computation of the final value does not overflow. There
- are three cases:
- 1) The case if the new final value is equal to the current one.
- 2) Induction varaible has pointer type, as the code cannot rely
- on the object to that the pointer points being placed at the
- end of the address space (and more pragmatically,
- TYPE_{MIN,MAX}_VALUE is not defined for pointers).
- 3) EXIT_MUST_BE_TAKEN is true, note it implies that the induction
- variable does not overflow. */
- if (!integer_zerop (mod) && !POINTER_TYPE_P (type) && !exit_must_be_taken)
+ then the computation of the final value does not overflow. This is
+ also obviously the case if the new final value is equal to the
+ current one. Finally, we postulate this for pointer type variables,
+ as the code cannot rely on the object to that the pointer points being
+ placed at the end of the address space (and more pragmatically,
+ TYPE_{MIN,MAX}_VALUE is not defined for pointers). */
+ if (integer_zerop (mod) || POINTER_TYPE_P (type))
+ fv_comp_no_overflow = true;
+ else if (!exit_must_be_taken)
+ fv_comp_no_overflow = false;
+ else
+ fv_comp_no_overflow =
+ (iv0->no_overflow && integer_nonzerop (iv0->step))
+ || (iv1->no_overflow && integer_nonzerop (iv1->step));
+
+ if (integer_nonzerop (iv0->step))
{
- if (integer_nonzerop (iv0->step))
+ /* The final value of the iv is iv1->base + MOD, assuming that this
+ computation does not overflow, and that
+ iv0->base <= iv1->base + MOD. */
+ if (!fv_comp_no_overflow)
{
- /* The final value of the iv is iv1->base + MOD, assuming
- that this computation does not overflow, and that
- iv0->base <= iv1->base + MOD. */
bound = fold_build2 (MINUS_EXPR, type1,
TYPE_MAX_VALUE (type1), tmod);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
+ if (integer_zerop (assumption))
+ goto end;
}
+ if (mpz_cmp (mmod, bnds->below) < 0)
+ noloop = boolean_false_node;
+ else if (POINTER_TYPE_P (type))
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ iv0->base,
+ fold_build_pointer_plus (iv1->base, tmod));
else
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ iv0->base,
+ fold_build2 (PLUS_EXPR, type1,
+ iv1->base, tmod));
+ }
+ else
+ {
+ /* The final value of the iv is iv0->base - MOD, assuming that this
+ computation does not overflow, and that
+ iv0->base - MOD <= iv1->base. */
+ if (!fv_comp_no_overflow)
{
- /* The final value of the iv is iv0->base - MOD, assuming
- that this computation does not overflow, and that
- iv0->base - MOD <= iv1->base. */
bound = fold_build2 (PLUS_EXPR, type1,
TYPE_MIN_VALUE (type1), tmod);
assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound);
+ if (integer_zerop (assumption))
+ goto end;
}
- if (integer_zerop (assumption))
- return false;
- else if (!integer_nonzerop (assumption))
- niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
- niter->assumptions, assumption);
+ if (mpz_cmp (mmod, bnds->below) < 0)
+ noloop = boolean_false_node;
+ else if (POINTER_TYPE_P (type))
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ fold_build_pointer_plus (iv0->base,
+ fold_build1 (NEGATE_EXPR,
+ type1, tmod)),
+ iv1->base);
+ else
+ noloop = fold_build2 (GT_EXPR, boolean_type_node,
+ fold_build2 (MINUS_EXPR, type1,
+ iv0->base, tmod),
+ iv1->base);
}
- /* Since we are transforming LT to NE and DELTA is constant, there
- is no need to compute may_be_zero because this loop must roll. */
-
+ if (!integer_nonzerop (assumption))
+ niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+ niter->assumptions,
+ assumption);
+ if (!integer_zerop (noloop))
+ niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
+ niter->may_be_zero,
+ noloop);
bounds_add (bnds, wi::to_widest (mod), type);
*delta = fold_build2 (PLUS_EXPR, niter_type, *delta, mod);
- return true;
+
+ ret = true;
+end:
+ mpz_clear (mmod);
+ return ret;
}
/* Add assertions to NITER that ensure that the control variable of the loop
@@ -1668,18 +1717,34 @@ number_of_iterations_cond (struct loop *loop,
exit_must_be_taken = true;
}
- /* We can handle the case when neither of the sides of the comparison is
- invariant, provided that the test is NE_EXPR. This rarely occurs in
- practice, but it is simple enough to manage. */
+ /* We can handle cases which neither of the sides of the comparison is
+ invariant:
+
+ {iv0.base, iv0.step} cmp_code {iv1.base, iv1.step}
+ as if:
+ {iv0.base, iv0.step - iv1.step} cmp_code {iv1.base, 0}
+
+ provided that either below condition is satisfied:
+
+ a) the test is NE_EXPR;
+ b) iv0.step - iv1.step is positive integer.
+
+ This rarely occurs in practice, but it is simple enough to manage. */
if (!integer_zerop (iv0->step) && !integer_zerop (iv1->step))
{
tree step_type = POINTER_TYPE_P (type) ? sizetype : type;
- if (code != NE_EXPR)
+ tree step = fold_binary_to_constant (MINUS_EXPR, step_type,
+ iv0->step, iv1->step);
+
+ /* No need to check sign of the new step since below code takes care
+ of this well. */
+ if (code != NE_EXPR && TREE_CODE (step) != INTEGER_CST)
return false;
- iv0->step = fold_binary_to_constant (MINUS_EXPR, step_type,
- iv0->step, iv1->step);
- iv0->no_overflow = false;
+ iv0->step = step;
+ if (!POINTER_TYPE_P (type))
+ iv0->no_overflow = false;
+
iv1->step = build_int_cst (step_type, 0);
iv1->no_overflow = true;
}
@@ -2362,9 +2427,9 @@ number_of_iterations_exit (struct loop *loop, edge exit,
return true;
if (warn)
- warning_at (gimple_location_safe (stmt),
- OPT_Wunsafe_loop_optimizations,
- "missed loop optimization, the loop counter may overflow");
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, gimple_location_safe (stmt),
+ "missed loop optimization: niters analysis ends up "
+ "with assumptions.\n");
return false;
}
@@ -3786,8 +3851,8 @@ maybe_lower_iteration_bound (struct loop *loop)
/* Records estimates on numbers of iterations of LOOP. If USE_UNDEFINED_P
is true also use estimates derived from undefined behavior. */
-static void
-estimate_numbers_of_iterations_loop (struct loop *loop)
+void
+estimate_numbers_of_iterations (struct loop *loop)
{
vec<edge> exits;
tree niter, type;
@@ -3815,8 +3880,7 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
recomputing iteration bounds later in the compilation process will just
introduce random roundoff errors. */
if (!loop->any_estimate
- && loop->header->count != 0
- && profile_status_for_fn (cfun) >= PROFILE_READ)
+ && loop->header->count > 0)
{
gcov_type nit = expected_loop_iterations_unbounded (loop);
bound = gcov_type_to_wide_int (nit);
@@ -3877,7 +3941,7 @@ estimated_loop_iterations (struct loop *loop, widest_int *nit)
/* When SCEV information is available, try to update loop iterations
estimate. Otherwise just return whatever we recorded earlier. */
if (scev_initialized_p ())
- estimate_numbers_of_iterations_loop (loop);
+ estimate_numbers_of_iterations (loop);
return (get_estimated_loop_iterations (loop, nit));
}
@@ -3913,7 +3977,7 @@ max_loop_iterations (struct loop *loop, widest_int *nit)
/* When SCEV information is available, try to update loop iterations
estimate. Otherwise just return whatever we recorded earlier. */
if (scev_initialized_p ())
- estimate_numbers_of_iterations_loop (loop);
+ estimate_numbers_of_iterations (loop);
return get_max_loop_iterations (loop, nit);
}
@@ -3948,7 +4012,7 @@ likely_max_loop_iterations (struct loop *loop, widest_int *nit)
/* When SCEV information is available, try to update loop iterations
estimate. Otherwise just return whatever we recorded earlier. */
if (scev_initialized_p ())
- estimate_numbers_of_iterations_loop (loop);
+ estimate_numbers_of_iterations (loop);
return get_likely_max_loop_iterations (loop, nit);
}
@@ -4052,7 +4116,7 @@ estimated_stmt_executions (struct loop *loop, widest_int *nit)
/* Records estimates on numbers of iterations of loops. */
void
-estimate_numbers_of_iterations (void)
+estimate_numbers_of_iterations (function *fn)
{
struct loop *loop;
@@ -4060,10 +4124,8 @@ estimate_numbers_of_iterations (void)
loop iteration estimates. */
fold_defer_overflow_warnings ();
- FOR_EACH_LOOP (loop, 0)
- {
- estimate_numbers_of_iterations_loop (loop);
- }
+ FOR_EACH_LOOP_FN (fn, loop, 0)
+ estimate_numbers_of_iterations (loop);
fold_undefer_and_ignore_overflow_warnings ();
}
@@ -4236,7 +4298,7 @@ loop_exits_before_overflow (tree base, tree step,
valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type, delta, step_abs);
- estimate_numbers_of_iterations_loop (loop);
+ estimate_numbers_of_iterations (loop);
if (max_loop_iterations (loop, &niter)
&& wi::fits_to_tree_p (niter, TREE_TYPE (valid_niter))
@@ -4503,7 +4565,7 @@ scev_probably_wraps_p (tree var, tree base, tree step,
/* Frees the information on upper bounds on numbers of iterations of LOOP. */
void
-free_numbers_of_iterations_estimates_loop (struct loop *loop)
+free_numbers_of_iterations_estimates (struct loop *loop)
{
struct control_iv *civ;
struct nb_iter_bound *bound;
@@ -4535,9 +4597,7 @@ free_numbers_of_iterations_estimates (function *fn)
struct loop *loop;
FOR_EACH_LOOP_FN (fn, loop, 0)
- {
- free_numbers_of_iterations_estimates_loop (loop);
- }
+ free_numbers_of_iterations_estimates (loop);
}
/* Substitute value VAL for ssa name NAME inside expressions held