Commit f017bf5e by Zdenek Dvorak Committed by Zdenek Dvorak

tree-scalar-evolution.c (analyze_scalar_evolution_in_loop): Extend comments.

	* tree-scalar-evolution.c (analyze_scalar_evolution_in_loop):
	Extend comments.
	(simple_iv):  Take loop as an argument instead of statement.
	* tree-scalar-evolution.h (simple_iv): Declaration changed.
	* tree-ssa-loop-niter.c (number_of_iterations_exit): Update calls
	to simple_iv.
	* tree-ssa-loop-ivopts.c (determine_biv_step, find_givs_in_stmt_scev):
	Ditto.
	* tree-parloops.c (loop_parallel_p, canonicalize_loop_ivs): Ditto.
	* matrix-reorg.c (analyze_transpose): Ditto.
	* tree-data-ref.c (dr_analyze_innermost): Ditto.
	* tree-vect-analyze.c (vect_analyze_data_refs): Ditto.
	* tree-predcom.c (ref_at_iteration): Ditto.
	* tree-ssa-loop-prefetch.c (idx_analyze_ref): Ditto.

From-SVN: r144615
parent 79c09787
2009-03-04 Zdenek Dvorak <ook@ucw.cz>
* tree-scalar-evolution.c (analyze_scalar_evolution_in_loop):
Extend comments.
(simple_iv): Take loop as an argument instead of statement.
* tree-scalar-evolution.h (simple_iv): Declaration changed.
* tree-ssa-loop-niter.c (number_of_iterations_exit): Update calls
to simple_iv.
* tree-ssa-loop-ivopts.c (determine_biv_step, find_givs_in_stmt_scev):
Ditto.
* tree-parloops.c (loop_parallel_p, canonicalize_loop_ivs): Ditto.
* matrix-reorg.c (analyze_transpose): Ditto.
* tree-data-ref.c (dr_analyze_innermost): Ditto.
* tree-vect-analyze.c (vect_analyze_data_refs): Ditto.
* tree-predcom.c (ref_at_iteration): Ditto.
* tree-ssa-loop-prefetch.c (idx_analyze_ref): Ditto.
2009-03-04 Richard Guenther <rguenther@suse.de> 2009-03-04 Richard Guenther <rguenther@suse.de>
PR tree-optimization/39358 PR tree-optimization/39358
......
...@@ -930,7 +930,7 @@ analyze_transpose (void **slot, void *data ATTRIBUTE_UNUSED) ...@@ -930,7 +930,7 @@ analyze_transpose (void **slot, void *data ATTRIBUTE_UNUSED)
free (acc_info); free (acc_info);
continue; continue;
} }
if (simple_iv (loop, acc_info->stmt, acc_info->offset, &iv, true)) if (simple_iv (loop, loop, acc_info->offset, &iv, true))
{ {
if (iv.step != NULL) if (iv.step != NULL)
{ {
......
...@@ -698,7 +698,7 @@ dr_analyze_innermost (struct data_reference *dr) ...@@ -698,7 +698,7 @@ dr_analyze_innermost (struct data_reference *dr)
} }
base = build_fold_addr_expr (base); base = build_fold_addr_expr (base);
if (!simple_iv (loop, stmt, base, &base_iv, false)) if (!simple_iv (loop, loop_containing_stmt (stmt), base, &base_iv, false))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "failed: evolution of base is not affine.\n"); fprintf (dump_file, "failed: evolution of base is not affine.\n");
...@@ -709,7 +709,8 @@ dr_analyze_innermost (struct data_reference *dr) ...@@ -709,7 +709,8 @@ dr_analyze_innermost (struct data_reference *dr)
offset_iv.base = ssize_int (0); offset_iv.base = ssize_int (0);
offset_iv.step = ssize_int (0); offset_iv.step = ssize_int (0);
} }
else if (!simple_iv (loop, stmt, poffset, &offset_iv, false)) else if (!simple_iv (loop, loop_containing_stmt (stmt),
poffset, &offset_iv, false))
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "failed: evolution of offset is not affine.\n"); fprintf (dump_file, "failed: evolution of offset is not affine.\n");
......
...@@ -385,7 +385,7 @@ loop_parallel_p (struct loop *loop, htab_t reduction_list, ...@@ -385,7 +385,7 @@ loop_parallel_p (struct loop *loop, htab_t reduction_list,
tree def = PHI_RESULT (phi); tree def = PHI_RESULT (phi);
affine_iv iv; affine_iv iv;
if (is_gimple_reg (def) && !simple_iv (loop, phi, def, &iv, true)) if (is_gimple_reg (def) && !simple_iv (loop, loop, def, &iv, true))
{ {
struct reduction_info *red; struct reduction_info *red;
...@@ -1380,7 +1380,7 @@ canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree *nit) ...@@ -1380,7 +1380,7 @@ canonicalize_loop_ivs (struct loop *loop, htab_t reduction_list, tree *nit)
continue; continue;
} }
ok = simple_iv (loop, phi, res, &iv, true); ok = simple_iv (loop, loop, res, &iv, true);
if (reduction_list) if (reduction_list)
red = reduction_phi (reduction_list, phi); red = reduction_phi (reduction_list, phi);
......
...@@ -1374,7 +1374,7 @@ ref_at_iteration (struct loop *loop, tree ref, int iter) ...@@ -1374,7 +1374,7 @@ ref_at_iteration (struct loop *loop, tree ref, int iter)
else else
return NULL_TREE; return NULL_TREE;
ok = simple_iv (loop, first_stmt (loop->header), idx, &iv, true); ok = simple_iv (loop, loop, idx, &iv, true);
if (!ok) if (!ok)
return NULL_TREE; return NULL_TREE;
iv.base = expand_simple_operations (iv.base); iv.base = expand_simple_operations (iv.base);
......
...@@ -1915,12 +1915,54 @@ analyze_scalar_evolution (struct loop *loop, tree var) ...@@ -1915,12 +1915,54 @@ analyze_scalar_evolution (struct loop *loop, tree var)
} }
/* Analyze scalar evolution of use of VERSION in USE_LOOP with respect to /* Analyze scalar evolution of use of VERSION in USE_LOOP with respect to
WRTO_LOOP (which should be a superloop of both USE_LOOP and definition WRTO_LOOP (which should be a superloop of USE_LOOP)
of VERSION).
FOLDED_CASTS is set to true if resolve_mixers used FOLDED_CASTS is set to true if resolve_mixers used
chrec_convert_aggressive (TODO -- not really, we are way too conservative chrec_convert_aggressive (TODO -- not really, we are way too conservative
at the moment in order to keep things simple). */ at the moment in order to keep things simple).
To illustrate the meaning of USE_LOOP and WRTO_LOOP, consider the following
example:
for (i = 0; i < 100; i++) -- loop 1
{
for (j = 0; j < 100; j++) -- loop 2
{
k1 = i;
k2 = j;
use2 (k1, k2);
for (t = 0; t < 100; t++) -- loop 3
use3 (k1, k2);
}
use1 (k1, k2);
}
Both k1 and k2 are invariants in loop3, thus
analyze_scalar_evolution_in_loop (loop3, loop3, k1) = k1
analyze_scalar_evolution_in_loop (loop3, loop3, k2) = k2
As they are invariant, it does not matter whether we consider their
usage in loop 3 or loop 2, hence
analyze_scalar_evolution_in_loop (loop2, loop3, k1) =
analyze_scalar_evolution_in_loop (loop2, loop2, k1) = i
analyze_scalar_evolution_in_loop (loop2, loop3, k2) =
analyze_scalar_evolution_in_loop (loop2, loop2, k2) = [0,+,1]_2
Similarly for their evolutions with respect to loop 1. The values of K2
in the use in loop 2 vary independently on loop 1, thus we cannot express
the evolution with respect to loop 1:
analyze_scalar_evolution_in_loop (loop1, loop3, k1) =
analyze_scalar_evolution_in_loop (loop1, loop2, k1) = [0,+,1]_1
analyze_scalar_evolution_in_loop (loop1, loop3, k2) =
analyze_scalar_evolution_in_loop (loop1, loop2, k2) = dont_know
The value of k2 in the use in loop 1 is known, though:
analyze_scalar_evolution_in_loop (loop1, loop1, k1) = [0,+,1]_1
analyze_scalar_evolution_in_loop (loop1, loop1, k2) = 100
*/
static tree static tree
analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop, analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop,
...@@ -1929,6 +1971,25 @@ analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop, ...@@ -1929,6 +1971,25 @@ analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop,
bool val = false; bool val = false;
tree ev = version, tmp; tree ev = version, tmp;
/* We cannot just do
tmp = analyze_scalar_evolution (use_loop, version);
ev = resolve_mixers (wrto_loop, tmp);
as resolve_mixers would query the scalar evolution with respect to
wrto_loop. For example, in the situation described in the function
comment, suppose that wrto_loop = loop1, use_loop = loop3 and
version = k2. Then
analyze_scalar_evolution (use_loop, version) = k2
and resolve_mixers (loop1, k2) finds that the value of k2 in loop 1
is 100, which is a wrong result, since we are interested in the
value in loop 3.
Instead, we need to proceed from use_loop to wrto_loop loop by loop,
each time checking that there is no evolution in the inner loop. */
if (folded_casts) if (folded_casts)
*folded_casts = false; *folded_casts = false;
while (1) while (1)
...@@ -2743,17 +2804,31 @@ scev_reset (void) ...@@ -2743,17 +2804,31 @@ scev_reset (void)
} }
} }
/* Checks whether OP behaves as a simple affine iv of LOOP in STMT and returns /* Checks whether use of OP in USE_LOOP behaves as a simple affine iv with
its base and step in IV if possible. If ALLOW_NONCONSTANT_STEP is true, we respect to WRTO_LOOP and returns its base and step in IV if possible
want step to be invariant in LOOP. Otherwise we require it to be an (see analyze_scalar_evolution_in_loop for more details on USE_LOOP
integer constant. IV->no_overflow is set to true if we are sure the iv cannot and WRTO_LOOP). If ALLOW_NONCONSTANT_STEP is true, we want step to be
overflow (e.g. because it is computed in signed arithmetics). */ invariant in LOOP. Otherwise we require it to be an integer constant.
IV->no_overflow is set to true if we are sure the iv cannot overflow (e.g.
because it is computed in signed arithmetics). Consequently, adding an
induction variable
for (i = IV->base; ; i += IV->step)
is only safe if IV->no_overflow is false, or TYPE_OVERFLOW_UNDEFINED is
false for the type of the induction variable, or you can prove that i does
not wrap by some other argument. Otherwise, this might introduce undefined
behavior, and
for (i = iv->base; ; i = (type) ((unsigned type) i + (unsigned type) iv->step))
must be used instead. */
bool bool
simple_iv (struct loop *loop, gimple stmt, tree op, affine_iv *iv, simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op,
bool allow_nonconstant_step) affine_iv *iv, bool allow_nonconstant_step)
{ {
basic_block bb = gimple_bb (stmt);
tree type, ev; tree type, ev;
bool folded_casts; bool folded_casts;
...@@ -2766,13 +2841,13 @@ simple_iv (struct loop *loop, gimple stmt, tree op, affine_iv *iv, ...@@ -2766,13 +2841,13 @@ simple_iv (struct loop *loop, gimple stmt, tree op, affine_iv *iv,
&& TREE_CODE (type) != POINTER_TYPE) && TREE_CODE (type) != POINTER_TYPE)
return false; return false;
ev = analyze_scalar_evolution_in_loop (loop, bb->loop_father, op, ev = analyze_scalar_evolution_in_loop (wrto_loop, use_loop, op,
&folded_casts); &folded_casts);
if (chrec_contains_undetermined (ev)) if (chrec_contains_undetermined (ev)
|| chrec_contains_symbols_defined_in_loop (ev, wrto_loop->num))
return false; return false;
if (tree_does_not_contain_chrecs (ev) if (tree_does_not_contain_chrecs (ev))
&& !chrec_contains_symbols_defined_in_loop (ev, loop->num))
{ {
iv->base = ev; iv->base = ev;
iv->step = build_int_cst (TREE_TYPE (ev), 0); iv->step = build_int_cst (TREE_TYPE (ev), 0);
...@@ -2781,22 +2856,16 @@ simple_iv (struct loop *loop, gimple stmt, tree op, affine_iv *iv, ...@@ -2781,22 +2856,16 @@ simple_iv (struct loop *loop, gimple stmt, tree op, affine_iv *iv,
} }
if (TREE_CODE (ev) != POLYNOMIAL_CHREC if (TREE_CODE (ev) != POLYNOMIAL_CHREC
|| CHREC_VARIABLE (ev) != (unsigned) loop->num) || CHREC_VARIABLE (ev) != (unsigned) wrto_loop->num)
return false; return false;
iv->step = CHREC_RIGHT (ev); iv->step = CHREC_RIGHT (ev);
if (allow_nonconstant_step) if ((!allow_nonconstant_step && TREE_CODE (iv->step) != INTEGER_CST)
{ || tree_contains_chrecs (iv->step, NULL))
if (tree_contains_chrecs (iv->step, NULL)
|| chrec_contains_symbols_defined_in_loop (iv->step, loop->num))
return false;
}
else if (TREE_CODE (iv->step) != INTEGER_CST)
return false; return false;
iv->base = CHREC_LEFT (ev); iv->base = CHREC_LEFT (ev);
if (tree_contains_chrecs (iv->base, NULL) if (tree_contains_chrecs (iv->base, NULL))
|| chrec_contains_symbols_defined_in_loop (iv->base, loop->num))
return false; return false;
iv->no_overflow = !folded_casts && TYPE_OVERFLOW_UNDEFINED (type); iv->no_overflow = !folded_casts && TYPE_OVERFLOW_UNDEFINED (type);
......
...@@ -36,7 +36,7 @@ extern void scev_analysis (void); ...@@ -36,7 +36,7 @@ extern void scev_analysis (void);
unsigned int scev_const_prop (void); unsigned int scev_const_prop (void);
bool expression_expensive_p (tree); bool expression_expensive_p (tree);
extern bool simple_iv (struct loop *, gimple, tree, affine_iv *, bool); extern bool simple_iv (struct loop *, struct loop *, tree, affine_iv *, bool);
/* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the /* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the
loop is function's body. */ loop is function's body. */
......
...@@ -884,7 +884,7 @@ determine_biv_step (gimple phi) ...@@ -884,7 +884,7 @@ determine_biv_step (gimple phi)
if (!is_gimple_reg (name)) if (!is_gimple_reg (name))
return NULL_TREE; return NULL_TREE;
if (!simple_iv (loop, phi, name, &iv, true)) if (!simple_iv (loop, loop, name, &iv, true))
return NULL_TREE; return NULL_TREE;
return integer_zerop (iv.step) ? NULL_TREE : iv.step; return integer_zerop (iv.step) ? NULL_TREE : iv.step;
...@@ -990,7 +990,7 @@ find_givs_in_stmt_scev (struct ivopts_data *data, gimple stmt, affine_iv *iv) ...@@ -990,7 +990,7 @@ find_givs_in_stmt_scev (struct ivopts_data *data, gimple stmt, affine_iv *iv)
if (TREE_CODE (lhs) != SSA_NAME) if (TREE_CODE (lhs) != SSA_NAME)
return false; return false;
if (!simple_iv (loop, stmt, lhs, iv, true)) if (!simple_iv (loop, loop_containing_stmt (stmt), lhs, iv, true))
return false; return false;
iv->base = expand_simple_operations (iv->base); iv->base = expand_simple_operations (iv->base);
......
...@@ -1781,9 +1781,9 @@ number_of_iterations_exit (struct loop *loop, edge exit, ...@@ -1781,9 +1781,9 @@ number_of_iterations_exit (struct loop *loop, edge exit,
&& !POINTER_TYPE_P (type)) && !POINTER_TYPE_P (type))
return false; return false;
if (!simple_iv (loop, stmt, op0, &iv0, false)) if (!simple_iv (loop, loop_containing_stmt (stmt), op0, &iv0, false))
return false; return false;
if (!simple_iv (loop, stmt, op1, &iv1, false)) if (!simple_iv (loop, loop_containing_stmt (stmt), op1, &iv1, false))
return false; return false;
/* We don't want to see undefined signed overflow warnings while /* We don't want to see undefined signed overflow warnings while
......
...@@ -364,7 +364,8 @@ idx_analyze_ref (tree base, tree *index, void *data) ...@@ -364,7 +364,8 @@ idx_analyze_ref (tree base, tree *index, void *data)
|| TREE_CODE (base) == ALIGN_INDIRECT_REF) || TREE_CODE (base) == ALIGN_INDIRECT_REF)
return false; return false;
if (!simple_iv (ar_data->loop, ar_data->stmt, *index, &iv, false)) if (!simple_iv (ar_data->loop, loop_containing_stmt (ar_data->stmt),
*index, &iv, false))
return false; return false;
ibase = iv.base; ibase = iv.base;
step = iv.step; step = iv.step;
......
...@@ -3622,7 +3622,8 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) ...@@ -3622,7 +3622,8 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
} }
outer_base = build_fold_addr_expr (outer_base); outer_base = build_fold_addr_expr (outer_base);
if (!simple_iv (loop, stmt, outer_base, &base_iv, false)) if (!simple_iv (loop, loop_containing_stmt (stmt), outer_base,
&base_iv, false))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "failed: evolution of base is not affine.\n"); fprintf (vect_dump, "failed: evolution of base is not affine.\n");
...@@ -3642,7 +3643,8 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) ...@@ -3642,7 +3643,8 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
offset_iv.base = ssize_int (0); offset_iv.base = ssize_int (0);
offset_iv.step = ssize_int (0); offset_iv.step = ssize_int (0);
} }
else if (!simple_iv (loop, stmt, poffset, &offset_iv, false)) else if (!simple_iv (loop, loop_containing_stmt (stmt), poffset,
&offset_iv, false))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "evolution of offset is not affine.\n"); fprintf (vect_dump, "evolution of offset is not affine.\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment