aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-data-ref.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-data-ref.c')
-rw-r--r--gcc/tree-data-ref.c728
1 files changed, 644 insertions, 84 deletions
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index b6750ee..7eadde7 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -1,5 +1,5 @@
/* Data references and dependences detectors.
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Sebastian Pop <pop@cri.ensmp.fr>
This file is part of GCC.
@@ -125,10 +125,6 @@ static struct datadep_stats
static tree object_analysis (tree, tree, bool, struct data_reference **,
tree *, tree *, tree *, tree *, tree *,
struct ptr_info_def **, subvar_t *);
-static struct data_reference * init_data_ref (tree, tree, tree, tree, bool,
- tree, tree, tree, tree, tree,
- struct ptr_info_def *,
- enum data_ref_type);
static bool subscript_dependence_tester_1 (struct data_dependence_relation *,
struct data_reference *,
struct data_reference *);
@@ -832,6 +828,7 @@ dump_data_dependence_relation (FILE *outf,
dump_subscript (outf, DDR_SUBSCRIPT (ddr, i));
}
+ fprintf (outf, " inner loop index: %d\n", DDR_INNER_LOOP (ddr));
fprintf (outf, " loop nest: (");
for (i = 0; VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
fprintf (outf, "%d ", loopi->num);
@@ -985,27 +982,24 @@ analyze_array_indexes (struct loop *loop,
set to true when REF is in the right hand side of an
assignment. */
-struct data_reference *
-analyze_array (tree stmt, tree ref, bool is_read)
+static struct data_reference *
+init_array_ref (tree stmt, tree ref, bool is_read)
{
- struct data_reference *res;
- VEC(tree,heap) *acc_fns;
+ struct loop *loop = loop_containing_stmt (stmt);
+ VEC(tree,heap) *acc_fns = VEC_alloc (tree, heap, 3);
+ struct data_reference *res = XNEW (struct data_reference);;
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "(analyze_array \n");
+ fprintf (dump_file, "(init_array_ref \n");
fprintf (dump_file, " (ref = ");
print_generic_stmt (dump_file, ref, 0);
fprintf (dump_file, ")\n");
}
- res = XNEW (struct data_reference);
-
DR_STMT (res) = stmt;
DR_REF (res) = ref;
- acc_fns = VEC_alloc (tree, heap, 3);
- DR_BASE_OBJECT (res) = analyze_array_indexes
- (loop_containing_stmt (stmt), &acc_fns, ref, stmt);
+ DR_BASE_OBJECT (res) = analyze_array_indexes (loop, &acc_fns, ref, stmt);
DR_TYPE (res) = ARRAY_REF_TYPE;
DR_SET_ACCESS_FNS (res, acc_fns);
DR_IS_READ (res) = is_read;
@@ -1023,6 +1017,45 @@ analyze_array (tree stmt, tree ref, bool is_read)
return res;
}
+/* For a data reference REF contained in the statement STMT, initialize
+ a DATA_REFERENCE structure, and return it. */
+
+static struct data_reference *
+init_pointer_ref (tree stmt, tree ref, tree access_fn, bool is_read,
+ tree base_address, tree step, struct ptr_info_def *ptr_info)
+{
+ struct data_reference *res = XNEW (struct data_reference);
+ VEC(tree,heap) *acc_fns = VEC_alloc (tree, heap, 3);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "(init_pointer_ref \n");
+ fprintf (dump_file, " (ref = ");
+ print_generic_stmt (dump_file, ref, 0);
+ fprintf (dump_file, ")\n");
+ }
+
+ DR_STMT (res) = stmt;
+ DR_REF (res) = ref;
+ DR_BASE_OBJECT (res) = NULL_TREE;
+ DR_TYPE (res) = POINTER_REF_TYPE;
+ DR_SET_ACCESS_FNS (res, acc_fns);
+ VEC_quick_push (tree, DR_ACCESS_FNS (res), access_fn);
+ DR_IS_READ (res) = is_read;
+ DR_BASE_ADDRESS (res) = base_address;
+ DR_OFFSET (res) = NULL_TREE;
+ DR_INIT (res) = NULL_TREE;
+ DR_STEP (res) = step;
+ DR_OFFSET_MISALIGNMENT (res) = NULL_TREE;
+ DR_MEMTAG (res) = NULL_TREE;
+ DR_PTR_INFO (res) = ptr_info;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, ")\n");
+
+ return res;
+}
+
/* Analyze an indirect memory reference, REF, that comes from STMT.
IS_READ is true if this is an indirect load, and false if it is
an indirect store.
@@ -1063,7 +1096,7 @@ analyze_indirect_ref (tree stmt, tree ref, bool is_read)
if (!expr_invariant_in_loop_p (loop, init))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
+ if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\ninitial condition is not loop invariant.\n");
}
else
@@ -1087,61 +1120,8 @@ analyze_indirect_ref (tree stmt, tree ref, bool is_read)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\nunknown evolution of ptr.\n");
}
- return init_data_ref (stmt, ref, NULL_TREE, access_fn, is_read, base_address,
- NULL_TREE, step, NULL_TREE, NULL_TREE,
- ptr_info, POINTER_REF_TYPE);
-}
-
-/* For a data reference REF contained in the statement STMT, initialize
- a DATA_REFERENCE structure, and return it. */
-
-struct data_reference *
-init_data_ref (tree stmt,
- tree ref,
- tree base,
- tree access_fn,
- bool is_read,
- tree base_address,
- tree init_offset,
- tree step,
- tree misalign,
- tree memtag,
- struct ptr_info_def *ptr_info,
- enum data_ref_type type)
-{
- struct data_reference *res;
- VEC(tree,heap) *acc_fns;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "(init_data_ref \n");
- fprintf (dump_file, " (ref = ");
- print_generic_stmt (dump_file, ref, 0);
- fprintf (dump_file, ")\n");
- }
-
- res = XNEW (struct data_reference);
-
- DR_STMT (res) = stmt;
- DR_REF (res) = ref;
- DR_BASE_OBJECT (res) = base;
- DR_TYPE (res) = type;
- acc_fns = VEC_alloc (tree, heap, 3);
- DR_SET_ACCESS_FNS (res, acc_fns);
- VEC_quick_push (tree, DR_ACCESS_FNS (res), access_fn);
- DR_IS_READ (res) = is_read;
- DR_BASE_ADDRESS (res) = base_address;
- DR_OFFSET (res) = init_offset;
- DR_INIT (res) = NULL_TREE;
- DR_STEP (res) = step;
- DR_OFFSET_MISALIGNMENT (res) = misalign;
- DR_MEMTAG (res) = memtag;
- DR_PTR_INFO (res) = ptr_info;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, ")\n");
-
- return res;
+ return init_pointer_ref (stmt, ref, access_fn, is_read, base_address,
+ step, ptr_info);
}
/* Function strip_conversions
@@ -1598,7 +1578,7 @@ object_analysis (tree memref, tree stmt, bool is_read,
if (!(*dr))
{
if (TREE_CODE (memref) == ARRAY_REF)
- *dr = analyze_array (stmt, memref, is_read);
+ *dr = init_array_ref (stmt, memref, is_read);
else if (TREE_CODE (memref) == COMPONENT_REF)
comp_ref = memref;
else
@@ -1671,7 +1651,7 @@ object_analysis (tree memref, tree stmt, bool is_read,
{
if (comp_ref && TREE_CODE (TREE_OPERAND (comp_ref, 0)) == ARRAY_REF)
{
- *dr = analyze_array (stmt, TREE_OPERAND (comp_ref, 0), is_read);
+ *dr = init_array_ref (stmt, TREE_OPERAND (comp_ref, 0), is_read);
if (DR_NUM_DIMENSIONS (*dr) != 1)
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2302,6 +2282,7 @@ initialize_data_dependence_relation (struct data_reference *a,
DDR_ARE_DEPENDENT (res) = NULL_TREE;
DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a));
DDR_LOOP_NEST (res) = loop_nest;
+ DDR_INNER_LOOP (res) = 0;
DDR_DIR_VECTS (res) = NULL;
DDR_DIST_VECTS (res) = NULL;
@@ -4176,10 +4157,10 @@ static bool
access_functions_are_affine_or_constant_p (struct data_reference *a)
{
unsigned int i;
- VEC(tree,heap) **fns = DR_ACCESS_FNS_ADDR (a);
+ VEC(tree,heap) *fns = DR_ACCESS_FNS (a);
tree t;
-
- for (i = 0; VEC_iterate (tree, *fns, i, t); i++)
+
+ for (i = 0; VEC_iterate (tree, fns, i, t); i++)
if (!evolution_function_is_constant_p (t)
&& !evolution_function_is_affine_multivariate_p (t))
return false;
@@ -4187,6 +4168,530 @@ access_functions_are_affine_or_constant_p (struct data_reference *a)
return true;
}
+/* Initializes an equation for an OMEGA problem using the information
+ contained in the ACCESS_FUN. Returns true when the operation
+ succeeded.
+
+ PB is the omega constraint system.
+ EQ is the number of the equation to be initialized.
+ OFFSET is used for shifting the variables names in the constraints:
+ a constrain is composed of 2 * the number of variables surrounding
+ dependence accesses. OFFSET is set either to 0 for the first n variables,
+ then it is set to n.
+ ACCESS_FUN is expected to be an affine chrec. */
+
+static bool
+init_omega_eq_with_af (omega_pb pb, unsigned eq,
+ unsigned int offset, tree access_fun,
+ struct data_dependence_relation *ddr)
+{
+ switch (TREE_CODE (access_fun))
+ {
+ case POLYNOMIAL_CHREC:
+ {
+ tree left = CHREC_LEFT (access_fun);
+ tree right = CHREC_RIGHT (access_fun);
+ int var = CHREC_VARIABLE (access_fun);
+ unsigned var_idx;
+
+ if (TREE_CODE (right) != INTEGER_CST)
+ return false;
+
+ var_idx = index_in_loop_nest (var, DDR_LOOP_NEST (ddr));
+ pb->eqs[eq].coef[offset + var_idx + 1] = int_cst_value (right);
+
+ /* Compute the innermost loop index. */
+ DDR_INNER_LOOP (ddr) = MAX (DDR_INNER_LOOP (ddr), var_idx);
+
+ if (offset == 0)
+ pb->eqs[eq].coef[var_idx + DDR_NB_LOOPS (ddr) + 1]
+ += int_cst_value (right);
+
+ switch (TREE_CODE (left))
+ {
+ case POLYNOMIAL_CHREC:
+ return init_omega_eq_with_af (pb, eq, offset, left, ddr);
+
+ case INTEGER_CST:
+ pb->eqs[eq].coef[0] += int_cst_value (left);
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ case INTEGER_CST:
+ pb->eqs[eq].coef[0] += int_cst_value (access_fun);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* As explained in the comments preceding init_omega_for_ddr, we have
+ to set up a system for each loop level, setting outer loops
+ variation to zero, and current loop variation to positive or zero.
+ Save each lexico positive distance vector. */
+
+static void
+omega_extract_distance_vectors (omega_pb pb,
+ struct data_dependence_relation *ddr)
+{
+ int eq, geq;
+ unsigned i, j;
+ struct loop *loopi, *loopj;
+ enum omega_result res;
+
+ /* Set a new problem for each loop in the nest. The basis is the
+ problem that we have initialized until now. On top of this we
+ add new constraints. */
+ for (i = 0; i <= DDR_INNER_LOOP (ddr)
+ && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
+ {
+ int dist = 0;
+ omega_pb copy = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr),
+ DDR_NB_LOOPS (ddr));
+
+ omega_copy_problem (copy, pb);
+
+ /* For all the outer loops "loop_j", add "dj = 0". */
+ for (j = 0;
+ j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++)
+ {
+ eq = omega_add_zero_eq (copy, omega_black);
+ copy->eqs[eq].coef[j + 1] = 1;
+ }
+
+ /* For "loop_i", add "0 <= di". */
+ geq = omega_add_zero_geq (copy, omega_black);
+ copy->geqs[geq].coef[i + 1] = 1;
+
+ /* Reduce the constraint system, and test that the current
+ problem is feasible. */
+ res = omega_simplify_problem (copy);
+ if (res == omega_false
+ || res == omega_unknown
+ || copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
+ goto next_problem;
+
+ for (eq = 0; eq < copy->num_subs; eq++)
+ if (copy->subs[eq].key == (int) i + 1)
+ {
+ dist = copy->subs[eq].coef[0];
+ goto found_dist;
+ }
+
+ if (dist == 0)
+ {
+ /* Reinitialize problem... */
+ omega_copy_problem (copy, pb);
+ for (j = 0;
+ j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++)
+ {
+ eq = omega_add_zero_eq (copy, omega_black);
+ copy->eqs[eq].coef[j + 1] = 1;
+ }
+
+ /* ..., but this time "di = 1". */
+ eq = omega_add_zero_eq (copy, omega_black);
+ copy->eqs[eq].coef[i + 1] = 1;
+ copy->eqs[eq].coef[0] = -1;
+
+ res = omega_simplify_problem (copy);
+ if (res == omega_false
+ || res == omega_unknown
+ || copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
+ goto next_problem;
+
+ for (eq = 0; eq < copy->num_subs; eq++)
+ if (copy->subs[eq].key == (int) i + 1)
+ {
+ dist = copy->subs[eq].coef[0];
+ goto found_dist;
+ }
+ }
+
+ found_dist:;
+ /* Save the lexicographically positive distance vector. */
+ if (dist >= 0)
+ {
+ lambda_vector dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
+ lambda_vector dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
+
+ dist_v[i] = dist;
+
+ for (eq = 0; eq < copy->num_subs; eq++)
+ if (copy->subs[eq].key > 0)
+ {
+ dist = copy->subs[eq].coef[0];
+ dist_v[copy->subs[eq].key - 1] = dist;
+ }
+
+ for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
+ dir_v[j] = dir_from_dist (dist_v[j]);
+
+ save_dist_v (ddr, dist_v);
+ save_dir_v (ddr, dir_v);
+ }
+
+ next_problem:;
+ omega_free_problem (copy);
+ }
+}
+
+/* This is called for each subscript of a tuple of data references:
+ insert an equality for representing the conflicts. */
+
+static bool
+omega_setup_subscript (tree access_fun_a, tree access_fun_b,
+ struct data_dependence_relation *ddr,
+ omega_pb pb, bool *maybe_dependent)
+{
+ int eq;
+ tree fun_a = chrec_convert (integer_type_node, access_fun_a, NULL_TREE);
+ tree fun_b = chrec_convert (integer_type_node, access_fun_b, NULL_TREE);
+ tree difference = chrec_fold_minus (integer_type_node, fun_a, fun_b);
+
+ /* When the fun_a - fun_b is not constant, the dependence is not
+ captured by the classic distance vector representation. */
+ if (TREE_CODE (difference) != INTEGER_CST)
+ return false;
+
+ /* ZIV test. */
+ if (ziv_subscript_p (fun_a, fun_b) && !integer_zerop (difference))
+ {
+ /* There is no dependence. */
+ *maybe_dependent = false;
+ return true;
+ }
+
+ fun_b = chrec_fold_multiply (integer_type_node, fun_b,
+ integer_minus_one_node);
+
+ eq = omega_add_zero_eq (pb, omega_black);
+ if (!init_omega_eq_with_af (pb, eq, DDR_NB_LOOPS (ddr), fun_a, ddr)
+ || !init_omega_eq_with_af (pb, eq, 0, fun_b, ddr))
+ /* There is probably a dependence, but the system of
+ constraints cannot be built: answer "don't know". */
+ return false;
+
+ /* GCD test. */
+ if (DDR_NB_LOOPS (ddr) != 0 && pb->eqs[eq].coef[0]
+ && !int_divides_p (lambda_vector_gcd
+ ((lambda_vector) &(pb->eqs[eq].coef[1]),
+ 2 * DDR_NB_LOOPS (ddr)),
+ pb->eqs[eq].coef[0]))
+ {
+ /* There is no dependence. */
+ *maybe_dependent = false;
+ return true;
+ }
+
+ return true;
+}
+
+/* Helper function, same as init_omega_for_ddr but specialized for
+ data references A and B. */
+
+static bool
+init_omega_for_ddr_1 (struct data_reference *dra, struct data_reference *drb,
+ struct data_dependence_relation *ddr,
+ omega_pb pb, bool *maybe_dependent)
+{
+ unsigned i;
+ int ineq;
+ struct loop *loopi;
+ unsigned nb_loops = DDR_NB_LOOPS (ddr);
+
+ /* Insert an equality per subscript. */
+ for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
+ {
+ if (!omega_setup_subscript (DR_ACCESS_FN (dra, i), DR_ACCESS_FN (drb, i),
+ ddr, pb, maybe_dependent))
+ return false;
+ else if (*maybe_dependent == false)
+ {
+ /* There is no dependence. */
+ DDR_ARE_DEPENDENT (ddr) = chrec_known;
+ return true;
+ }
+ }
+
+ /* Insert inequalities: constraints corresponding to the iteration
+ domain, i.e. the loops surrounding the references "loop_x" and
+ the distance variables "dx". The layout of the OMEGA
+ representation is as follows:
+ - coef[0] is the constant
+ - coef[1..nb_loops] are the protected variables that will not be
+ removed by the solver: the "dx"
+ - coef[nb_loops + 1, 2*nb_loops] are the loop variables: "loop_x".
+ */
+ for (i = 0; i <= DDR_INNER_LOOP (ddr)
+ && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
+ {
+ HOST_WIDE_INT nbi = estimated_loop_iterations_int (loopi, true);
+
+ /* 0 <= loop_x */
+ ineq = omega_add_zero_geq (pb, omega_black);
+ pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
+
+ /* 0 <= loop_x + dx */
+ ineq = omega_add_zero_geq (pb, omega_black);
+ pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
+ pb->geqs[ineq].coef[i + 1] = 1;
+
+ if (nbi != -1)
+ {
+ /* loop_x <= nb_iters */
+ ineq = omega_add_zero_geq (pb, omega_black);
+ pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
+ pb->geqs[ineq].coef[0] = nbi;
+
+ /* loop_x + dx <= nb_iters */
+ ineq = omega_add_zero_geq (pb, omega_black);
+ pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
+ pb->geqs[ineq].coef[i + 1] = -1;
+ pb->geqs[ineq].coef[0] = nbi;
+
+ /* A step "dx" bigger than nb_iters is not feasible, so
+ add "0 <= nb_iters + dx", */
+ ineq = omega_add_zero_geq (pb, omega_black);
+ pb->geqs[ineq].coef[i + 1] = 1;
+ pb->geqs[ineq].coef[0] = nbi;
+ /* and "dx <= nb_iters". */
+ ineq = omega_add_zero_geq (pb, omega_black);
+ pb->geqs[ineq].coef[i + 1] = -1;
+ pb->geqs[ineq].coef[0] = nbi;
+ }
+ }
+
+ omega_extract_distance_vectors (pb, ddr);
+
+ return true;
+}
+
+/* Sets up the Omega dependence problem for the data dependence
+ relation DDR. Returns false when the constraint system cannot be
+ built, ie. when the test answers "don't know". Returns true
+ otherwise, and when independence has been proved (using one of the
+ trivial dependence test), set MAYBE_DEPENDENT to false, otherwise
+ set MAYBE_DEPENDENT to true.
+
+ Example: for setting up the dependence system corresponding to the
+ conflicting accesses
+
+ | loop_i
+ | loop_j
+ | A[i, i+1] = ...
+ | ... A[2*j, 2*(i + j)]
+ | endloop_j
+ | endloop_i
+
+ the following constraints come from the iteration domain:
+
+ 0 <= i <= Ni
+ 0 <= i + di <= Ni
+ 0 <= j <= Nj
+ 0 <= j + dj <= Nj
+
+ where di, dj are the distance variables. The constraints
+ representing the conflicting elements are:
+
+ i = 2 * (j + dj)
+ i + 1 = 2 * (i + di + j + dj)
+
+ For asking that the resulting distance vector (di, dj) be
+ lexicographically positive, we insert the constraint "di >= 0". If
+ "di = 0" in the solution, we fix that component to zero, and we
+ look at the inner loops: we set a new problem where all the outer
+ loop distances are zero, and fix this inner component to be
+ positive. When one of the components is positive, we save that
+ distance, and set a new problem where the distance on this loop is
+ zero, searching for other distances in the inner loops. Here is
+ the classic example that illustrates that we have to set for each
+ inner loop a new problem:
+
+ | loop_1
+ | loop_2
+ | A[10]
+ | endloop_2
+ | endloop_1
+
+ we have to save two distances (1, 0) and (0, 1).
+
+ Given two array references, refA and refB, we have to set the
+ dependence problem twice, refA vs. refB and refB vs. refA, and we
+ cannot do a single test, as refB might occur before refA in the
+ inner loops, and the contrary when considering outer loops: ex.
+
+ | loop_0
+ | loop_1
+ | loop_2
+ | T[{1,+,1}_2][{1,+,1}_1] // refA
+ | T[{2,+,1}_2][{0,+,1}_1] // refB
+ | endloop_2
+ | endloop_1
+ | endloop_0
+
+ refB touches the elements in T before refA, and thus for the same
+ loop_0 refB precedes refA: ie. the distance vector (0, 1, -1)
+ but for successive loop_0 iterations, we have (1, -1, 1)
+
+ The Omega solver expects the distance variables ("di" in the
+ previous example) to come first in the constraint system (as
+ variables to be protected, or "safe" variables), the constraint
+ system is built using the following layout:
+
+ "cst | distance vars | index vars".
+*/
+
+static bool
+init_omega_for_ddr (struct data_dependence_relation *ddr,
+ bool *maybe_dependent)
+{
+ omega_pb pb;
+ bool res = false;
+
+ *maybe_dependent = true;
+
+ if (same_access_functions (ddr))
+ {
+ unsigned j;
+ lambda_vector dir_v;
+
+ /* Save the 0 vector. */
+ save_dist_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
+ dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
+ for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
+ dir_v[j] = dir_equal;
+ save_dir_v (ddr, dir_v);
+
+ /* Save the dependences carried by outer loops. */
+ pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
+ res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
+ maybe_dependent);
+ omega_free_problem (pb);
+ return res;
+ }
+
+ /* Omega expects the protected variables (those that have to be kept
+ after elimination) to appear first in the constraint system.
+ These variables are the distance variables. In the following
+ initialization we declare NB_LOOPS safe variables, and the total
+ number of variables for the constraint system is 2*NB_LOOPS. */
+ pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
+ res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
+ maybe_dependent);
+ omega_free_problem (pb);
+
+ /* Stop computation if not decidable, or no dependence. */
+ if (res == false || *maybe_dependent == false)
+ return res;
+
+ pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
+ res = init_omega_for_ddr_1 (DDR_B (ddr), DDR_A (ddr), ddr, pb,
+ maybe_dependent);
+ omega_free_problem (pb);
+
+ return res;
+}
+
+/* Return true when DDR contains the same information as that stored
+ in DIR_VECTS and in DIST_VECTS, return false otherwise. */
+
+static bool
+ddr_consistent_p (FILE *file,
+ struct data_dependence_relation *ddr,
+ VEC (lambda_vector, heap) *dist_vects,
+ VEC (lambda_vector, heap) *dir_vects)
+{
+ unsigned int i, j;
+
+ /* If dump_file is set, output there. */
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ file = dump_file;
+
+ if (VEC_length (lambda_vector, dist_vects) != DDR_NUM_DIST_VECTS (ddr))
+ {
+ lambda_vector b_dist_v;
+ fprintf (file, "\n(Number of distance vectors differ: Banerjee has %d, Omega has %d.\n",
+ VEC_length (lambda_vector, dist_vects),
+ DDR_NUM_DIST_VECTS (ddr));
+
+ fprintf (file, "Banerjee dist vectors:\n");
+ for (i = 0; VEC_iterate (lambda_vector, dist_vects, i, b_dist_v); i++)
+ print_lambda_vector (file, b_dist_v, DDR_NB_LOOPS (ddr));
+
+ fprintf (file, "Omega dist vectors:\n");
+ for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
+ print_lambda_vector (file, DDR_DIST_VECT (ddr, i), DDR_NB_LOOPS (ddr));
+
+ fprintf (file, "data dependence relation:\n");
+ dump_data_dependence_relation (file, ddr);
+
+ fprintf (file, ")\n");
+ return false;
+ }
+
+ if (VEC_length (lambda_vector, dir_vects) != DDR_NUM_DIR_VECTS (ddr))
+ {
+ fprintf (file, "\n(Number of direction vectors differ: Banerjee has %d, Omega has %d.)\n",
+ VEC_length (lambda_vector, dir_vects),
+ DDR_NUM_DIR_VECTS (ddr));
+ return false;
+ }
+
+ for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
+ {
+ lambda_vector a_dist_v;
+ lambda_vector b_dist_v = DDR_DIST_VECT (ddr, i);
+
+ /* Distance vectors are not ordered in the same way in the DDR
+ and in the DIST_VECTS: search for a matching vector. */
+ for (j = 0; VEC_iterate (lambda_vector, dist_vects, j, a_dist_v); j++)
+ if (lambda_vector_equal (a_dist_v, b_dist_v, DDR_NB_LOOPS (ddr)))
+ break;
+
+ if (j == VEC_length (lambda_vector, dist_vects))
+ {
+ fprintf (file, "\n(Dist vectors from the first dependence analyzer:\n");
+ print_dist_vectors (file, dist_vects, DDR_NB_LOOPS (ddr));
+ fprintf (file, "not found in Omega dist vectors:\n");
+ print_dist_vectors (file, DDR_DIST_VECTS (ddr), DDR_NB_LOOPS (ddr));
+ fprintf (file, "data dependence relation:\n");
+ dump_data_dependence_relation (file, ddr);
+ fprintf (file, ")\n");
+ }
+ }
+
+ for (i = 0; i < DDR_NUM_DIR_VECTS (ddr); i++)
+ {
+ lambda_vector a_dir_v;
+ lambda_vector b_dir_v = DDR_DIR_VECT (ddr, i);
+
+ /* Direction vectors are not ordered in the same way in the DDR
+ and in the DIR_VECTS: search for a matching vector. */
+ for (j = 0; VEC_iterate (lambda_vector, dir_vects, j, a_dir_v); j++)
+ if (lambda_vector_equal (a_dir_v, b_dir_v, DDR_NB_LOOPS (ddr)))
+ break;
+
+ if (j == VEC_length (lambda_vector, dist_vects))
+ {
+ fprintf (file, "\n(Dir vectors from the first dependence analyzer:\n");
+ print_dir_vectors (file, dir_vects, DDR_NB_LOOPS (ddr));
+ fprintf (file, "not found in Omega dir vectors:\n");
+ print_dir_vectors (file, DDR_DIR_VECTS (ddr), DDR_NB_LOOPS (ddr));
+ fprintf (file, "data dependence relation:\n");
+ dump_data_dependence_relation (file, ddr);
+ fprintf (file, ")\n");
+ }
+ }
+
+ return true;
+}
+
/* This computes the affine dependence relation between A and B.
CHREC_KNOWN is used for representing the independence between two
accesses, while CHREC_DONT_KNOW is used for representing the unknown
@@ -4219,13 +4724,57 @@ compute_affine_dependence (struct data_dependence_relation *ddr)
if (access_functions_are_affine_or_constant_p (dra)
&& access_functions_are_affine_or_constant_p (drb))
- subscript_dependence_tester (ddr);
-
+ {
+ if (flag_check_data_deps)
+ {
+ /* Compute the dependences using the first algorithm. */
+ subscript_dependence_tester (ddr);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n\nBanerjee Analyzer\n");
+ dump_data_dependence_relation (dump_file, ddr);
+ }
+
+ if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
+ {
+ bool maybe_dependent;
+ VEC (lambda_vector, heap) *dir_vects, *dist_vects;
+
+ /* Save the result of the first DD analyzer. */
+ dist_vects = DDR_DIST_VECTS (ddr);
+ dir_vects = DDR_DIR_VECTS (ddr);
+
+ /* Reset the information. */
+ DDR_DIST_VECTS (ddr) = NULL;
+ DDR_DIR_VECTS (ddr) = NULL;
+
+ /* Compute the same information using Omega. */
+ if (!init_omega_for_ddr (ddr, &maybe_dependent))
+ goto csys_dont_know;
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Omega Analyzer\n");
+ dump_data_dependence_relation (dump_file, ddr);
+ }
+
+ /* Check that we get the same information. */
+ if (maybe_dependent)
+ gcc_assert (ddr_consistent_p (stderr, ddr, dist_vects,
+ dir_vects));
+ }
+ }
+ else
+ subscript_dependence_tester (ddr);
+ }
+
/* As a last case, if the dependence cannot be determined, or if
the dependence is considered too difficult to determine, answer
"don't know". */
else
{
+ csys_dont_know:;
dependence_stats.num_dependence_undetermined++;
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4584,7 +5133,7 @@ compute_data_dependences_for_loop (struct loop *loop,
}
/* Entry point (for testing only). Analyze all the data references
- and the dependence relations.
+ and the dependence relations in LOOP.
The data references are computed first.
@@ -4604,9 +5153,8 @@ compute_data_dependences_for_loop (struct loop *loop,
recompute the same information. The implementation of this KB is
transparent to the optimizer, and thus the KB can be changed with a
more efficient implementation, or the KB could be disabled. */
-#if 0
static void
-analyze_all_data_dependences (struct loops *loops)
+analyze_all_data_dependences (struct loop *loop)
{
unsigned int i;
int nb_data_refs = 10;
@@ -4616,8 +5164,8 @@ analyze_all_data_dependences (struct loops *loops)
VEC_alloc (ddr_p, heap, nb_data_refs * nb_data_refs);
/* Compute DDs on the whole function. */
- compute_data_dependences_for_loop (loops->parray[0], false,
- &datarefs, &dependence_relations);
+ compute_data_dependences_for_loop (loop, false, &datarefs,
+ &dependence_relations);
if (dump_file)
{
@@ -4666,7 +5214,19 @@ analyze_all_data_dependences (struct loops *loops)
free_dependence_relations (dependence_relations);
free_data_refs (datarefs);
}
-#endif
+
+/* Computes all the data dependences and check that the results of
+ several analyzers are the same. */
+
+void
+tree_check_data_deps (void)
+{
+ loop_iterator li;
+ struct loop *loop_nest;
+
+ FOR_EACH_LOOP (li, loop_nest, 0)
+ analyze_all_data_dependences (loop_nest);
+}
/* Free the memory used by a data dependence relation DDR. */