re PR middle-end/37375 ([graphite] Parameter detection and scev only take a surrounding loop as border)

2008-09-05  Sebastian Pop  <sebastian.pop@amd.com>

	PR tree-optimization/37375
	* tree-scalar-evolution.c (scev_info_str): Add field instantiated_below.
	(new_scev_info_str, eq_scev_info, find_var_scev_info,
	set_scalar_evolution, get_scalar_evolution, get_instantiated_value,
	set_instantiated_value): Pass instantiated_below.
	(analyze_scalar_evolution_1, analyze_scalar_evolution): Update calls to
	above functions.
	(instantiate_scev_1, instantiate_scev): Pass a basic block above which the
	definitions are not instantiated.

	* tree-scalar-evolution.h (instantiate_scev): Update declaration.
	(block_before_loop): New.
	* tree-data-ref.c (dr_analyze_indices): Update uses of instantiate_scev.
	* graphite.c (block_before_scop): New.
	(loop_affine_expr, stmt_simple_for_scop_p, harmful_stmt_in_bb): Pass a 
	basic block, not a loop for determining the parameters.
	(scopdet_edge_info, build_scops_1): Do not pass outermost loop in the
	scop.
	(idx_record_params, find_params_in_bb, find_scop_parameters,
	build_loop_iteration_domains, add_conditions_to_domain): Update calls 
	to instantiate_scev.
	
	* Makefile.in (cfgloopmanip.o): Add missing dependency on TREE_FLOW_H.

From-SVN: r140164
This commit is contained in:
Sebastian Pop 2008-09-09 18:39:45 +00:00 committed by Sebastian Pop
parent 00ca66405c
commit a213b2190b
6 changed files with 172 additions and 134 deletions

View File

@ -1,3 +1,29 @@
2008-09-09 Sebastian Pop <sebastian.pop@amd.com>
PR tree-optimization/37375
* tree-scalar-evolution.c (scev_info_str): Add field instantiated_below.
(new_scev_info_str, eq_scev_info, find_var_scev_info,
set_scalar_evolution, get_scalar_evolution, get_instantiated_value,
set_instantiated_value): Pass instantiated_below.
(analyze_scalar_evolution_1, analyze_scalar_evolution): Update calls to
above functions.
(instantiate_scev_1, instantiate_scev): Pass a basic block above which the
definitions are not instantiated.
* tree-scalar-evolution.h (instantiate_scev): Update declaration.
(block_before_loop): New.
* tree-data-ref.c (dr_analyze_indices): Update uses of instantiate_scev.
* graphite.c (block_before_scop): New.
(loop_affine_expr, stmt_simple_for_scop_p, harmful_stmt_in_bb): Pass a
basic block, not a loop for determining the parameters.
(scopdet_edge_info, build_scops_1): Do not pass outermost loop in the
scop.
(idx_record_params, find_params_in_bb, find_scop_parameters,
build_loop_iteration_domains, add_conditions_to_domain): Update calls
to instantiate_scev.
* Makefile.in (cfgloopmanip.o): Add missing dependency on TREE_FLOW_H.
2008-09-09 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-opt/37333

View File

@ -2816,7 +2816,7 @@ loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(HASHTAB_H) except.h
cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) output.h \
coretypes.h $(TM_H) cfghooks.h $(OBSTACK_H)
coretypes.h $(TM_H) cfghooks.h $(OBSTACK_H) $(TREE_FLOW_H)
loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(GGC_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) \
coretypes.h $(TM_H) $(OBSTACK_H) tree-pass.h $(TIMEVAR_H) $(FLAGS_H) $(DF_H)

View File

