Commit 9be872b7 by Zdenek Dvorak Committed by Zdenek Dvorak

re PR tree-optimization/18316 (Missed IV optimization)

	PR tree-optimization/18316
	PR tree-optimization/19126
	* tree.c (build_int_cst_type): Avoid shift by size of type.
	* tree-scalar-evolution.c (simple_iv): Add allow_nonconstant_step
	argument.
	* tree-scalar-evolution.h (simple_iv): Declaration changed.
	* tree-ssa-loop-ivopts.c (struct iv_cand): Add depends_on
	field.
	(dump_cand): Dump depends_on information.
	(determine_biv_step): Add argument to simple_iv call.
	(contains_abnormal_ssa_name_p): Handle case expr == NULL.
	(find_bivs, find_givs_in_stmt_scev): Do not require step to be a
	constant.
	(add_candidate_1): Record depends_on for candidates.
	(tree_int_cst_sign_bit, constant_multiple_of): New functions.
	(get_computation_at, get_computation_cost_at, may_eliminate_iv):
	Handle ivs with nonconstant step.
	(iv_ca_set_remove_invariants, iv_ca_set_add_invariants): New functions.
	(iv_ca_set_no_cp, iv_ca_set_cp): Handle cand->depends_on.
	(create_new_iv): Unshare the step before passing it to create_iv.
	(free_loop_data): Free cand->depends_on.
	(build_addr_strip_iref): New function.
	(find_interesting_uses_address): Use build_addr_strip_iref.
	(strip_offset_1): Split the recursive part from strip_offset.
	Strip constant offset component_refs and array_refs.
	(strip_offset): Split the recursive part to strip_offset_1.
	(add_address_candidates): Removed.
	(add_derived_ivs_candidates): Do not use add_address_candidates.
	(add_iv_value_candidates): Add candidates with stripped constant
	offset.  Consider all candidates with initial value 0 important.
	(struct affine_tree_combination): New.
	(aff_combination_const, aff_combination_elt, aff_combination_scale,
	aff_combination_add_elt, aff_combination_add,
	tree_to_aff_combination, add_elt_to_tree, aff_combination_to_tree,
	fold_affine_sum): New functions.
	(get_computation_at): Use fold_affine_sum.
	* tree-ssa-loop-manip.c (create_iv): Handle ivs with nonconstant step.
	* tree-ssa-loop-niter.c (number_of_iterations_exit): Add argument
	to simple_iv call.

	* gcc.dg/tree-ssa/loop-8.c: New test.

