tree-vrp.c (adjust_range_with_scev): Use number of iteration estimate.

2010-09-01  Richard Guenther  <rguenther@suse.de>

	* tree-vrp.c (adjust_range_with_scev): Use number of iteration
	estimate.
	(vrp_visit_phi_node): Delay using SCEV till we balloon the
	range.
	(execute_vrp): Compute number of iteration estimates.
	* cfgloop.h (estimate_numbers_of_iterations_loop): Adjust prototype.
	* tree-flow.h (estimate_numbers_of_iterations): Likewise.
	* tree-data-ref.c (estimated_loop_iterations): Adjust.
	* tree-ssa-loop-niter.c (estimate_numbers_of_iterations_loop):
	Infer loop bounds from undefined behavior based on a new
	parameter.
	(estimate_numbers_of_iterations): Likewise.
	(scev_probably_wraps_p): Adjust.
	* tree-ssa-loop.c (tree_ssa_loop_bounds): Likewise.

	* gcc.dg/vect/vect-outer-fir.c: Adjust.
	* gcc.dg/tree-ssa/vrp54.c: New testcase.
	* gcc.c-torture/execute/20100827-1.c: Likewise.

From-SVN: r163724
This commit is contained in:
Richard Guenther 2010-09-01 11:39:55 +00:00 committed by Richard Biener
parent eacbdaaac1
commit e34882831e
11 changed files with 199 additions and 96 deletions

View File

@ -1,3 +1,20 @@
2010-09-01 Richard Guenther <rguenther@suse.de>
* tree-vrp.c (adjust_range_with_scev): Use number of iteration
estimate.
(vrp_visit_phi_node): Delay using SCEV till we balloon the
range.
(execute_vrp): Compute number of iteration estimates.
* cfgloop.h (estimate_numbers_of_iterations_loop): Adjust prototype.
* tree-flow.h (estimate_numbers_of_iterations): Likewise.
* tree-data-ref.c (estimated_loop_iterations): Adjust.
* tree-ssa-loop-niter.c (estimate_numbers_of_iterations_loop):
Infer loop bounds from undefined behavior based on a new
parameter.
(estimate_numbers_of_iterations): Likewise.
(scev_probably_wraps_p): Adjust.
* tree-ssa-loop.c (tree_ssa_loop_bounds): Likewise.
2010-09-01 Nick Clifton <nickc@redhat.com>
* config/stormy16/stormy16.c: Use REG_P, MEM_P and CONST_INT_P

View File

@ -276,7 +276,7 @@ gcov_type expected_loop_iterations_unbounded (const struct loop *);
extern unsigned expected_loop_iterations (const struct loop *);
extern rtx doloop_condition_get (rtx);
void estimate_numbers_of_iterations_loop (struct loop *);
void estimate_numbers_of_iterations_loop (struct loop *, bool);
HOST_WIDE_INT estimated_loop_iterations_int (struct loop *, bool);
bool estimated_loop_iterations (struct loop *, bool, double_int *);

View File

@ -1,3 +1,9 @@
2010-09-01 Richard Guenther <rguenther@suse.de>
* gcc.dg/vect/vect-outer-fir.c: Adjust.
* gcc.dg/tree-ssa/vrp54.c: New testcase.
* gcc.c-torture/execute/20100827-1.c: Likewise.
2010-09-01 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
* gfortran.dg/execute_command_line_1.f90: New test.

View File

@ -0,0 +1,23 @@
extern void abort (void);
int __attribute__((noinline,noclone))
foo (char *p)
{
int h = 0;
do
{
if (*p == '\0')
break;
++h;
if (p == 0)
abort ();
++p;
}
while (1);
return h;
}
int main()
{
if (foo("a") != 1)
abort ();
return 0;
}

View File

@ -0,0 +1,34 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1" } */
extern void link_error (void);
void foo (void)
{
int j = 256;
do
{
if (j < 0 || j > 256)
link_error ();
j--;
}
while (j >= 0);
if (j != -1)
link_error ();
}
extern void link_error (void);
void bar (void)
{
int j = 0;
do
{
if (j < 0 || j > 256)
link_error ();
j++;
}
while (j <= 256);
if (j != 257)
link_error ();
}
/* { dg-final { scan-tree-dump-not "link_error" "vrp1" } } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */

View File

@ -11,10 +11,6 @@ float out[N];
float fir_out[N];
/* Should be vectorized. Fixed misaligment in the inner-loop. */
/* Currently not vectorized because we get too many BBs in the inner-loop,
because the compiler doesn't realize that the inner-loop executes at
least once (cause k<4), and so there's no need to create a guard code
to skip the inner-loop in case it doesn't execute. */
__attribute__ ((noinline))
void foo (){
int i,j,k;
@ -74,6 +70,5 @@ int main (void)
return 0;
}
/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 2 "vect" { xfail *-*-* } } } */
/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail vect_no_align } } } */
/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 2 "vect" { xfail vect_no_align } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */

View File

@ -1716,7 +1716,7 @@ bool
estimated_loop_iterations (struct loop *loop, bool conservative,
double_int *nit)
{
estimate_numbers_of_iterations_loop (loop);
estimate_numbers_of_iterations_loop (loop, true);
if (conservative)
{
if (!loop->any_upper_bound)

View File

@ -684,7 +684,7 @@ bool number_of_iterations_exit (struct loop *, edge,
tree find_loop_niter (struct loop *, edge *);
tree loop_niter_by_eval (struct loop *, edge);
tree find_loop_niter_by_eval (struct loop *, edge *);
void estimate_numbers_of_iterations (void);
void estimate_numbers_of_iterations (bool);
bool array_at_struct_end_p (tree);
bool scev_probably_wraps_p (tree, tree, gimple, struct loop *, bool);
bool convert_affine_scev (struct loop *, tree, tree *, tree *, gimple, bool);

View File

@ -2933,10 +2933,11 @@ gcov_type_to_double_int (gcov_type val)
return ret;
}
/* Records estimates on numbers of iterations of LOOP. */
/* Records estimates on numbers of iterations of LOOP. If USE_UNDEFINED_P
is true also use estimates derived from undefined behavior. */
void
estimate_numbers_of_iterations_loop (struct loop *loop)
estimate_numbers_of_iterations_loop (struct loop *loop, bool use_undefined_p)
{
VEC (edge, heap) *exits;
tree niter, type;
@ -2970,7 +2971,8 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
}
VEC_free (edge, heap, exits);
infer_loop_bounds_from_undefined (loop);
if (use_undefined_p)
infer_loop_bounds_from_undefined (loop);
/* If we have a measured profile, use it to estimate the number of
iterations. */
@ -2993,7 +2995,7 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
/* Records estimates on numbers of iterations of loops. */
void
estimate_numbers_of_iterations (void)
estimate_numbers_of_iterations (bool use_undefined_p)
{
loop_iterator li;
struct loop *loop;
@ -3004,7 +3006,7 @@ estimate_numbers_of_iterations (void)
FOR_EACH_LOOP (li, loop, 0)
{
estimate_numbers_of_iterations_loop (loop);
estimate_numbers_of_iterations_loop (loop, use_undefined_p);
}
fold_undefer_and_ignore_overflow_warnings ();
@ -3200,7 +3202,7 @@ scev_probably_wraps_p (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 (loop, true);
for (bound = loop->bounds; bound; bound = bound->next)
{
if (n_of_executions_at_most (at_stmt, bound, valid_niter))

View File

@ -458,7 +458,7 @@ tree_ssa_loop_bounds (void)
if (number_of_loops () <= 1)
return 0;
estimate_numbers_of_iterations ();
estimate_numbers_of_iterations (true);
scev_reset ();
return 0;
}

View File

@ -3382,6 +3382,38 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
else
tmax = TYPE_MAX_VALUE (type);
/* Try to use estimated number of iterations for the loop to constrain the
final value in the evolution.
We are interested in the number of executions of the latch, while
nb_iterations_upper_bound includes the last execution of the exit test. */
if (TREE_CODE (step) == INTEGER_CST
&& loop->any_upper_bound
&& !double_int_zero_p (loop->nb_iterations_upper_bound)
&& is_gimple_val (init)
&& (TREE_CODE (init) != SSA_NAME
|| get_value_range (init)->type == VR_RANGE))
{
value_range_t maxvr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
double_int dtmp;
dtmp = double_int_mul (tree_to_double_int (step),
double_int_sub (loop->nb_iterations_upper_bound,
double_int_one));
tem = double_int_to_tree (TREE_TYPE (init), dtmp);
/* If the multiplication overflowed we can't do a meaningful
adjustment. */
if (double_int_equal_p (dtmp, tree_to_double_int (tem)))
{
extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
TREE_TYPE (init), init, tem);
/* Likewise if the addition did. */
if (maxvr.type == VR_RANGE)
{
tmin = maxvr.min;
tmax = maxvr.max;
}
}
}
if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED)
{
min = tmin;
@ -3414,40 +3446,35 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
/* INIT is the maximum value. If INIT is lower than VR->MAX
but no smaller than VR->MIN, set VR->MAX to INIT. */
if (compare_values (init, max) == -1)
{
max = init;
/* If we just created an invalid range with the minimum
greater than the maximum, we fail conservatively.
This should happen only in unreachable
parts of code, or for invalid programs. */
if (compare_values (min, max) == 1)
return;
}
max = init;
/* According to the loop information, the variable does not
overflow. If we think it does, probably because of an
overflow due to arithmetic on a different INF value,
reset now. */
if (is_negative_overflow_infinity (min))
if (is_negative_overflow_infinity (min)
|| compare_values (min, tmin) == -1)
min = tmin;
}
else
{
/* If INIT is bigger than VR->MIN, set VR->MIN to INIT. */
if (compare_values (init, min) == 1)
{
min = init;
min = init;
/* Again, avoid creating invalid range by failing. */
if (compare_values (min, max) == 1)
return;
}
if (is_positive_overflow_infinity (max))
if (is_positive_overflow_infinity (max)
|| compare_values (tmax, max) == -1)
max = tmax;
}
/* If we just created an invalid range with the minimum
greater than the maximum, we fail conservatively.
This should happen only in unreachable
parts of code, or for invalid programs. */
if (compare_values (min, max) == 1)
return;
set_value_range (vr, VR_RANGE, min, max, vr->equiv);
}
}
@ -6509,8 +6536,6 @@ vrp_visit_phi_node (gimple phi)
int edges, old_edges;
struct loop *l;
copy_value_range (&vr_result, lhs_vr);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "\nVisiting PHI node: ");
@ -6571,13 +6596,6 @@ vrp_visit_phi_node (gimple phi)
}
}
/* If this is a loop PHI node SCEV may known more about its
value-range. */
if (current_loops
&& (l = loop_containing_stmt (phi))
&& l->header == gimple_bb (phi))
adjust_range_with_scev (&vr_result, l, phi, lhs);
if (vr_result.type == VR_VARYING)
goto varying;
@ -6589,61 +6607,63 @@ vrp_visit_phi_node (gimple phi)
previous one. We don't do this if we have seen a new executable
edge; this helps us avoid an overflow infinity for conditionals
which are not in a loop. */
if (lhs_vr->type == VR_RANGE && vr_result.type == VR_RANGE
&& edges <= old_edges)
if (edges > 0
&& edges == old_edges)
{
if (!POINTER_TYPE_P (TREE_TYPE (lhs)))
int cmp_min = compare_values (lhs_vr->min, vr_result.min);
int cmp_max = compare_values (lhs_vr->max, vr_result.max);
/* For non VR_RANGE or for pointers fall back to varying if
the range changed. */
if ((lhs_vr->type != VR_RANGE || vr_result.type != VR_RANGE
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
&& (cmp_min != 0 || cmp_max != 0))
goto varying;
/* If the new minimum is smaller or larger than the previous
one, go all the way to -INF. In the first case, to avoid
iterating millions of times to reach -INF, and in the
other case to avoid infinite bouncing between different
minimums. */
if (cmp_min > 0 || cmp_min < 0)
{
int cmp_min = compare_values (lhs_vr->min, vr_result.min);
int cmp_max = compare_values (lhs_vr->max, vr_result.max);
/* If the new minimum is smaller or larger than the previous
one, go all the way to -INF. In the first case, to avoid
iterating millions of times to reach -INF, and in the
other case to avoid infinite bouncing between different
minimums. */
if (cmp_min > 0 || cmp_min < 0)
{
/* If we will end up with a (-INF, +INF) range, set it to
VARYING. Same if the previous max value was invalid for
the type and we'd end up with vr_result.min > vr_result.max. */
if (vrp_val_is_max (vr_result.max)
|| compare_values (TYPE_MIN_VALUE (TREE_TYPE (vr_result.min)),
vr_result.max) > 0)
goto varying;
if (!needs_overflow_infinity (TREE_TYPE (vr_result.min))
|| !vrp_var_may_overflow (lhs, phi))
vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min));
else if (supports_overflow_infinity (TREE_TYPE (vr_result.min)))
vr_result.min =
negative_overflow_infinity (TREE_TYPE (vr_result.min));
else
goto varying;
}
/* Similarly, if the new maximum is smaller or larger than
the previous one, go all the way to +INF. */
if (cmp_max < 0 || cmp_max > 0)
{
/* If we will end up with a (-INF, +INF) range, set it to
VARYING. Same if the previous min value was invalid for
the type and we'd end up with vr_result.max < vr_result.min. */
if (vrp_val_is_min (vr_result.min)
|| compare_values (TYPE_MAX_VALUE (TREE_TYPE (vr_result.max)),
vr_result.min) < 0)
goto varying;
if (!needs_overflow_infinity (TREE_TYPE (vr_result.max))
|| !vrp_var_may_overflow (lhs, phi))
vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max));
else if (supports_overflow_infinity (TREE_TYPE (vr_result.max)))
vr_result.max =
positive_overflow_infinity (TREE_TYPE (vr_result.max));
else
goto varying;
}
if (!needs_overflow_infinity (TREE_TYPE (vr_result.min))
|| !vrp_var_may_overflow (lhs, phi))
vr_result.min = TYPE_MIN_VALUE (TREE_TYPE (vr_result.min));
else if (supports_overflow_infinity (TREE_TYPE (vr_result.min)))
vr_result.min =
negative_overflow_infinity (TREE_TYPE (vr_result.min));
}
/* Similarly, if the new maximum is smaller or larger than
the previous one, go all the way to +INF. */
if (cmp_max < 0 || cmp_max > 0)
{
if (!needs_overflow_infinity (TREE_TYPE (vr_result.max))
|| !vrp_var_may_overflow (lhs, phi))
vr_result.max = TYPE_MAX_VALUE (TREE_TYPE (vr_result.max));
else if (supports_overflow_infinity (TREE_TYPE (vr_result.max)))
vr_result.max =
positive_overflow_infinity (TREE_TYPE (vr_result.max));
}
/* If we dropped either bound to +-INF then if this is a loop
PHI node SCEV may known more about its value-range. */
if ((cmp_min > 0 || cmp_min < 0
|| cmp_max < 0 || cmp_max > 0)
&& current_loops
&& (l = loop_containing_stmt (phi))
&& l->header == gimple_bb (phi))
adjust_range_with_scev (&vr_result, l, phi, lhs);
/* If we will end up with a (-INF, +INF) range, set it to
VARYING. Same if the previous max value was invalid for
the type and we end up with vr_result.min > vr_result.max. */
if ((vrp_val_is_max (vr_result.max)
&& vrp_val_is_min (vr_result.min))
|| compare_values (vr_result.min,
vr_result.max) > 0)
goto varying;
}
/* If the new range is different than the previous value, keep
@ -7650,6 +7670,12 @@ execute_vrp (void)
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
scev_initialize ();
/* Estimate number of iterations - but do not use undefined behavior
for this. We can't do this lazily as other functions may compute
this using undefined behavior. */
free_numbers_of_iterations_estimates ();
estimate_numbers_of_iterations (false);
insert_range_assertions ();
to_remove_edges = VEC_alloc (edge, heap, 10);