@ -717,16 +717,24 @@ outermost_loop_in_scop (scop_p scop, basic_block bb)
return nest;
}
/* Returns the block preceding the entry of SCOP. */
static basic_block
block_before_scop (scop_p scop)
{
return SESE_ENTRY (SCOP_REGION (scop))->src;
}
/* Return true when EXPR is an affine function in LOOP with parameters
instantiated relative to outermost_loop. */
instantiated relative to SCOP_ENTRY. */
static bool
loop_affine_expr (struct loop *outermost_loop, struct loop *loop, tree expr)
loop_affine_expr (basic_block scop_entry, struct loop *loop, tree expr)
{
int n = outermost_loop->num;
int n = scop_entry->loop_father->num;
tree scev = analyze_scalar_evolution (loop, expr);
scev = instantiate_scev (outermost_loop, loop, scev);
scev = instantiate_scev (scop_entry, loop, scev);
return (evolution_function_is_invariant_p (scev, n)
|| evolution_function_is_affine_multivariate_p (scev, n));
@ -751,11 +759,11 @@ is_simple_operand (loop_p loop, gimple stmt, tree op)
}
/* Return true only when STMT is simple enough for being handled by
Graphite. This depends on OUTERMOST_LOOP, as the parametetrs are
initialized relative to this loop. */
Graphite. This depends on SCOP_ENTRY, as the parametetrs are
initialized relatively to this basic block. */
static bool
stmt_simple_for_scop_p (struct loop *outermost_loop, gimple stmt)
stmt_simple_for_scop_p (basic_block scop_entry, gimple stmt)
{
basic_block bb = gimple_bb (stmt);
struct loop *loop = bb->loop_father;
@ -791,11 +799,11 @@ stmt_simple_for_scop_p (struct loop *outermost_loop, gimple stmt)
|| code == GE_EXPR))
return false;
if (!outermost_loop)
if (!scop_entry)
return false;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, op_iter, SSA_OP_ALL_USES)
if (!loop_affine_expr (outermost_loop, loop, op))
if (!loop_affine_expr (scop_entry, loop, op))
return false;
return true;
@ -850,18 +858,17 @@ stmt_simple_for_scop_p (struct loop *outermost_loop, gimple stmt)
}
/* Returns the statement of BB that contains a harmful operation: that
can be a function call with side effects, data dependences that
cannot be computed in OUTERMOST_LOOP, the induction variables are
not linear with respect to OUTERMOST_LOOP, etc. The current open
can be a function call with side effects, the induction variables
are not linear with respect to SCOP_ENTRY, etc. The current open
scop should end before this statement. */
static gimple
harmful_stmt_in_bb (struct loop *outermost_loop, basic_block bb)
harmful_stmt_in_bb (basic_block scop_entry, basic_block bb)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
if (!stmt_simple_for_scop_p (outermost_loop, gsi_stmt (gsi)))
if (!stmt_simple_for_scop_p (scop_entry, gsi_stmt (gsi)))
return gsi_stmt (gsi);
return NULL;
@ -1048,20 +1055,28 @@ struct scopdet_info
};
static struct scopdet_info build_scops_1 (edge, VEC (scop_p, heap) **,
loop_p, loop_p);
loop_p);
/* Checks, if a bb can be added to a SCoP. */
static struct scopdet_info
scopdet_edge_info (edge ee, loop_p outermost_loop,
scopdet_edge_info (edge ee,
VEC (scop_p, heap) **scops, gbb_type type, gimple *stmt)
{
basic_block bb = ee->dest;
struct loop *loop = bb->loop_father;
struct scopdet_info result;
basic_block scop_entry;
*stmt = harmful_stmt_in_bb (outermost_loop, bb);
if (VEC_length (scop_p, *scops) != 0)
scop_entry = block_before_scop (VEC_last (scop_p, *scops));
else if (loop->header)
scop_entry = loop->header;
else
scop_entry = ENTRY_BLOCK_PTR;
*stmt = harmful_stmt_in_bb (scop_entry, bb);
result.difficult = (*stmt != NULL);
result.last = NULL;
@ -1084,7 +1099,7 @@ scopdet_edge_info (edge ee, loop_p outermost_loop,
VEC (scop_p, heap) *tmp_scops = VEC_alloc (scop_p, heap, 3);
struct scopdet_info sinfo;
sinfo = build_scops_1 (ee, &tmp_scops, loop, outermost_loop);
sinfo = build_scops_1 (ee, &tmp_scops, loop);
result.last = single_exit (bb->loop_father);
@ -1117,20 +1132,18 @@ scopdet_edge_info (edge ee, loop_p outermost_loop,
case GBB_LOOP_MULT_EXIT_HEADER:
{
/* XXX: Handle loop nests with the same header. */
/* XXX: Handle iterative optimization of outermost_loop. */
/* XXX: For now we just do not join loops with multiple exits. If the
exits lead to the same bb it may be possible to join the loop. */
VEC (scop_p, heap) *tmp_scops = VEC_alloc (scop_p, heap, 3);
VEC (edge, heap) *exits = get_loop_exit_edges (loop);
edge e;
int i;
build_scops_1 (ee, &tmp_scops, loop, outermost_loop);
build_scops_1 (ee, &tmp_scops, loop);
for (i = 0; VEC_iterate (edge, exits, i, e); i++)
if (dominated_by_p (CDI_DOMINATORS, e->dest, e->src)
&& e->dest->loop_father == loop_outer (loop))
build_scops_1 (e, &tmp_scops, e->dest->loop_father,
outermost_loop);
build_scops_1 (e, &tmp_scops, e->dest->loop_father);
result.next = NULL;
result.last = NULL;
@ -1199,7 +1212,7 @@ scopdet_edge_info (edge ee, loop_p outermost_loop,
continue;
}
sinfo = build_scops_1 (e, &tmp_scops, loop, outermost_loop);
sinfo = build_scops_1 (e, &tmp_scops, loop);
result.exits |= sinfo.exits;
result.last = sinfo.last;
@ -1261,10 +1274,9 @@ scopdet_edge_info (edge ee, loop_p outermost_loop,
e = split_block (dom_bb, NULL);
if (loop_depth (loop) > loop_depth (dom_bb->loop_father))
sinfo = build_scops_1 (e, &tmp_scops, loop_outer (loop),
outermost_loop);
sinfo = build_scops_1 (e, &tmp_scops, loop_outer (loop));
else
sinfo = build_scops_1 (e, &tmp_scops, loop, outermost_loop);
sinfo = build_scops_1 (e, &tmp_scops, loop);
result.exits |= sinfo.exits;
@ -1335,8 +1347,7 @@ end_scop (scop_p scop, edge exit, bool split_entry)
/* Creates the SCoPs and writes entry and exit points for every SCoP. */
static struct scopdet_info
build_scops_1 (edge start, VEC (scop_p, heap) **scops, loop_p loop,
loop_p outermost_loop)
build_scops_1 (edge start, VEC (scop_p, heap) **scops, loop_p loop)
{
edge current = start;
@ -1357,7 +1368,7 @@ build_scops_1 (edge start, VEC (scop_p, heap) **scops, loop_p loop,
and can only be added if all bbs in deeper layers are simple. */
while (current != NULL)
{
sinfo = scopdet_edge_info (current, outermost_loop, scops,
sinfo = scopdet_edge_info (current, scops,
get_bb_type (current->dest, loop), &stmt);
if (!in_scop && !(sinfo.exits || sinfo.difficult))
@ -1433,7 +1444,7 @@ static void
build_scops (void)
{
struct loop *loop = current_loops->tree_root;
build_scops_1 (single_succ_edge (ENTRY_BLOCK_PTR), &current_scops, loop, loop);
build_scops_1 (single_succ_edge (ENTRY_BLOCK_PTR), &current_scops, loop);
}
/* Gather the basic blocks belonging to the SCOP. */
@ -1895,19 +1906,15 @@ idx_record_params (tree base, tree *idx, void *dta)
tree scev;
scop_p scop = data->scop;
struct loop *loop = data->loop;
Value one;
scev = analyze_scalar_evolution (loop, *idx);
scev = instantiate_scev (outermost_loop_in_scop (scop, loop->header),
loop, scev);
scev = instantiate_scev (block_before_scop (scop), loop, scev);
{
Value one;
value_init (one);
value_set_si (one, 1);
scan_tree_for_params (scop, scev, NULL, 0, one, false);
value_clear (one);
}
value_init (one);
value_set_si (one, 1);
scan_tree_for_params (scop, scev, NULL, 0, one, false);
value_clear (one);
}
return true;
@ -1957,11 +1964,11 @@ find_params_in_bb (scop_p scop, basic_block bb)
lhs = gimple_cond_lhs (stmt);
lhs = analyze_scalar_evolution (loop, lhs);
lhs = instantiate_scev (nest, loop, lhs);
lhs = instantiate_scev (block_before_scop (scop), loop, lhs);
rhs = gimple_cond_rhs (stmt);
rhs = analyze_scalar_evolution (loop, rhs);
rhs = instantiate_scev (nest, loop, rhs);
rhs = instantiate_scev (block_before_scop (scop), loop, rhs);
value_init (one);
scan_tree_for_params (scop, lhs, NULL, 0, one, false);
@ -2081,8 +2088,7 @@ find_scop_parameters (scop_p scop)
continue;
nb_iters = analyze_scalar_evolution (loop, nb_iters);
nb_iters = instantiate_scev (outermost_loop_in_scop (scop, loop->header),
loop, nb_iters);
nb_iters = instantiate_scev (block_before_scop (scop), loop, nb_iters);
scan_tree_for_params (scop, nb_iters, NULL, 0, one, false);
}
@ -2209,10 +2215,10 @@ build_loop_iteration_domains (scop_p scop, struct loop *loop,
row++;
value_set_si (cstr->p[row][0], 1);
value_set_si (cstr->p[row][loop_col], -1);
nb_iters = analyze_scalar_evolution (loop, nb_iters);
nb_iters =
instantiate_scev (outermost_loop_in_scop (scop, loop->header),
loop, nb_iters);
nb_iters = instantiate_scev (block_before_scop (scop), loop, nb_iters);
value_init (one);
value_set_si (one, 1);
scan_tree_for_params (scop, nb_iters, cstr, row, one, false);
@ -2333,15 +2339,15 @@ add_conditions_to_domain (graphite_bb_p gb)
tree left;
tree right;
loop_p loop = GBB_BB (gb)->loop_father;
loop_p outermost = outermost_loop_in_scop (scop, GBB_BB (gb));
left = gimple_cond_lhs (stmt);
right = gimple_cond_rhs (stmt);
left = analyze_scalar_evolution (loop, left);
right = analyze_scalar_evolution (loop, right);
left = instantiate_scev (outermost, loop, left);
right = instantiate_scev (outermost, loop, right);
left = instantiate_scev (block_before_scop (scop), loop, left);
right = instantiate_scev (block_before_scop (scop), loop, right);
code = gimple_cond_code (stmt);
@ -3974,13 +3980,13 @@ gbb_can_be_ignored (graphite_bb_p gb)
XXX: Just a heuristic, that needs further investigation. */
case GIMPLE_ASSIGN:
{
tree var = gimple_assign_lhs (stmt);
tree var = gimple_assign_lhs (stmt);
var = analyze_scalar_evolution (loop, var);
var = instantiate_scev (outermost_loop_in_scop (scop,
GBB_BB (gb)),
loop, var);
var = instantiate_scev (block_before_scop (scop), loop, var);
if (TREE_CODE (var) == SCEV_NOT_KNOWN)
return false;
break;
}
/* Otherwise not ignoreable. */

View File

@ -747,6 +747,7 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
VEC (tree, heap) *access_fns = NULL;
tree ref = unshare_expr (DR_REF (dr)), aref = ref, op;
tree base, off, access_fn;
basic_block before_loop = block_before_loop (nest);
while (handled_component_p (aref))
{
@ -754,7 +755,7 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
{
op = TREE_OPERAND (aref, 1);
access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (nest, loop, access_fn);
access_fn = instantiate_scev (before_loop, loop, access_fn);
VEC_safe_push (tree, heap, access_fns, access_fn);
TREE_OPERAND (aref, 1) = build_int_cst (TREE_TYPE (op), 0);
@ -767,7 +768,7 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
{
op = TREE_OPERAND (aref, 0);
access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (nest, loop, access_fn);
access_fn = instantiate_scev (before_loop, loop, access_fn);
base = initial_condition (access_fn);
split_constant_offset (base, &base, &off);
access_fn = chrec_replace_initial_condition (access_fn,

View File

@ -175,8 +175,8 @@ along with GCC; see the file COPYING3. If not see
value of loop_2 for "j" is 4, and the evolution of "k" in loop_1 is
{0, +, 1}_1. To obtain the evolution function in loop_3 and
instantiate the scalar variables up to loop_1, one has to use:
instantiate_scev (loop_1, loop_3, "j + k"). The result of this
call is {{0, +, 1}_1, +, 1}_2.
instantiate_scev (block_before_loop (loop_1), loop_3, "j + k").
The result of this call is {{0, +, 1}_1, +, 1}_2.
Example 3: Higher degree polynomials.
@ -278,11 +278,13 @@ along with GCC; see the file COPYING3. If not see
static tree analyze_scalar_evolution_1 (struct loop *, tree, tree);
/* The cached information about a ssa name VAR, claiming that inside LOOP,
the value of VAR can be expressed as CHREC. */
/* The cached information about an SSA name VAR, claiming that below
basic block INSTANTIATED_BELOW, the value of VAR can be expressed
as CHREC. */
struct scev_info_str GTY(())
{
basic_block instantiated_below;
tree var;
tree chrec;
};
@ -306,22 +308,21 @@ tree chrec_dont_know;
happen, then it qualifies it with chrec_known. */
tree chrec_known;
static bitmap already_instantiated;
static GTY ((param_is (struct scev_info_str))) htab_t scalar_evolution_info;
/* Constructs a new SCEV_INFO_STR structure. */
/* Constructs a new SCEV_INFO_STR structure for VAR and INSTANTIATED_BELOW. */
static inline struct scev_info_str *
new_scev_info_str (tree var)
new_scev_info_str (basic_block instantiated_below, tree var)
{
struct scev_info_str *res;
res = GGC_NEW (struct scev_info_str);
res->var = var;
res->chrec = chrec_not_analyzed_yet;
res->instantiated_below = instantiated_below;
return res;
}
@ -341,7 +342,8 @@ eq_scev_info (const void *e1, const void *e2)
const struct scev_info_str *elt1 = (const struct scev_info_str *) e1;
const struct scev_info_str *elt2 = (const struct scev_info_str *) e2;
return elt1->var == elt2->var;
return (elt1->var == elt2->var
&& elt1->instantiated_below == elt2->instantiated_below);
}
/* Deletes database element E. */
@ -352,22 +354,22 @@ del_scev_info (void *e)
ggc_free (e);
}
/* Get the index corresponding to VAR in the current LOOP. If
it's the first time we ask for this VAR, then we return
chrec_not_analyzed_yet for this VAR and return its index. */
/* Get the scalar evolution of VAR for INSTANTIATED_BELOW basic block.
A first query on VAR returns chrec_not_analyzed_yet. */
static tree *
find_var_scev_info (tree var)
find_var_scev_info (basic_block instantiated_below, tree var)
{
struct scev_info_str *res;
struct scev_info_str tmp;
PTR *slot;
tmp.var = var;
tmp.instantiated_below = instantiated_below;
slot = htab_find_slot (scalar_evolution_info, &tmp, INSERT);
if (!*slot)
*slot = new_scev_info_str (var);
*slot = new_scev_info_str (instantiated_below, var);
res = (struct scev_info_str *) *slot;
return &res->chrec;
@ -570,20 +572,22 @@ chrec_is_positive (tree chrec, bool *value)
/* Associate CHREC to SCALAR. */
static void
set_scalar_evolution (tree scalar, tree chrec)
set_scalar_evolution (basic_block instantiated_below, tree scalar, tree chrec)
{
tree *scalar_info;
if (TREE_CODE (scalar) != SSA_NAME)
return;
scalar_info = find_var_scev_info (scalar);
scalar_info = find_var_scev_info (instantiated_below, scalar);
if (dump_file)
{
if (dump_flags & TDF_DETAILS)
{
fprintf (dump_file, "(set_scalar_evolution \n");
fprintf (dump_file, " instantiated_below = %d \n",
instantiated_below->index);
fprintf (dump_file, " (scalar = ");
print_generic_expr (dump_file, scalar, 0);
fprintf (dump_file, ")\n (scalar_evolution = ");
@ -597,10 +601,11 @@ set_scalar_evolution (tree scalar, tree chrec)
*scalar_info = chrec;
}
/* Retrieve the chrec associated to SCALAR in the LOOP. */
/* Retrieve the chrec associated to SCALAR instantiated below
INSTANTIATED_BELOW block. */
static tree
get_scalar_evolution (tree scalar)
get_scalar_evolution (basic_block instantiated_below, tree scalar)
{
tree res;
@ -620,7 +625,7 @@ get_scalar_evolution (tree scalar)
switch (TREE_CODE (scalar))
{
case SSA_NAME:
res = *find_var_scev_info (scalar);
res = *find_var_scev_info (instantiated_below, scalar);
break;
case REAL_CST:
@ -1845,7 +1850,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
res = var;
if (loop == def_loop)
set_scalar_evolution (var, res);
set_scalar_evolution (block_before_loop (loop), var, res);
return res;
}
@ -1879,7 +1884,8 @@ analyze_scalar_evolution (struct loop *loop, tree var)
fprintf (dump_file, ")\n");
}
res = analyze_scalar_evolution_1 (loop, var, get_scalar_evolution (var));
res = get_scalar_evolution (block_before_loop (loop), var);
res = analyze_scalar_evolution_1 (loop, var, res);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, ")\n");
@ -1926,14 +1932,17 @@ analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop,
}
}
/* Returns instantiated value for VERSION in CACHE. */
/* Returns from CACHE the value for VERSION instantiated below
INSTANTIATED_BELOW block. */
static tree
get_instantiated_value (htab_t cache, tree version)
get_instantiated_value (htab_t cache, basic_block instantiated_below,
tree version)
{
struct scev_info_str *info, pattern;
pattern.var = version;
pattern.instantiated_below = instantiated_below;
info = (struct scev_info_str *) htab_find (cache, &pattern);
if (info)
@ -1942,10 +1951,12 @@ get_instantiated_value (htab_t cache, tree version)
return NULL_TREE;
}
/* Sets instantiated value for VERSION to VAL in CACHE. */
/* Sets in CACHE the value of VERSION instantiated below basic block
INSTANTIATED_BELOW to VAL. */
static void
set_instantiated_value (htab_t cache, tree version, tree val)
set_instantiated_value (htab_t cache, basic_block instantiated_below,
tree version, tree val)
{
struct scev_info_str *info, pattern;
PTR *slot;
@ -1954,7 +1965,7 @@ set_instantiated_value (htab_t cache, tree version, tree val)
slot = htab_find_slot (cache, &pattern, INSERT);
if (!*slot)
*slot = new_scev_info_str (version);
*slot = new_scev_info_str (instantiated_below, version);
info = (struct scev_info_str *) *slot;
info->chrec = val;
}
@ -1989,7 +2000,7 @@ loop_closed_phi_def (tree var)
return NULL_TREE;
}
/* Analyze all the parameters of the chrec, between INSTANTIATION_LOOP
/* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is the scalar evolution to instantiate.
@ -2004,7 +2015,7 @@ loop_closed_phi_def (tree var)
instantiated, and to stop if it exceeds some limit. */
static tree
instantiate_scev_1 (struct loop *instantiation_loop,
instantiate_scev_1 (basic_block instantiate_below,
struct loop *evolution_loop, tree chrec,
bool fold_conversions, htab_t cache, int size_expr)
{
@ -2030,7 +2041,7 @@ instantiate_scev_1 (struct loop *instantiation_loop,
evolutions in outer loops), nothing to do. */
if (!def_bb
|| loop_depth (def_bb->loop_father) == 0
|| !flow_bb_inside_loop_p (instantiation_loop, def_bb))
|| dominated_by_p (CDI_DOMINATORS, instantiate_below, def_bb))
return chrec;
/* We cache the value of instantiated variable to avoid exponential
@ -2042,31 +2053,17 @@ instantiate_scev_1 (struct loop *instantiation_loop,
| a_2 -> {0, +, 1, +, a_2}_1 */
res = get_instantiated_value (cache, chrec);
res = get_instantiated_value (cache, instantiate_below, chrec);
if (res)
return res;
/* Store the convenient value for chrec in the structure. If it
is defined outside of the loop, we may just leave it in symbolic
form, otherwise we need to admit that we do not know its behavior
inside the loop. */
res = !flow_bb_inside_loop_p (instantiation_loop, def_bb)
? chrec : chrec_dont_know;
set_instantiated_value (cache, chrec, res);
/* To make things even more complicated, instantiate_scev_1
calls analyze_scalar_evolution that may call # of iterations
analysis that may in turn call instantiate_scev_1 again.
To prevent the infinite recursion, keep also the bitmap of
ssa names that are being instantiated globally. */
if (bitmap_bit_p (already_instantiated, SSA_NAME_VERSION (chrec)))
return res;
res = chrec_dont_know;
set_instantiated_value (cache, instantiate_below, chrec, res);
def_loop = find_common_loop (evolution_loop, def_bb->loop_father);
/* If the analysis yields a parametric chrec, instantiate the
result again. */
bitmap_set_bit (already_instantiated, SSA_NAME_VERSION (chrec));
res = analyze_scalar_evolution (def_loop, chrec);
/* Don't instantiate loop-closed-ssa phi nodes. */
@ -2085,23 +2082,21 @@ instantiate_scev_1 (struct loop *instantiation_loop,
}
else if (res != chrec_dont_know)
res = instantiate_scev_1 (instantiation_loop, evolution_loop, res,
res = instantiate_scev_1 (instantiate_below, evolution_loop, res,
fold_conversions, cache, size_expr);
bitmap_clear_bit (already_instantiated, SSA_NAME_VERSION (chrec));
/* Store the correct value to the cache. */
set_instantiated_value (cache, chrec, res);
set_instantiated_value (cache, instantiate_below, chrec, res);
return res;
case POLYNOMIAL_CHREC:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
CHREC_LEFT (chrec), fold_conversions, cache,
size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
CHREC_RIGHT (chrec), fold_conversions, cache,
size_expr);
if (op1 == chrec_dont_know)
@ -2117,13 +2112,13 @@ instantiate_scev_1 (struct loop *instantiation_loop,
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 0), fold_conversions, cache,
size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 1), fold_conversions, cache,
size_expr);
if (op1 == chrec_dont_know)
@ -2139,13 +2134,13 @@ instantiate_scev_1 (struct loop *instantiation_loop,
return chrec;
case MINUS_EXPR:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 0), fold_conversions, cache,
size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 1),
fold_conversions, cache, size_expr);
if (op1 == chrec_dont_know)
@ -2161,13 +2156,13 @@ instantiate_scev_1 (struct loop *instantiation_loop,
return chrec;
case MULT_EXPR:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 0),
fold_conversions, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 1),
fold_conversions, cache, size_expr);
if (op1 == chrec_dont_know)
@ -2183,7 +2178,7 @@ instantiate_scev_1 (struct loop *instantiation_loop,
return chrec;
CASE_CONVERT:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 0),
fold_conversions, cache, size_expr);
if (op0 == chrec_dont_know)
@ -2221,19 +2216,19 @@ instantiate_scev_1 (struct loop *instantiation_loop,
switch (TREE_CODE_LENGTH (TREE_CODE (chrec)))
{
case 3:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 0),
fold_conversions, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 1),
fold_conversions, cache, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
op2 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op2 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 2),
fold_conversions, cache, size_expr);
if (op2 == chrec_dont_know)
@ -2248,13 +2243,13 @@ instantiate_scev_1 (struct loop *instantiation_loop,
TREE_TYPE (chrec), op0, op1, op2);
case 2:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 0),
fold_conversions, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op1 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 1),
fold_conversions, cache, size_expr);
if (op1 == chrec_dont_know)
@ -2266,7 +2261,7 @@ instantiate_scev_1 (struct loop *instantiation_loop,
return fold_build2 (TREE_CODE (chrec), TREE_TYPE (chrec), op0, op1);
case 1:
op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
op0 = instantiate_scev_1 (instantiate_below, evolution_loop,
TREE_OPERAND (chrec, 0),
fold_conversions, cache, size_expr);
if (op0 == chrec_dont_know)
@ -2287,12 +2282,13 @@ instantiate_scev_1 (struct loop *instantiation_loop,
}
/* Analyze all the parameters of the chrec that were left under a
symbolic form. INSTANTIATION_LOOP is the loop in which symbolic
names have to be instantiated, and EVOLUTION_LOOP is the loop in
which the evolution of scalars have to be analyzed. */
symbolic form. INSTANTIATE_BELOW is the basic block that stops the
recursive instantiation of parameters: a parameter is a variable
that is defined in a basic block that dominates INSTANTIATE_BELOW or
a function parameter. */
tree
instantiate_scev (struct loop *instantiation_loop, struct loop *evolution_loop,
instantiate_scev (basic_block instantiate_below, struct loop *evolution_loop,
tree chrec)
{
tree res;
@ -2301,14 +2297,14 @@ instantiate_scev (struct loop *instantiation_loop, struct loop *evolution_loop,
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "(instantiate_scev \n");
fprintf (dump_file, " (instantiation_loop = %d)\n", instantiation_loop->num);
fprintf (dump_file, " (instantiate_below = %d)\n", instantiate_below->index);
fprintf (dump_file, " (evolution_loop = %d)\n", evolution_loop->num);
fprintf (dump_file, " (chrec = ");
print_generic_expr (dump_file, chrec, 0);
fprintf (dump_file, ")\n");
}
res = instantiate_scev_1 (instantiation_loop, evolution_loop, chrec, false,
res = instantiate_scev_1 (instantiate_below, evolution_loop, chrec, false,
cache, 0);
if (dump_file && (dump_flags & TDF_DETAILS))
@ -2332,7 +2328,8 @@ tree
resolve_mixers (struct loop *loop, tree chrec)
{
htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info);
tree ret = instantiate_scev_1 (loop, loop, chrec, true, cache, 0);
tree ret = instantiate_scev_1 (block_before_loop (loop), loop, chrec, true,
cache, 0);
htab_delete (cache);
return ret;
}
@ -2677,7 +2674,6 @@ scev_initialize (void)
del_scev_info,
ggc_calloc,
ggc_free);
already_instantiated = BITMAP_ALLOC (NULL);
initialize_scalar_evolutions_analyzer ();
@ -2791,7 +2787,6 @@ scev_finalize (void)
if (!scalar_evolution_info)
return;
htab_delete (scalar_evolution_info);
BITMAP_FREE (already_instantiated);
scalar_evolution_info = NULL;
}

