aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-ivopts.c
diff options
context:
space:
mode:
authorZdenek Dvorak <dvorakz@suse.cz>2004-10-01 11:06:06 +0200
committerZdenek Dvorak <rakdver@gcc.gnu.org>2004-10-01 09:06:06 +0000
commite6845c238200c37250282413728488871a8ffea5 (patch)
tree7e352a964e8d59a79b5a87f2f3a25bb04f957d6a /gcc/tree-ssa-loop-ivopts.c
parent5496b36fc242741f3b35796bebcf5c7e99c0465b (diff)
downloadgcc-e6845c238200c37250282413728488871a8ffea5.zip
gcc-e6845c238200c37250282413728488871a8ffea5.tar.gz
gcc-e6845c238200c37250282413728488871a8ffea5.tar.bz2
tree-chrec.c (chrec_fold_plus_poly_poly, [...]): Use fold_convert or build_int_cst_type instead od fonvert.
* tree-chrec.c (chrec_fold_plus_poly_poly, chrec_fold_plus_1, chrec_fold_multiply): Use fold_convert or build_int_cst_type instead od fonvert. * tree-scalar-evolution.c (compute_overall_effect_of_inner_loop, add_to_evolution, set_nb_iterations_in_loop, follow_ssa_edge_in_rhs, follow_ssa_edge_in_rhs): Ditto. * tree-ssa-loop-ivopts.c (struct iv): Add base_object field. (dump_iv): Dump base_object. (dump_use, dump_cand): Use dump_iv. (determine_base_object): New function. (alloc_iv): Initialize base_object field. (record_use): Clear the ssa_name field of iv. (get_computation_cost_at): Do not use difference of addresses of two different objects. (may_eliminate_iv): Do not require the loop to have just single exit. * tree-ssa-loop-niter.c (zero_p): Do not check for overflows. (nonzero_p): New function. (inverse, number_of_iterations_cond, simplify_using_outer_evolutions, tree_simplify_using_condition, simplify_using_initial_conditions, loop_niter_by_eval, find_loop_niter_by_eval, estimate_numbers_of_iterations_loop, compare_trees, upper_bound_in_type, lower_bound_in_type, can_count_iv_in_wider_type_bound): Use buildN instead of build. Use fold_convert or build_int_cst_type instead of convert. Use (non)zero_p instead of integer_(non)zerop. From-SVN: r88388
Diffstat (limited to 'gcc/tree-ssa-loop-ivopts.c')
-rw-r--r--gcc/tree-ssa-loop-ivopts.c165
1 files changed, 104 insertions, 61 deletions
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 33c275f..4dae6c9 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -104,6 +104,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
struct iv
{
tree base; /* Initial value of the iv. */
+ tree base_object; /* A memory object to that the induction variable points. */
tree step; /* Step of the iv (constant only). */
tree ssa_name; /* The ssa name with the value. */
bool biv_p; /* Is it a biv? */
@@ -301,9 +302,12 @@ extern void dump_iv (FILE *, struct iv *);
void
dump_iv (FILE *file, struct iv *iv)
{
- fprintf (file, "ssa name ");
- print_generic_expr (file, iv->ssa_name, TDF_SLIM);
- fprintf (file, "\n");
+ if (iv->ssa_name)
+ {
+ fprintf (file, "ssa name ");
+ print_generic_expr (file, iv->ssa_name, TDF_SLIM);
+ fprintf (file, "\n");
+ }
fprintf (file, " type ");
print_generic_expr (file, TREE_TYPE (iv->base), TDF_SLIM);
@@ -326,6 +330,13 @@ dump_iv (FILE *file, struct iv *iv)
fprintf (file, "\n");
}
+ if (iv->base_object)
+ {
+ fprintf (file, " base object ");
+ print_generic_expr (file, iv->base_object, TDF_SLIM);
+ fprintf (file, "\n");
+ }
+
if (iv->biv_p)
fprintf (file, " is a biv\n");
}
@@ -336,8 +347,6 @@ extern void dump_use (FILE *, struct iv_use *);
void
dump_use (FILE *file, struct iv_use *use)
{
- struct iv *iv = use->iv;
-
fprintf (file, "use %d\n", use->id);
switch (use->type)
@@ -371,26 +380,7 @@ dump_use (FILE *file, struct iv_use *use)
print_generic_expr (file, *use->op_p, TDF_SLIM);
fprintf (file, "\n");
- fprintf (file, " type ");
- print_generic_expr (file, TREE_TYPE (iv->base), TDF_SLIM);
- fprintf (file, "\n");
-
- if (iv->step)
- {
- fprintf (file, " base ");
- print_generic_expr (file, iv->base, TDF_SLIM);
- fprintf (file, "\n");
-
- fprintf (file, " step ");
- print_generic_expr (file, iv->step, TDF_SLIM);
- fprintf (file, "\n");
- }
- else
- {
- fprintf (file, " invariant ");
- print_generic_expr (file, iv->base, TDF_SLIM);
- fprintf (file, "\n");
- }
+ dump_iv (file, use->iv);
fprintf (file, " related candidates ");
dump_bitmap (file, use->related_cands);
@@ -446,26 +436,7 @@ dump_cand (FILE *file, struct iv_cand *cand)
break;
}
- fprintf (file, " type ");
- print_generic_expr (file, TREE_TYPE (iv->base), TDF_SLIM);
- fprintf (file, "\n");
-
- if (iv->step)
- {
- fprintf (file, " base ");
- print_generic_expr (file, iv->base, TDF_SLIM);
- fprintf (file, "\n");
-
- fprintf (file, " step ");
- print_generic_expr (file, iv->step, TDF_SLIM);
- fprintf (file, "\n");
- }
- else
- {
- fprintf (file, " invariant ");
- print_generic_expr (file, iv->base, TDF_SLIM);
- fprintf (file, "\n");
- }
+ dump_iv (file, iv);
}
/* Returns the info for ssa version VER. */
@@ -626,6 +597,52 @@ tree_ssa_iv_optimize_init (struct loops *loops, struct ivopts_data *data)
VARRAY_GENERIC_PTR_NOGC_INIT (decl_rtl_to_reset, 20, "decl_rtl_to_reset");
}
+/* Returns a memory object to that EXPR points. In case we are able to
+ determine that it does not point to any such object, NULL is returned. */
+
+static tree
+determine_base_object (tree expr)
+{
+ enum tree_code code = TREE_CODE (expr);
+ tree base, obj, op0, op1;
+
+ if (!POINTER_TYPE_P (TREE_TYPE (expr)))
+ return NULL_TREE;
+
+ switch (code)
+ {
+ case INTEGER_CST:
+ return NULL_TREE;
+
+ case ADDR_EXPR:
+ obj = TREE_OPERAND (expr, 0);
+ base = get_base_address (obj);
+
+ if (!base)
+ return fold_convert (ptr_type_node, expr);
+
+ return fold (build1 (ADDR_EXPR, ptr_type_node, base));
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ op0 = determine_base_object (TREE_OPERAND (expr, 0));
+ op1 = determine_base_object (TREE_OPERAND (expr, 1));
+
+ if (!op1)
+ return op0;
+
+ if (!op0)
+ return (code == PLUS_EXPR
+ ? op1
+ : fold (build1 (NEGATE_EXPR, ptr_type_node, op1)));
+
+ return fold (build (code, ptr_type_node, op0, op1));
+
+ default:
+ return fold_convert (ptr_type_node, expr);
+ }
+}
+
/* Allocates an induction variable with given initial value BASE and step STEP
for loop LOOP. */
@@ -638,6 +655,7 @@ alloc_iv (tree base, tree step)
step = NULL_TREE;
iv->base = base;
+ iv->base_object = determine_base_object (base);
iv->step = step;
iv->biv_p = false;
iv->have_use_for = false;
@@ -1001,6 +1019,10 @@ record_use (struct ivopts_data *data, tree *use_p, struct iv *iv,
use->op_p = use_p;
use->related_cands = BITMAP_XMALLOC ();
+ /* To avoid showing ssa name in the dumps, if it was not reset by the
+ caller. */
+ iv->ssa_name = NULL_TREE;
+
if (dump_file && (dump_flags & TDF_DETAILS))
dump_use (dump_file, use);
@@ -2794,6 +2816,19 @@ get_computation_cost_at (struct ivopts_data *data,
return INFTY;
}
+ if (address_p)
+ {
+ /* Do not try to express address of an object with computation based
+ on address of a different object. This may cause problems in rtl
+ level alias analysis (that does not expect this to be happening,
+ as this is illegal in C), and would be unlikely to be useful
+ anyway. */
+ if (use->iv->base_object
+ && cand->iv->base_object
+ && !operand_equal_p (use->iv->base_object, cand->iv->base_object, 0))
+ return INFTY;
+ }
+
if (!cst_and_fits_in_hwi (ustep)
|| !cst_and_fits_in_hwi (cstep))
return INFTY;
@@ -2974,23 +3009,31 @@ may_eliminate_iv (struct loop *loop,
struct iv_use *use, struct iv_cand *cand,
enum tree_code *compare, tree *bound)
{
+ basic_block ex_bb;
edge exit;
- struct tree_niter_desc *niter, new_niter;
+ struct tree_niter_desc niter, new_niter;
tree wider_type, type, base;
-
- /* For now just very primitive -- we work just for the single exit condition,
- and are quite conservative about the possible overflows. TODO -- both of
- these can be improved. */
- exit = single_dom_exit (loop);
- if (!exit)
+
+ /* For now works only for exits that dominate the loop latch. TODO -- extend
+ for other conditions inside loop body. */
+ ex_bb = bb_for_stmt (use->stmt);
+ if (use->stmt != last_stmt (ex_bb)
+ || TREE_CODE (use->stmt) != COND_EXPR)
return false;
- if (use->stmt != last_stmt (exit->src))
+ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, ex_bb))
return false;
- niter = &loop_data (loop)->niter;
- if (!niter->niter
- || !integer_nonzerop (niter->assumptions)
- || !integer_zerop (niter->may_be_zero))
+ exit = EDGE_SUCC (ex_bb, 0);
+ if (flow_bb_inside_loop_p (loop, exit->dest))
+ exit = EDGE_SUCC (ex_bb, 1);
+ if (flow_bb_inside_loop_p (loop, exit->dest))
+ return false;
+
+ niter.niter = NULL_TREE;
+ number_of_iterations_exit (loop, exit, &niter);
+ if (!niter.niter
+ || !integer_nonzerop (niter.assumptions)
+ || !integer_zerop (niter.may_be_zero))
return false;
if (exit->flags & EDGE_TRUE_VALUE)
@@ -2998,7 +3041,7 @@ may_eliminate_iv (struct loop *loop,
else
*compare = NE_EXPR;
- *bound = cand_value_at (loop, cand, use->stmt, niter->niter);
+ *bound = cand_value_at (loop, cand, use->stmt, niter.niter);
/* Let us check there is not some problem with overflows, by checking that
the number of iterations is unchanged. */
@@ -3017,9 +3060,9 @@ may_eliminate_iv (struct loop *loop,
return false;
wider_type = TREE_TYPE (new_niter.niter);
- if (TYPE_PRECISION (wider_type) < TYPE_PRECISION (TREE_TYPE (niter->niter)))
- wider_type = TREE_TYPE (niter->niter);
- if (!operand_equal_p (fold_convert (wider_type, niter->niter),
+ if (TYPE_PRECISION (wider_type) < TYPE_PRECISION (TREE_TYPE (niter.niter)))
+ wider_type = TREE_TYPE (niter.niter);
+ if (!operand_equal_p (fold_convert (wider_type, niter.niter),
fold_convert (wider_type, new_niter.niter), 0))
return false;