From-SVN: r99059
parent 600f3598
2005-05-01 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/18316
PR tree-optimization/19126
* tree.c (build_int_cst_type): Avoid shift by size of type.
* tree-scalar-evolution.c (simple_iv): Add allow_nonconstant_step
argument.
* tree-scalar-evolution.h (simple_iv): Declaration changed.
* tree-ssa-loop-ivopts.c (struct iv_cand): Add depends_on
field.
(dump_cand): Dump depends_on information.
(determine_biv_step): Add argument to simple_iv call.
(contains_abnormal_ssa_name_p): Handle case expr == NULL.
(find_bivs, find_givs_in_stmt_scev): Do not require step to be a
constant.
(add_candidate_1): Record depends_on for candidates.
(tree_int_cst_sign_bit, constant_multiple_of): New functions.
(get_computation_at, get_computation_cost_at, may_eliminate_iv):
Handle ivs with nonconstant step.
(iv_ca_set_remove_invariants, iv_ca_set_add_invariants): New functions.
(iv_ca_set_no_cp, iv_ca_set_cp): Handle cand->depends_on.
(create_new_iv): Unshare the step before passing it to create_iv.
(free_loop_data): Free cand->depends_on.
(build_addr_strip_iref): New function.
(find_interesting_uses_address): Use build_addr_strip_iref.
(strip_offset_1): Split the recursive part from strip_offset.
Strip constant offset component_refs and array_refs.
(strip_offset): Split the recursive part to strip_offset_1.
(add_address_candidates): Removed.
(add_derived_ivs_candidates): Do not use add_address_candidates.
(add_iv_value_candidates): Add candidates with stripped constant
offset. Consider all candidates with initial value 0 important.
(struct affine_tree_combination): New.
(aff_combination_const, aff_combination_elt, aff_combination_scale,
aff_combination_add_elt, aff_combination_add,
tree_to_aff_combination, add_elt_to_tree, aff_combination_to_tree,
fold_affine_sum): New functions.
(get_computation_at): Use fold_affine_sum.
* tree-ssa-loop-manip.c (create_iv): Handle ivs with nonconstant step.
* tree-ssa-loop-niter.c (number_of_iterations_exit): Add argument
to simple_iv call.
2005-04-30 Michael Matz <matz@suse.de>
* config/i386/i386.md (movmemsi): Also active when
......
2005-05-01 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/loop-8.c: New test.
2005-04-30 Michael Maty <matz@suse.de>
* gcc.dg/inline-mcpy.c: New test.
......
/* A test for strength reduction of ivs with nonconstant step. */
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-vars" } */
int bar (void);
int a[100];
void xxx (void)
{
int iter, step = bar ();
for (iter = 0; iter < 10; iter++)
a[iter * step] = bar ();
}
/* The array access should be strength reduced. But to determine the value of
the step, we need to calculate step * sizeof (int), thus we need to be
a bit careful about which multiplications we disallow. */
/* { dg-final { scan-tree-dump-times "step \\* \[^0-9\]" 0 "vars" } } */
/* { dg-final { scan-tree-dump-times "\[^0-9\] \\* step" 0 "vars" } } */
/* { dg-final { cleanup-tree-dump "vars" } } */
......@@ -2547,10 +2547,13 @@ scev_reset (void)
}
/* Checks whether OP behaves as a simple affine iv of LOOP in STMT and returns
its BASE and STEP if possible. */
its BASE and STEP if possible. If ALLOW_NONCONSTANT_STEP is true, we
want STEP to be invariant in LOOP. Otherwise we require it to be an
integer constant. */
bool
simple_iv (struct loop *loop, tree stmt, tree op, tree *base, tree *step)
simple_iv (struct loop *loop, tree stmt, tree op, tree *base, tree *step,
bool allow_nonconstant_step)
{
basic_block bb = bb_for_stmt (stmt);
tree type, ev;
......@@ -2579,8 +2582,15 @@ simple_iv (struct loop *loop, tree stmt, tree op, tree *base, tree *step)
return false;
*step = CHREC_RIGHT (ev);
if (TREE_CODE (*step) != INTEGER_CST)
if (allow_nonconstant_step)
{
if (tree_contains_chrecs (*step, NULL)
|| chrec_contains_symbols_defined_in_loop (*step, loop->num))
return false;
}
else if (TREE_CODE (*step) != INTEGER_CST)
return false;
*base = CHREC_LEFT (ev);
if (tree_contains_chrecs (*base, NULL)
|| chrec_contains_symbols_defined_in_loop (*base, loop->num))
......
......@@ -32,6 +32,6 @@ extern tree analyze_scalar_evolution (struct loop *, tree);
extern tree instantiate_parameters (struct loop *, tree);
extern void gather_stats_on_scev_database (void);
extern void scev_analysis (void);
extern bool simple_iv (struct loop *, tree, tree, tree *, tree *);
extern bool simple_iv (struct loop *, tree, tree, tree *, tree *, bool);
#endif /* GCC_TREE_SCALAR_EVOLUTION_H */
......@@ -54,6 +54,7 @@ create_iv (tree base, tree step, tree var, struct loop *loop,
tree stmt, initial, step1, stmts;
tree vb, va;
enum tree_code incr_op = PLUS_EXPR;
edge pe = loop_preheader_edge (loop);
if (!var)
{
......@@ -92,6 +93,12 @@ create_iv (tree base, tree step, tree var, struct loop *loop,
}
}
/* Gimplify the step if necessary. We put the computations in front of the
loop (i.e. the step should be loop invariant). */
step = force_gimple_operand (step, &stmts, true, var);
if (stmts)
bsi_insert_on_edge_immediate_loop (pe, stmts);
stmt = build2 (MODIFY_EXPR, void_type_node, va,
build2 (incr_op, TREE_TYPE (base),
vb, step));
......@@ -103,11 +110,7 @@ create_iv (tree base, tree step, tree var, struct loop *loop,
initial = force_gimple_operand (base, &stmts, true, var);
if (stmts)
{
edge pe = loop_preheader_edge (loop);
bsi_insert_on_edge_immediate_loop (pe, stmts);
}
bsi_insert_on_edge_immediate_loop (pe, stmts);
stmt = create_phi_node (vb, loop->header);
SSA_NAME_DEF_STMT (vb) = stmt;
......
......@@ -952,9 +952,9 @@ number_of_iterations_exit (struct loop *loop, edge exit,
&& !POINTER_TYPE_P (type))
return false;
if (!simple_iv (loop, stmt, op0, &base0, &step0))
if (!simple_iv (loop, stmt, op0, &base0, &step0, false))
return false;
if (!simple_iv (loop, stmt, op1, &base1, &step1))
if (!simple_iv (loop, stmt, op1, &base1, &step1, false))
return false;
niter->niter = NULL_TREE;
......
......@@ -518,7 +518,7 @@ tree
build_int_cst_type (tree type, HOST_WIDE_INT low)
{
unsigned HOST_WIDE_INT val = (unsigned HOST_WIDE_INT) low;
unsigned HOST_WIDE_INT hi;
unsigned HOST_WIDE_INT hi, mask;
unsigned bits;
bool signed_p;
bool negative;
......@@ -538,10 +538,12 @@ build_int_cst_type (tree type, HOST_WIDE_INT low)
negative = ((val >> (bits - 1)) & 1) != 0;
/* Mask out the bits outside of the precision of the constant. */
mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
if (signed_p && negative)
val = val | ((~(unsigned HOST_WIDE_INT) 0) << bits);
val |= ~mask;
else
val = val & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
val &= mask;
}
/* Determine the high bits. */
......@@ -556,7 +558,8 @@ build_int_cst_type (tree type, HOST_WIDE_INT low)
else
{
bits -= HOST_BITS_PER_WIDE_INT;
hi = hi & ~((~(unsigned HOST_WIDE_INT) 0) << bits);
mask = (((unsigned HOST_WIDE_INT) 2) << (bits - 1)) - 1;
hi &= mask;
}
}
......
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