View File

@ -29,7 +29,7 @@ extern void scev_initialize (void);
extern void scev_reset (void);
extern void scev_finalize (void);
extern tree analyze_scalar_evolution (struct loop *, tree);
extern tree instantiate_scev (struct loop *, struct loop *, tree);
extern tree instantiate_scev (basic_block, struct loop *, tree);
extern tree resolve_mixers (struct loop *, tree);
extern void gather_stats_on_scev_database (void);
extern void scev_analysis (void);
@ -37,6 +37,16 @@ unsigned int scev_const_prop (void);
extern bool simple_iv (struct loop *, gimple, tree, affine_iv *, bool);
/* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the
loop is function's body. */
static inline basic_block
block_before_loop (loop_p loop)
{
edge preheader = loop_preheader_edge (loop);
return (preheader ? preheader->src : ENTRY_BLOCK_PTR);
}
/* Analyze all the parameters of the chrec that were left under a
symbolic form. LOOP is the loop in which symbolic names have to
be analyzed and instantiated. */
@ -44,7 +54,7 @@ extern bool simple_iv (struct loop *, gimple, tree, affine_iv *, bool);
static inline tree
instantiate_parameters (struct loop *loop, tree chrec)
{
return instantiate_scev (loop, loop, chrec);
return instantiate_scev (block_before_loop (loop), loop, chrec);
}
/* Returns the loop of the polynomial chrec CHREC. */