#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "errors.h"
#include "ggc.h"
#include "tree.h"
\f
-/* Compute the lowest iteration bound for LOOP. It is an
- INTEGER_CST. */
+/* Initialize LOOP->ESTIMATED_NB_ITERATIONS with the lowest safe
+ approximation of the number of iterations for LOOP. */
static void
compute_estimated_nb_iterations (struct loop *loop)
{
- tree estimation;
- struct nb_iter_bound *bound, *next;
-
- for (bound = loop->bounds; bound; bound = next)
- {
- next = bound->next;
- estimation = bound->bound;
-
- if (TREE_CODE (estimation) != INTEGER_CST)
- continue;
-
- if (loop->estimated_nb_iterations)
- {
- /* Update only if estimation is smaller. */
- if (tree_int_cst_lt (estimation, loop->estimated_nb_iterations))
- loop->estimated_nb_iterations = estimation;
- }
- else
- loop->estimated_nb_iterations = estimation;
- }
+ struct nb_iter_bound *bound;
+
+ for (bound = loop->bounds; bound; bound = bound->next)
+ if (TREE_CODE (bound->bound) == INTEGER_CST
+ /* Update only when there is no previous estimation. */
+ && (chrec_contains_undetermined (loop->estimated_nb_iterations)
+ /* Or when the current estimation is smaller. */
+ || tree_int_cst_lt (bound->bound, loop->estimated_nb_iterations)))
+ loop->estimated_nb_iterations = bound->bound;
}
/* Estimate the number of iterations from the size of the data and the
access_fn = instantiate_parameters
(loop, analyze_scalar_evolution (loop, opnd1));
- if (loop->estimated_nb_iterations == NULL_TREE)
+ if (chrec_contains_undetermined (loop->estimated_nb_iterations))
estimate_niter_from_size_of_data (loop, opnd0, access_fn, stmt);
VEC_safe_push (tree, heap, *access_fns, access_fn);
numiter_z = current_loops->parray[CHREC_VARIABLE (chrec_b)]
->estimated_nb_iterations;
- if (numiter_x == NULL_TREE || numiter_y == NULL_TREE
- || numiter_z == NULL_TREE)
+ if (chrec_contains_undetermined (numiter_x)
+ || chrec_contains_undetermined (numiter_y)
+ || chrec_contains_undetermined (numiter_z)
+ || TREE_CODE (numiter_x) != INTEGER_CST
+ || TREE_CODE (numiter_y) != INTEGER_CST
+ || TREE_CODE (numiter_z) != INTEGER_CST)
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
if (TREE_CODE (numiter_b) != INTEGER_CST)
numiter_b = current_loops->parray[CHREC_VARIABLE (chrec_b)]
->estimated_nb_iterations;
- if (numiter_a == NULL_TREE || numiter_b == NULL_TREE)
+ if (chrec_contains_undetermined (numiter_a)
+ || chrec_contains_undetermined (numiter_b)
+ || TREE_CODE (numiter_a) != INTEGER_CST
+ || TREE_CODE (numiter_b) != INTEGER_CST)
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
if (TREE_CODE (numiter_b) != INTEGER_CST)
numiter_b = current_loops->parray[CHREC_VARIABLE (chrec_b)]
->estimated_nb_iterations;
- if (numiter_a == NULL_TREE || numiter_b == NULL_TREE)
+ if (chrec_contains_undetermined (numiter_a)
+ || chrec_contains_undetermined (numiter_b)
+ || TREE_CODE (numiter_a) != INTEGER_CST
+ || TREE_CODE (numiter_b) != INTEGER_CST)
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
fprintf (dump_file, ")\n");
}
+/* This computes the dependence relation for the same data
+ reference into DDR. */
+
+static void
+compute_self_dependence (struct data_dependence_relation *ddr)
+{
+ unsigned int i;
+
+ for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
+ {
+ struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
+
+ /* The accessed index overlaps for each iteration. */
+ SUB_CONFLICTS_IN_A (subscript) = integer_zero_node;
+ SUB_CONFLICTS_IN_B (subscript) = integer_zero_node;
+ SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
+ }
+}
+
+
+typedef struct data_dependence_relation *ddr_p;
+DEF_VEC_P(ddr_p);
+DEF_VEC_ALLOC_P(ddr_p,heap);
+
/* Compute a subset of the data dependence relation graph. Don't
compute read-read relations, and avoid the computation of the
opposite relation, i.e. when AB has been computed, don't compute BA.
static void
compute_all_dependences (varray_type datarefs,
- varray_type *dependence_relations)
+ VEC(ddr_p,heap) **dependence_relations)
{
unsigned int i, j, N;
N = VARRAY_ACTIVE_SIZE (datarefs);
+ /* Note that we specifically skip i == j because it's a self dependence, and
+ use compute_self_dependence below. */
+
for (i = 0; i < N; i++)
- for (j = i; j < N; j++)
+ for (j = i + 1; j < N; j++)
{
struct data_reference *a, *b;
struct data_dependence_relation *ddr;
b = VARRAY_GENERIC_PTR (datarefs, j);
ddr = initialize_data_dependence_relation (a, b);
- VARRAY_PUSH_GENERIC_PTR (*dependence_relations, ddr);
+ VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
compute_affine_dependence (ddr);
compute_subscript_distance (ddr);
}
+
+ /* Compute self dependence relation of each dataref to itself. */
+
+ for (i = 0; i < N; i++)
+ {
+ struct data_reference *a, *b;
+ struct data_dependence_relation *ddr;
+
+ a = VARRAY_GENERIC_PTR (datarefs, i);
+ b = VARRAY_GENERIC_PTR (datarefs, i);
+ ddr = initialize_data_dependence_relation (a, b);
+
+ VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
+ compute_self_dependence (ddr);
+ compute_subscript_distance (ddr);
+ }
}
/* Search the data references in LOOP, and record the information into
tree
find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
{
- bool dont_know_node_not_inserted = true;
basic_block bb, *bbs;
unsigned int i;
block_stmt_iterator bsi;
{
tree stmt = bsi_stmt (bsi);
- if (TREE_CODE (stmt) != MODIFY_EXPR)
- continue;
+ /* ASM_EXPR and CALL_EXPR may embed arbitrary side effects.
+ Calls have side-effects, except those to const or pure
+ functions. */
+ if ((TREE_CODE (stmt) == CALL_EXPR
+ && !(call_expr_flags (stmt) & (ECF_CONST | ECF_PURE)))
+ || (TREE_CODE (stmt) == ASM_EXPR
+ && ASM_VOLATILE_P (stmt)))
+ goto insert_dont_know_node;
if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
continue;
-
- /* In the GIMPLE representation, a modify expression
- contains a single load or store to memory. */
- if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF)
- VARRAY_PUSH_GENERIC_PTR
- (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 0),
- false));
-
- else if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ARRAY_REF)
- VARRAY_PUSH_GENERIC_PTR
- (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 1),
- true));
- else
+
+ switch (TREE_CODE (stmt))
{
- if (dont_know_node_not_inserted)
+ case MODIFY_EXPR:
+ if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF)
+ VARRAY_PUSH_GENERIC_PTR
+ (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 0),
+ false));
+
+ if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ARRAY_REF)
+ VARRAY_PUSH_GENERIC_PTR
+ (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 1),
+ true));
+
+ if (TREE_CODE (TREE_OPERAND (stmt, 0)) != ARRAY_REF
+ && TREE_CODE (TREE_OPERAND (stmt, 1)) != ARRAY_REF)
+ goto insert_dont_know_node;
+
+ break;
+
+ case CALL_EXPR:
+ {
+ tree args;
+ bool one_inserted = false;
+
+ for (args = TREE_OPERAND (stmt, 1); args; args = TREE_CHAIN (args))
+ if (TREE_CODE (TREE_VALUE (args)) == ARRAY_REF)
+ {
+ VARRAY_PUSH_GENERIC_PTR
+ (*datarefs, analyze_array (stmt, TREE_VALUE (args), true));
+ one_inserted = true;
+ }
+
+ if (!one_inserted)
+ goto insert_dont_know_node;
+
+ break;
+ }
+
+ default:
{
struct data_reference *res;
+
+ insert_dont_know_node:;
res = xmalloc (sizeof (struct data_reference));
DR_STMT (res) = NULL_TREE;
DR_REF (res) = NULL_TREE;
DR_BASE_NAME (res) = NULL;
DR_IS_READ (res) = false;
VARRAY_PUSH_GENERIC_PTR (*datarefs, res);
- dont_know_node_not_inserted = false;
+
+ free (bbs);
+ return chrec_dont_know;
}
}
/* When there are no defs in the loop, the loop is parallel. */
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
- bb->loop_father->parallel_p = false;
+ loop->parallel_p = false;
}
- if (bb->loop_father->estimated_nb_iterations == NULL_TREE)
- compute_estimated_nb_iterations (bb->loop_father);
+ if (chrec_contains_undetermined (loop->estimated_nb_iterations))
+ compute_estimated_nb_iterations (loop);
}
free (bbs);
- return dont_know_node_not_inserted ? NULL_TREE : chrec_dont_know;
+ return NULL_TREE;
}
\f
varray_type *dependence_relations)
{
unsigned int i;
- varray_type allrelations;
+ VEC(ddr_p,heap) *allrelations;
+ struct data_dependence_relation *ddr;
/* If one of the data references is not computable, give up without
spending time to compute other dependences. */
return;
}
- VARRAY_GENERIC_PTR_INIT (allrelations, 1, "Data dependence relations");
+ allrelations = NULL;
compute_all_dependences (*datarefs, &allrelations);
- for (i = 0; i < VARRAY_ACTIVE_SIZE (allrelations); i++)
+ for (i = 0; VEC_iterate (ddr_p, allrelations, i, ddr); i++)
{
- struct data_dependence_relation *ddr;
- ddr = VARRAY_GENERIC_PTR (allrelations, i);
if (build_classic_dist_vector (ddr, nb_loops, loop->depth))
{
VARRAY_PUSH_GENERIC_PTR (*dependence_relations, ddr);