that the scev for "b" is known, it is possible to compute the
scev for "c", that is "c -> {a + 1, +, 1}_1". In order to
determine the number of iterations in the loop_1, we have to
- instantiate_parameters ({a + 1, +, 1}_1), that gives after some
+ instantiate_parameters (loop_1, {a + 1, +, 1}_1), that gives after some
more analysis the scev {4, +, 1}_1, or in other words, this is
the function "f (x) = x + 4", where x is the iteration count of
the loop_1. Now we have to solve the inequality "x + 4 > 10",
| c = x + 4
| }
- Example 2: Illustration of the algorithm on nested loops.
+ Example 2a: Illustration of the algorithm on nested loops.
| loop_1
| a = phi (1, b)
a -> {1, +, 32}_1
c -> {3, +, 32}_1
-
+
+ Example 2b: Multivariate chains of recurrences.
+
+ | loop_1
+ | k = phi (0, k + 1)
+ | loop_2 4 times
+ | j = phi (0, j + 1)
+ | loop_3 4 times
+ | i = phi (0, i + 1)
+ | A[j + k] = ...
+ | endloop
+ | endloop
+ | endloop
+
+ Analyzing the access function of array A with
+ instantiate_parameters (loop_1, "j + k"), we obtain the
+ instantiation and the analysis of the scalar variables "j" and "k"
+ in loop_1. This leads to the scalar evolution {4, +, 1}_1: the end
+ 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.
+
Example 3: Higher degree polynomials.
| loop_1
c -> {5, +, a}_1
d -> {5 + a, +, a}_1
- instantiate_parameters ({5, +, a}_1) -> {5, +, 2, +, 1}_1
- instantiate_parameters ({5 + a, +, a}_1) -> {7, +, 3, +, 1}_1
+ instantiate_parameters (loop_1, {5, +, a}_1) -> {5, +, 2, +, 1}_1
+ instantiate_parameters (loop_1, {5 + a, +, a}_1) -> {7, +, 3, +, 1}_1
Example 4: Lucas, Fibonacci, or mixers in general.
unsigned loop_nb = loop_containing_stmt (stmt)->num;
tree chrec_with_symbols = analyze_scalar_evolution (loop_nb, var);
- tree chrec_instantiated = instantiate_parameters
- (loop_nb, chrec_with_symbols);
+ tree chrec_instantiated = instantiate_parameters (loop, chrec_with_symbols);
*/
tree
return NULL_TREE;
}
-/* Analyze all the parameters of the chrec that were left under a symbolic form,
- with respect to LOOP. CHREC is the chrec to instantiate. CACHE is the cache
- of already instantiated values. FLAGS modify the way chrecs are
- instantiated. SIZE_EXPR is used for computing the size of the expression to
- be instantiated, and to stop if it exceeds some limit. */
+/* Analyze all the parameters of the chrec, between INSTANTIATION_LOOP
+ and EVOLUTION_LOOP, that were left under a symbolic form. CHREC is
+ the scalar evolution to instantiate. CACHE is the cache of already
+ instantiated values. FLAGS modify the way chrecs are instantiated.
+ SIZE_EXPR is used for computing the size of the expression to be
+ instantiated, and to stop if it exceeds some limit. */
/* Values for FLAGS. */
enum
};
static tree
-instantiate_parameters_1 (struct loop *loop, tree chrec, int flags, htab_t cache,
- int size_expr)
+instantiate_scev_1 (struct loop *instantiation_loop,
+ struct loop *evolution_loop, tree chrec,
+ int flags, htab_t cache, int size_expr)
{
tree res, op0, op1, op2;
basic_block def_bb;
if (!def_bb
|| loop_depth (def_bb->loop_father) == 0
|| (!(flags & INSERT_SUPERLOOP_CHRECS)
- && !flow_bb_inside_loop_p (loop, def_bb)))
+ && !flow_bb_inside_loop_p (instantiation_loop, def_bb)))
return chrec;
/* We cache the value of instantiated variable to avoid exponential
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 (loop, def_bb) ? chrec : chrec_dont_know;
+ 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_parameters_1
+ /* 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_parameters_1 again.
+ 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;
- def_loop = find_common_loop (loop, def_bb->loop_father);
+ def_loop = find_common_loop (evolution_loop, def_bb->loop_father);
/* If the analysis yields a parametric chrec, instantiate the
result again. */
}
else if (res != chrec_dont_know)
- res = instantiate_parameters_1 (loop, res, flags, cache, size_expr);
+ res = instantiate_scev_1 (instantiation_loop, evolution_loop, res,
+ flags, cache, size_expr);
bitmap_clear_bit (already_instantiated, SSA_NAME_VERSION (chrec));
return res;
case POLYNOMIAL_CHREC:
- op0 = instantiate_parameters_1 (loop, CHREC_LEFT (chrec),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ CHREC_LEFT (chrec), flags, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
- op1 = instantiate_parameters_1 (loop, CHREC_RIGHT (chrec),
- flags, cache, size_expr);
+ op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ CHREC_RIGHT (chrec), flags, cache, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
- op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 0), flags, cache,
+ size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
- op1 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 1),
- flags, cache, size_expr);
+ op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 1), flags, cache,
+ size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
return chrec;
case MINUS_EXPR:
- op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 0), flags, cache,
+ size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
- op1 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 1),
- flags, cache, size_expr);
+ op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 1),
+ flags, cache, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
return chrec;
case MULT_EXPR:
- op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 0),
+ flags, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
- op1 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 1),
- flags, cache, size_expr);
+ op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 1),
+ flags, cache, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
return chrec;
CASE_CONVERT:
- op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 0),
+ flags, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
switch (TREE_CODE_LENGTH (TREE_CODE (chrec)))
{
case 3:
- op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 0),
+ flags, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
- op1 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 1),
- flags, cache, size_expr);
+ op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 1),
+ flags, cache, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
- op2 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 2),
- flags, cache, size_expr);
+ op2 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 2),
+ flags, cache, size_expr);
if (op2 == chrec_dont_know)
return chrec_dont_know;
TREE_TYPE (chrec), op0, op1, op2);
case 2:
- op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 0),
+ flags, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
- op1 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 1),
- flags, cache, size_expr);
+ op1 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 1),
+ flags, cache, size_expr);
if (op1 == chrec_dont_know)
return chrec_dont_know;
return fold_build2 (TREE_CODE (chrec), TREE_TYPE (chrec), op0, op1);
case 1:
- op0 = instantiate_parameters_1 (loop, TREE_OPERAND (chrec, 0),
- flags, cache, size_expr);
+ op0 = instantiate_scev_1 (instantiation_loop, evolution_loop,
+ TREE_OPERAND (chrec, 0),
+ flags, cache, size_expr);
if (op0 == chrec_dont_know)
return chrec_dont_know;
if (op0 == TREE_OPERAND (chrec, 0))
}
/* 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. */
+ 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. */
tree
-instantiate_parameters (struct loop *loop,
- tree chrec)
+instantiate_scev (struct loop *instantiation_loop, struct loop *evolution_loop,
+ tree chrec)
{
tree res;
htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info);
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "(instantiate_parameters \n");
- fprintf (dump_file, " (loop_nb = %d)\n", loop->num);
+ fprintf (dump_file, "(instantiate_scev \n");
+ fprintf (dump_file, " (instantiation_loop = %d)\n", instantiation_loop->num);
+ 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_parameters_1 (loop, chrec, INSERT_SUPERLOOP_CHRECS, cache,
- 0);
+ res = instantiate_scev_1 (instantiation_loop, evolution_loop, chrec,
+ INSERT_SUPERLOOP_CHRECS, cache, 0);
if (dump_file && (dump_flags & TDF_DETAILS))
{
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_parameters_1 (loop, chrec, FOLD_CONVERSIONS, cache, 0);
+ tree ret = instantiate_scev_1 (loop, loop, chrec, FOLD_CONVERSIONS, cache, 0);
htab_delete (cache);
return ret;
}
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
if (is_gimple_reg (PHI_RESULT (phi)))
{
- chrec = instantiate_parameters
+ chrec = instantiate_parameters
(loop,
analyze_scalar_evolution (loop, PHI_RESULT (phi)));