tree-ssa-loop-niter.c (idx_infer_loop_bounds): Add and use argument "reliable".
* tree-ssa-loop-niter.c (idx_infer_loop_bounds): Add and use argument "reliable". (infer_loop_bounds_from_ref, infer_loop_bounds_from_array): Add argument "reliable". Propagate it through calls. (infer_loop_bounds_from_undefined): Derive number of iterations estimates from references in blocks that do not dominate loop latch. (gcov_type_to_double_int): New function. (estimate_numbers_of_iterations_loop): Use gcov_type_to_double_int and expected_loop_iterations_unbounded. * cfgloopanal.c (expected_loop_iterations_unbounded): New function. (expected_loop_iterations): Use expected_loop_iterations_unbounded. * tree-data-ref.c (estimated_loop_iterations): Export. (get_references_in_stmt): Fix -- do not return addresses of local objects. * cfgloop.h (expected_loop_iterations_unbounded, estimated_loop_iterations): Declare. From-SVN: r123630
This commit is contained in:
parent
64199a9eed
commit
ac84e05eb6
@ -1,3 +1,22 @@
|
||||
2007-04-06 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
* tree-ssa-loop-niter.c (idx_infer_loop_bounds): Add and use
|
||||
argument "reliable".
|
||||
(infer_loop_bounds_from_ref, infer_loop_bounds_from_array):
|
||||
Add argument "reliable". Propagate it through calls.
|
||||
(infer_loop_bounds_from_undefined): Derive number of iterations
|
||||
estimates from references in blocks that do not dominate loop latch.
|
||||
(gcov_type_to_double_int): New function.
|
||||
(estimate_numbers_of_iterations_loop): Use gcov_type_to_double_int
|
||||
and expected_loop_iterations_unbounded.
|
||||
* cfgloopanal.c (expected_loop_iterations_unbounded): New function.
|
||||
(expected_loop_iterations): Use expected_loop_iterations_unbounded.
|
||||
* tree-data-ref.c (estimated_loop_iterations): Export.
|
||||
(get_references_in_stmt): Fix -- do not return addresses of local
|
||||
objects.
|
||||
* cfgloop.h (expected_loop_iterations_unbounded,
|
||||
estimated_loop_iterations): Declare.
|
||||
|
||||
2007-04-06 Andreas Tobler <a.tobler@schweiz.org>
|
||||
|
||||
* tree-sra.c (sra_build_elt_assignment): Initialize min/maxshift.
|
||||
|
@ -262,11 +262,13 @@ extern void verify_loop_structure (void);
|
||||
|
||||
/* Loop analysis. */
|
||||
extern bool just_once_each_iteration_p (const struct loop *, basic_block);
|
||||
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 *);
|
||||
HOST_WIDE_INT estimated_loop_iterations_int (struct loop *, bool);
|
||||
bool estimated_loop_iterations (struct loop *, bool, double_int *);
|
||||
|
||||
/* Loop manipulation. */
|
||||
extern bool can_duplicate_loop_p (struct loop *loop);
|
||||
|
@ -423,11 +423,12 @@ average_num_loop_insns (struct loop *loop)
|
||||
return ninsns;
|
||||
}
|
||||
|
||||
/* Returns expected number of LOOP iterations.
|
||||
Compute upper bound on number of iterations in case they do not fit integer
|
||||
to help loop peeling heuristics. Use exact counts if at all possible. */
|
||||
unsigned
|
||||
expected_loop_iterations (const struct loop *loop)
|
||||
/* Returns expected number of iterations of LOOP, according to
|
||||
measured or guessed profile. No bounding is done on the
|
||||
value. */
|
||||
|
||||
gcov_type
|
||||
expected_loop_iterations_unbounded (const struct loop *loop)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
@ -450,8 +451,7 @@ expected_loop_iterations (const struct loop *loop)
|
||||
else
|
||||
expected = (count_latch + count_in - 1) / count_in;
|
||||
|
||||
/* Avoid overflows. */
|
||||
return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected);
|
||||
return expected;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -473,6 +473,16 @@ expected_loop_iterations (const struct loop *loop)
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns expected number of LOOP iterations. The returned value is bounded
|
||||
by REG_BR_PROB_BASE. */
|
||||
|
||||
unsigned
|
||||
expected_loop_iterations (const struct loop *loop)
|
||||
{
|
||||
gcov_type expected = expected_loop_iterations_unbounded (loop);
|
||||
return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected);
|
||||
}
|
||||
|
||||
/* Returns the maximum level of nesting of subloops of LOOP. */
|
||||
|
||||
unsigned
|
||||
|
@ -2553,7 +2553,7 @@ analyze_ziv_subscript (tree chrec_a,
|
||||
large as the number of iterations. If we have no reliable estimate,
|
||||
the function returns false, otherwise returns true. */
|
||||
|
||||
static bool
|
||||
bool
|
||||
estimated_loop_iterations (struct loop *loop, bool conservative,
|
||||
double_int *nit)
|
||||
{
|
||||
@ -4873,8 +4873,7 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references)
|
||||
{
|
||||
bool clobbers_memory = false;
|
||||
data_ref_loc *ref;
|
||||
tree *op0, *op1, arg, call;
|
||||
call_expr_arg_iterator iter;
|
||||
tree *op0, *op1, call;
|
||||
|
||||
*references = NULL;
|
||||
|
||||
@ -4915,9 +4914,12 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references)
|
||||
|
||||
if (call)
|
||||
{
|
||||
FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
|
||||
unsigned i, n = call_expr_nargs (call);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
op0 = &arg;
|
||||
op0 = &CALL_EXPR_ARG (call, i);
|
||||
|
||||
if (DECL_P (*op0)
|
||||
|| REFERENCE_CLASS_P (*op0))
|
||||
{
|
||||
|
@ -2581,12 +2581,15 @@ array_at_struct_end_p (tree ref)
|
||||
}
|
||||
|
||||
/* Determine information about number of iterations a LOOP from the index
|
||||
IDX of a data reference accessed in STMT. Callback for for_each_index. */
|
||||
IDX of a data reference accessed in STMT. RELIABLE is true if STMT is
|
||||
guaranteed to be executed in every iteration of LOOP. Callback for
|
||||
for_each_index. */
|
||||
|
||||
struct ilb_data
|
||||
{
|
||||
struct loop *loop;
|
||||
tree stmt;
|
||||
bool reliable;
|
||||
};
|
||||
|
||||
static bool
|
||||
@ -2595,7 +2598,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
|
||||
struct ilb_data *data = dta;
|
||||
tree ev, init, step;
|
||||
tree low, high, type, next;
|
||||
bool sign, upper = true;
|
||||
bool sign, upper = data->reliable, at_end = false;
|
||||
struct loop *loop = data->loop;
|
||||
|
||||
if (TREE_CODE (base) != ARRAY_REF)
|
||||
@ -2605,7 +2608,10 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
|
||||
do not really extend over their declared size. However, for arrays of
|
||||
size greater than one, this is unlikely to be intended. */
|
||||
if (array_at_struct_end_p (base))
|
||||
upper = false;
|
||||
{
|
||||
at_end = true;
|
||||
upper = false;
|
||||
}
|
||||
|
||||
ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, *idx));
|
||||
init = initial_condition (ev);
|
||||
@ -2633,7 +2639,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
|
||||
|
||||
/* The array of length 1 at the end of a structure most likely extends
|
||||
beyond its bounds. */
|
||||
if (!upper
|
||||
if (at_end
|
||||
&& operand_equal_p (low, high, 0))
|
||||
return true;
|
||||
|
||||
@ -2665,23 +2671,27 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
|
||||
}
|
||||
|
||||
/* Determine information about number of iterations a LOOP from the bounds
|
||||
of arrays in the data reference REF accessed in STMT. */
|
||||
of arrays in the data reference REF accessed in STMT. RELIABLE is true if
|
||||
STMT is guaranteed to be executed in every iteration of LOOP.*/
|
||||
|
||||
static void
|
||||
infer_loop_bounds_from_ref (struct loop *loop, tree stmt, tree ref)
|
||||
infer_loop_bounds_from_ref (struct loop *loop, tree stmt, tree ref,
|
||||
bool reliable)
|
||||
{
|
||||
struct ilb_data data;
|
||||
|
||||
data.loop = loop;
|
||||
data.stmt = stmt;
|
||||
data.reliable = reliable;
|
||||
for_each_index (&ref, idx_infer_loop_bounds, &data);
|
||||
}
|
||||
|
||||
/* Determine information about number of iterations of a LOOP from the way
|
||||
arrays are used in STMT. */
|
||||
arrays are used in STMT. RELIABLE is true if STMT is guaranteed to be
|
||||
executed in every iteration of LOOP. */
|
||||
|
||||
static void
|
||||
infer_loop_bounds_from_array (struct loop *loop, tree stmt)
|
||||
infer_loop_bounds_from_array (struct loop *loop, tree stmt, bool reliable)
|
||||
{
|
||||
tree call;
|
||||
|
||||
@ -2693,10 +2703,10 @@ infer_loop_bounds_from_array (struct loop *loop, tree stmt)
|
||||
/* For each memory access, analyze its access function
|
||||
and record a bound on the loop iteration domain. */
|
||||
if (REFERENCE_CLASS_P (op0))
|
||||
infer_loop_bounds_from_ref (loop, stmt, op0);
|
||||
infer_loop_bounds_from_ref (loop, stmt, op0, reliable);
|
||||
|
||||
if (REFERENCE_CLASS_P (op1))
|
||||
infer_loop_bounds_from_ref (loop, stmt, op1);
|
||||
infer_loop_bounds_from_ref (loop, stmt, op1, reliable);
|
||||
}
|
||||
|
||||
|
||||
@ -2708,7 +2718,7 @@ infer_loop_bounds_from_array (struct loop *loop, tree stmt)
|
||||
|
||||
FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
|
||||
if (REFERENCE_CLASS_P (arg))
|
||||
infer_loop_bounds_from_ref (loop, stmt, arg);
|
||||
infer_loop_bounds_from_ref (loop, stmt, arg, reliable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2768,6 +2778,7 @@ infer_loop_bounds_from_undefined (struct loop *loop)
|
||||
basic_block *bbs;
|
||||
block_stmt_iterator bsi;
|
||||
basic_block bb;
|
||||
bool reliable;
|
||||
|
||||
bbs = get_loop_body (loop);
|
||||
|
||||
@ -2776,16 +2787,18 @@ infer_loop_bounds_from_undefined (struct loop *loop)
|
||||
bb = bbs[i];
|
||||
|
||||
/* If BB is not executed in each iteration of the loop, we cannot
|
||||
use it to infer any information about # of iterations of the loop. */
|
||||
if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
|
||||
continue;
|
||||
use the operations in it to infer reliable upper bound on the
|
||||
# of iterations of the loop. However, we can use it as a guess. */
|
||||
reliable = dominated_by_p (CDI_DOMINATORS, loop->latch, bb);
|
||||
|
||||
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
|
||||
{
|
||||
tree stmt = bsi_stmt (bsi);
|
||||
|
||||
infer_loop_bounds_from_array (loop, stmt);
|
||||
infer_loop_bounds_from_signedness (loop, stmt);
|
||||
infer_loop_bounds_from_array (loop, stmt, reliable);
|
||||
|
||||
if (reliable)
|
||||
infer_loop_bounds_from_signedness (loop, stmt);
|
||||
}
|
||||
|
||||
}
|
||||
@ -2793,6 +2806,23 @@ infer_loop_bounds_from_undefined (struct loop *loop)
|
||||
free (bbs);
|
||||
}
|
||||
|
||||
/* Converts VAL to double_int. */
|
||||
|
||||
static double_int
|
||||
gcov_type_to_double_int (gcov_type val)
|
||||
{
|
||||
double_int ret;
|
||||
|
||||
ret.low = (unsigned HOST_WIDE_INT) val;
|
||||
/* If HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_WIDEST_INT, avoid shifting by
|
||||
the size of type. */
|
||||
val >>= HOST_BITS_PER_WIDE_INT - 1;
|
||||
val >>= 1;
|
||||
ret.high = (unsigned HOST_WIDE_INT) val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Records estimates on numbers of iterations of LOOP. */
|
||||
|
||||
void
|
||||
@ -2836,7 +2866,8 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
|
||||
iterations. */
|
||||
if (loop->header->count != 0)
|
||||
{
|
||||
bound = uhwi_to_double_int (expected_loop_iterations (loop) + 1);
|
||||
gcov_type nit = expected_loop_iterations_unbounded (loop) + 1;
|
||||
bound = gcov_type_to_double_int (nit);
|
||||
record_niter_bound (loop, bound, true, false);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user