Commit 86df10e3 by Sebastian Pop Committed by Daniel Berlin

Makefile.in (tree-ssa-loop-niter.o): Depends on tree-data-ref.h.

2004-10-11  Sebastian Pop  <pop@cri.ensmp.fr>

	* Makefile.in (tree-ssa-loop-niter.o): Depends on tree-data-ref.h.
	* cfgloop.c (initialize_loops_parallel_p): New.
	(flow_loops_find): Initialize the parallel_p field to true for all
	the loops.
	* tree-ssa-loop-niter.c: Include "tree-data-ref.h".
	(estimate_numbers_of_iterations_loop): Infers the loop bounds from
	the size of the data accessed in the loop.
	(struct nb_iter_bound): Moved...
	* cfgloop.h (struct nb_iter_bound): ... here.
	(estimated_nb_iterations, parallel_p): New fields in struct loop.
	(record_estimate): Declare extern here.
	* tree-chrec.c: Fix comments.
	(nb_vars_in_chrec): New function.
	* tree-chrec.h (nb_vars_in_chrec): Declared here.
	* tree-data-ref.c: Don't include lambda.h, that is already included
	in tree-data-ref.h.
	(tree_fold_divides_p): Don't check for integer_onep.
	(tree_fold_bezout): Removed.
	(gcd): New static duplicated function.
	(int_divides_p, dump_subscript): New.
	(dump_data_dependence_relation): Use dump_subscript.
	(dump_dist_dir_vectors, dump_ddrs, compute_estimated_nb_iterations,
	estimate_niter_from_size_of_data): New.
	(analyze_array_indexes, analyze_array): Call
	estimate_niter_from_size_of_data during	the detection of array
	references.  Pass in a pointer to the statement that contains the
	array reference.
	(all_chrecs_equal_p): New.
	(compute_distance_vector): Renamed compute_subscript_distance.
	Deal with multivariate conflict functions.
	(initialize_data_dependence_relation): Initialize DDR_AFFINE_P,
	DDR_SIZE_VECT, DDR_DIST_VECT, and DDR_DIR_VECT.
	(non_affine_dependence_relation): New.
	(analyze_ziv_subscript, analyze_siv_subscript_cst_affine,
	analyze_siv_subscript, analyze_miv_subscript,
	analyze_overlapping_iterations, subscript_dependence_tester):
	Initialize and return last_conflicts function.
	(initialize_matrix_A, FLOOR, compute_overlap_steps_for_affine_univar,
	compute_overlap_steps_for_affine_1_2): New.
	(analyze_siv_subscript_affine_cst): Removed.
	(analyze_subscript_affine_affine): Disprove dependences based on the
	iteration domains.  Solve the univariate dependence case as before,
	but use lambda_matrix_right_hermite instead of tree_fold_bezout.
	Implement the multivariate case of 2 versus 1 variables.
	(build_classic_dist_vector, build_classic_dir_vector): Implement some
	unhandled cases.
	(find_data_references_in_loop): Compute and initialize
	loop->estimated_nb_iterations and loop->parallel_p.
	(analyze_all_data_dependences): Modify the debug dump order.
	* tree-data-ref.h (SUB_LAST_CONFLICT_IN_A, SUB_LAST_CONFLICT_IN_B,
	subscript->last_conflict_in_a, subscript->last_conflict_in_b): Removed.
	(SUB_LAST_CONFLICT, subscript->last_conflict,
	data_dependence_relation->affine_p, data_dependence_relation->size_vect,
	DDR_AFFINE_P, DDR_SIZE_VECT): New.
	(find_data_references_in_loop, initialize_data_dependence_relation,
	dump_subscript, dump_ddrs, dump_dist_dir_vectors): Declared here.

From-SVN: r88965
parent 06c3418c
2004-10-11 Sebastian Pop <pop@cri.ensmp.fr>
* Makefile.in (tree-ssa-loop-niter.o): Depends on tree-data-ref.h.
* cfgloop.c (initialize_loops_parallel_p): New.
(flow_loops_find): Initialize the parallel_p field to true for all
the loops.
* tree-ssa-loop-niter.c: Include "tree-data-ref.h".
(estimate_numbers_of_iterations_loop): Infers the loop bounds from
the size of the data accessed in the loop.
(struct nb_iter_bound): Moved...
* cfgloop.h (struct nb_iter_bound): ... here.
(estimated_nb_iterations, parallel_p): New fields in struct loop.
(record_estimate): Declare extern here.
* tree-chrec.c: Fix comments.
(nb_vars_in_chrec): New function.
* tree-chrec.h (nb_vars_in_chrec): Declared here.
* tree-data-ref.c: Don't include lambda.h, that is already included
in tree-data-ref.h.
(tree_fold_divides_p): Don't check for integer_onep.
(tree_fold_bezout): Removed.
(gcd): New static duplicated function.
(int_divides_p, dump_subscript): New.
(dump_data_dependence_relation): Use dump_subscript.
(dump_dist_dir_vectors, dump_ddrs, compute_estimated_nb_iterations,
estimate_niter_from_size_of_data): New.
(analyze_array_indexes, analyze_array): Call
estimate_niter_from_size_of_data during the detection of array
references. Pass in a pointer to the statement that contains the
array reference.
(all_chrecs_equal_p): New.
(compute_distance_vector): Renamed compute_subscript_distance.
Deal with multivariate conflict functions.
(initialize_data_dependence_relation): Initialize DDR_AFFINE_P,
DDR_SIZE_VECT, DDR_DIST_VECT, and DDR_DIR_VECT.
(non_affine_dependence_relation): New.
(analyze_ziv_subscript, analyze_siv_subscript_cst_affine,
analyze_siv_subscript, analyze_miv_subscript,
analyze_overlapping_iterations, subscript_dependence_tester):
Initialize and return last_conflicts function.
(initialize_matrix_A, FLOOR, compute_overlap_steps_for_affine_univar,
compute_overlap_steps_for_affine_1_2): New.
(analyze_siv_subscript_affine_cst): Removed.
(analyze_subscript_affine_affine): Disprove dependences based on the
iteration domains. Solve the univariate dependence case as before,
but use lambda_matrix_right_hermite instead of tree_fold_bezout.
Implement the multivariate case of 2 versus 1 variables.
(build_classic_dist_vector, build_classic_dir_vector): Implement some
unhandled cases.
(find_data_references_in_loop): Compute and initialize
loop->estimated_nb_iterations and loop->parallel_p.
(analyze_all_data_dependences): Modify the debug dump order.
* tree-data-ref.h (SUB_LAST_CONFLICT_IN_A, SUB_LAST_CONFLICT_IN_B,
subscript->last_conflict_in_a, subscript->last_conflict_in_b): Removed.
(SUB_LAST_CONFLICT, subscript->last_conflict,
data_dependence_relation->affine_p, data_dependence_relation->size_vect,
DDR_AFFINE_P, DDR_SIZE_VECT): New.
(find_data_references_in_loop, initialize_data_dependence_relation,
dump_subscript, dump_ddrs, dump_dist_dir_vectors): Declared here.
2004-10-12 Kelley Cook <kcook@gcc.gnu.org> 2004-10-12 Kelley Cook <kcook@gcc.gnu.org>
* configure: Regenerate. * configure: Regenerate.
......
...@@ -1706,7 +1706,7 @@ tree-ssa-loop-unswitch.o : tree-ssa-loop-unswitch.c $(TREE_FLOW_H) $(CONFIG_H) \ ...@@ -1706,7 +1706,7 @@ tree-ssa-loop-unswitch.o : tree-ssa-loop-unswitch.c $(TREE_FLOW_H) $(CONFIG_H) \
tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) cfgloop.h $(PARAMS_H) tree-inline.h \ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) cfgloop.h $(PARAMS_H) tree-inline.h \
output.h diagnostic.h $(TM_H) coretypes.h $(TREE_DUMP_H) $(FLAGS_H) \ output.h diagnostic.h $(TM_H) coretypes.h $(TREE_DUMP_H) $(FLAGS_H) \
tree-pass.h $(SCEV_H) tree-pass.h $(SCEV_H) tree-data-ref.h
tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \ tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) tree-inline.h \ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) tree-inline.h \
output.h diagnostic.h $(TM_H) coretypes.h $(TREE_DUMP_H) $(FLAGS_H) \ output.h diagnostic.h $(TM_H) coretypes.h $(TREE_DUMP_H) $(FLAGS_H) \
......
...@@ -780,6 +780,20 @@ canonicalize_loop_headers (void) ...@@ -780,6 +780,20 @@ canonicalize_loop_headers (void)
#endif #endif
} }
/* Initialize all the parallel_p fields of the loops structure to true. */
static void
initialize_loops_parallel_p (struct loops *loops)
{
unsigned int i;
for (i = 0; i < loops->num; i++)
{
struct loop *loop = loops->parray[i];
loop->parallel_p = true;
}
}
/* Find all the natural loops in the function and save in LOOPS structure and /* Find all the natural loops in the function and save in LOOPS structure and
recalculate loop_depth information in basic block structures. FLAGS recalculate loop_depth information in basic block structures. FLAGS
controls which loop information is collected. Return the number of natural controls which loop information is collected. Return the number of natural
...@@ -945,6 +959,7 @@ flow_loops_find (struct loops *loops, int flags) ...@@ -945,6 +959,7 @@ flow_loops_find (struct loops *loops, int flags)
flow_loop_scan (loops->parray[i], flags); flow_loop_scan (loops->parray[i], flags);
loops->num = num_loops; loops->num = num_loops;
initialize_loops_parallel_p (loops);
} }
sbitmap_free (headers); sbitmap_free (headers);
......
...@@ -43,6 +43,20 @@ struct lpt_decision ...@@ -43,6 +43,20 @@ struct lpt_decision
unsigned times; unsigned times;
}; };
/* The structure describing a bound on number of iterations of a loop. */
struct nb_iter_bound
{
tree bound; /* The expression whose value is an upper bound on the
number of executions of anything after ... */
tree at_stmt; /* ... this statement during one execution of loop. */
tree additional; /* A conjunction of conditions the operands of BOUND
satisfy. The additional information about the value
of the bound may be derived from it. */
struct nb_iter_bound *next;
/* The next bound in a list. */
};
/* Structure to hold information for each natural loop. */ /* Structure to hold information for each natural loop. */
struct loop struct loop
{ {
...@@ -173,12 +187,22 @@ struct loop ...@@ -173,12 +187,22 @@ struct loop
information in this field. */ information in this field. */
tree nb_iterations; tree nb_iterations;
/* An INTEGER_CST estimation of the number of iterations. NULL_TREE
if there is no estimation. */
tree estimated_nb_iterations;
/* Upper bound on number of iterations of a loop. */ /* Upper bound on number of iterations of a loop. */
struct nb_iter_bound *bounds; struct nb_iter_bound *bounds;
/* If not NULL, loop has just single exit edge stored here (edges to the /* If not NULL, loop has just single exit edge stored here (edges to the
EXIT_BLOCK_PTR do not count. */ EXIT_BLOCK_PTR do not count. */
edge single_exit; edge single_exit;
/* True when the loop does not carry data dependences, and
consequently the iterations can be executed in any order. False
when the loop carries data dependences, or when the property is
not decidable. */
bool parallel_p;
}; };
/* Flags for state of loop structure. */ /* Flags for state of loop structure. */
...@@ -462,6 +486,7 @@ enum ...@@ -462,6 +486,7 @@ enum
extern void unroll_and_peel_loops (struct loops *, int); extern void unroll_and_peel_loops (struct loops *, int);
extern void doloop_optimize_loops (struct loops *); extern void doloop_optimize_loops (struct loops *);
extern void move_loop_invariants (struct loops *); extern void move_loop_invariants (struct loops *);
extern void record_estimate (struct loop *, tree, tree, tree);
/* Old loop optimizer interface. */ /* Old loop optimizer interface. */
......
...@@ -636,7 +636,7 @@ chrec_component_in_loop_num (tree chrec, ...@@ -636,7 +636,7 @@ chrec_component_in_loop_num (tree chrec,
} }
/* Returns the evolution part in LOOP_NUM. Example: the call /* Returns the evolution part in LOOP_NUM. Example: the call
evolution_part_in_loop_num (1, {{0, +, 1}_1, +, 2}_1) returns evolution_part_in_loop_num ({{0, +, 1}_1, +, 2}_1, 1) returns
{1, +, 2}_1 */ {1, +, 2}_1 */
tree tree
...@@ -647,7 +647,7 @@ evolution_part_in_loop_num (tree chrec, ...@@ -647,7 +647,7 @@ evolution_part_in_loop_num (tree chrec,
} }
/* Returns the initial condition in LOOP_NUM. Example: the call /* Returns the initial condition in LOOP_NUM. Example: the call
initial_condition_in_loop_num ({{0, +, 1}_1, +, 2}_2, 1) returns initial_condition_in_loop_num ({{0, +, 1}_1, +, 2}_2, 2) returns
{0, +, 1}_1 */ {0, +, 1}_1 */
tree tree
...@@ -932,6 +932,26 @@ evolution_function_is_univariate_p (tree chrec) ...@@ -932,6 +932,26 @@ evolution_function_is_univariate_p (tree chrec)
} }
} }
/* Returns the number of variables of CHREC. Example: the call
nb_vars_in_chrec ({{0, +, 1}_5, +, 2}_6) returns 2. */
unsigned
nb_vars_in_chrec (tree chrec)
{
if (chrec == NULL_TREE)
return 0;
switch (TREE_CODE (chrec))
{
case POLYNOMIAL_CHREC:
return 1 + nb_vars_in_chrec
(initial_condition_in_loop_num (chrec, CHREC_VARIABLE (chrec)));
default:
return 0;
}
}
/* Convert the initial condition of chrec to type. */ /* Convert the initial condition of chrec to type. */
......
...@@ -91,6 +91,7 @@ extern bool chrec_contains_undetermined (tree); ...@@ -91,6 +91,7 @@ extern bool chrec_contains_undetermined (tree);
extern bool tree_contains_chrecs (tree); extern bool tree_contains_chrecs (tree);
extern bool evolution_function_is_affine_multivariate_p (tree); extern bool evolution_function_is_affine_multivariate_p (tree);
extern bool evolution_function_is_univariate_p (tree); extern bool evolution_function_is_univariate_p (tree);
extern unsigned nb_vars_in_chrec (tree);
......
...@@ -44,7 +44,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -44,7 +44,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- polyhedron dependence - polyhedron dependence
or with the chains of recurrences based representation, or with the chains of recurrences based representation,
- to define a knowledge base for storing the data dependences - to define a knowledge base for storing the data dependeces
information, information,
- to define an interface to access this data. - to define an interface to access this data.
...@@ -94,7 +94,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -94,7 +94,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree-data-ref.h" #include "tree-data-ref.h"
#include "tree-scalar-evolution.h" #include "tree-scalar-evolution.h"
#include "tree-pass.h" #include "tree-pass.h"
#include "lambda.h"
/* This is the simplest data dependence test: determines whether the /* This is the simplest data dependence test: determines whether the
data references A and B access the same array/region. Returns data references A and B access the same array/region. Returns
...@@ -113,6 +112,7 @@ array_base_name_differ_p (struct data_reference *a, ...@@ -113,6 +112,7 @@ array_base_name_differ_p (struct data_reference *a,
tree ta = TREE_TYPE (base_a); tree ta = TREE_TYPE (base_a);
tree tb = TREE_TYPE (base_b); tree tb = TREE_TYPE (base_b);
/* Determine if same base. Example: for the array accesses /* Determine if same base. Example: for the array accesses
a[i], b[i] or pointer accesses *a, *b, bases are a, b. */ a[i], b[i] or pointer accesses *a, *b, bases are a, b. */
if (base_a == base_b) if (base_a == base_b)
...@@ -130,7 +130,7 @@ array_base_name_differ_p (struct data_reference *a, ...@@ -130,7 +130,7 @@ array_base_name_differ_p (struct data_reference *a,
return true; return true;
} }
/* record/union based accesses - s.a[i], t.b[j]. bases are s.a,t.b. */ /* Record/union based accesses - s.a[i], t.b[j]. bases are s.a,t.b. */
if (TREE_CODE (base_a) == COMPONENT_REF && TREE_CODE (base_b) == COMPONENT_REF if (TREE_CODE (base_a) == COMPONENT_REF && TREE_CODE (base_b) == COMPONENT_REF
&& TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0) && TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0)
&& TREE_OPERAND (base_a, 1) == TREE_OPERAND (base_b, 1)) && TREE_OPERAND (base_a, 1) == TREE_OPERAND (base_b, 1))
...@@ -139,6 +139,7 @@ array_base_name_differ_p (struct data_reference *a, ...@@ -139,6 +139,7 @@ array_base_name_differ_p (struct data_reference *a,
return true; return true;
} }
/* Determine if different bases. */ /* Determine if different bases. */
/* At this point we know that base_a != base_b. However, pointer /* At this point we know that base_a != base_b. However, pointer
...@@ -206,109 +207,39 @@ tree_fold_divides_p (tree type, ...@@ -206,109 +207,39 @@ tree_fold_divides_p (tree type,
tree a, tree a,
tree b) tree b)
{ {
if (integer_onep (a))
return true;
/* Determines whether (A == gcd (A, B)). */ /* Determines whether (A == gcd (A, B)). */
return integer_zerop return integer_zerop
(fold (build (MINUS_EXPR, type, a, tree_fold_gcd (a, b)))); (fold (build (MINUS_EXPR, type, a, tree_fold_gcd (a, b))));
} }
/* Bezout: Let A1 and A2 be two integers; there exist two integers U11 /* Compute the greatest common denominator of two numbers using
and U12 such that, Euclid's algorithm. */
| U11 * A1 + U12 * A2 = gcd (A1, A2).
This function computes the greatest common divisor using the
Blankinship algorithm. The gcd is returned, and the coefficients
of the unimodular matrix U are (U11, U12, U21, U22) such that,
| U.A = S static int
gcd (int a, int b)
| (U11 U12) (A1) = (gcd)
| (U21 U22) (A2) (0)
FIXME: Use lambda_..._hermite for implementing this function.
*/
static tree
tree_fold_bezout (tree a1,
tree a2,
tree *u11, tree *u12,
tree *u21, tree *u22)
{ {
tree s1, s2;
/* Initialize S with the coefficients of A. */
s1 = a1;
s2 = a2;
/* Initialize the U matrix */ int x, y, z;
*u11 = integer_one_node;
*u12 = integer_zero_node;
*u21 = integer_zero_node;
*u22 = integer_one_node;
if (integer_zerop (a1) x = abs (a);
|| integer_zerop (a2)) y = abs (b);
return integer_zero_node;
while (!integer_zerop (s2)) while (x>0)
{ {
int sign; z = y % x;
tree z, zu21, zu22, zs2; y = x;
x = z;
sign = tree_int_cst_sgn (s1) * tree_int_cst_sgn (s2);
z = fold (build (FLOOR_DIV_EXPR, integer_type_node,
fold (build1 (ABS_EXPR, integer_type_node, s1)),
fold (build1 (ABS_EXPR, integer_type_node, s2))));
zu21 = fold (build (MULT_EXPR, integer_type_node, z, *u21));
zu22 = fold (build (MULT_EXPR, integer_type_node, z, *u22));
zs2 = fold (build (MULT_EXPR, integer_type_node, z, s2));
/* row1 -= z * row2. */
gcc_assert (sign != 0);
if (sign < 0)
{
*u11 = fold (build (PLUS_EXPR, integer_type_node, *u11, zu21));
*u12 = fold (build (PLUS_EXPR, integer_type_node, *u12, zu22));
s1 = fold (build (PLUS_EXPR, integer_type_node, s1, zs2));
}
else
{
*u11 = fold (build (MINUS_EXPR, integer_type_node, *u11, zu21));
*u12 = fold (build (MINUS_EXPR, integer_type_node, *u12, zu22));
s1 = fold (build (MINUS_EXPR, integer_type_node, s1, zs2));
} }
/* Interchange row1 and row2. */ return (y);
{ }
tree flip;
flip = *u11;
*u11 = *u21;
*u21 = flip;
flip = *u12;
*u12 = *u22;
*u22 = flip;
flip = s1;
s1 = s2;
s2 = flip;
}
}
if (tree_int_cst_sgn (s1) < 0) /* Returns true iff A divides B. */
{
*u11 = fold (build (MULT_EXPR, integer_type_node, *u11,
integer_minus_one_node));
*u12 = fold (build (MULT_EXPR, integer_type_node, *u12,
integer_minus_one_node));
s1 = fold (build (MULT_EXPR, integer_type_node, s1, integer_minus_one_node));
}
return s1; static inline bool
int_divides_p (int a, int b)
{
return ((b % a) == 0);
} }
...@@ -360,43 +291,14 @@ dump_data_reference (FILE *outf, ...@@ -360,43 +291,14 @@ dump_data_reference (FILE *outf,
fprintf (outf, ")\n"); fprintf (outf, ")\n");
} }
/* Dump function for a DATA_DEPENDENCE_RELATION structure. */ /* Dump function for a SUBSCRIPT structure. */
void void
dump_data_dependence_relation (FILE *outf, dump_subscript (FILE *outf, struct subscript *subscript)
struct data_dependence_relation *ddr)
{ {
unsigned int i; tree chrec = SUB_CONFLICTS_IN_A (subscript);
struct data_reference *dra, *drb;
dra = DDR_A (ddr); fprintf (outf, "\n (subscript \n");
drb = DDR_B (ddr);
if (dra && drb)
fprintf (outf, "(Data Dep:");
else
fprintf (outf, "(Data Dep:");
if (chrec_contains_undetermined (DDR_ARE_DEPENDENT (ddr)))
fprintf (outf, " (don't know)\n");
else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
fprintf (outf, " (no dependence)\n");
else
{
for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
{
tree chrec;
struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
fprintf (outf, "\n (subscript %d:\n", i);
fprintf (outf, " access_fn_A: ");
print_generic_stmt (outf, DR_ACCESS_FN (dra, i), 0);
fprintf (outf, " access_fn_B: ");
print_generic_stmt (outf, DR_ACCESS_FN (drb, i), 0);
chrec = SUB_CONFLICTS_IN_A (subscript);
fprintf (outf, " iterations_that_access_an_element_twice_in_A: "); fprintf (outf, " iterations_that_access_an_element_twice_in_A: ");
print_generic_stmt (outf, chrec, 0); print_generic_stmt (outf, chrec, 0);
if (chrec == chrec_known) if (chrec == chrec_known)
...@@ -405,8 +307,8 @@ dump_data_dependence_relation (FILE *outf, ...@@ -405,8 +307,8 @@ dump_data_dependence_relation (FILE *outf,
fprintf (outf, " (don't know)\n"); fprintf (outf, " (don't know)\n");
else else
{ {
tree last_iteration = SUB_LAST_CONFLICT_IN_A (subscript); tree last_iteration = SUB_LAST_CONFLICT (subscript);
fprintf (outf, " last_iteration_that_access_an_element_twice_in_A: "); fprintf (outf, " last_conflict: ");
print_generic_stmt (outf, last_iteration, 0); print_generic_stmt (outf, last_iteration, 0);
} }
...@@ -419,24 +321,55 @@ dump_data_dependence_relation (FILE *outf, ...@@ -419,24 +321,55 @@ dump_data_dependence_relation (FILE *outf,
fprintf (outf, " (don't know)\n"); fprintf (outf, " (don't know)\n");
else else
{ {
tree last_iteration = SUB_LAST_CONFLICT_IN_B (subscript); tree last_iteration = SUB_LAST_CONFLICT (subscript);
fprintf (outf, " last_iteration_that_access_an_element_twice_in_B: "); fprintf (outf, " last_conflict: ");
print_generic_stmt (outf, last_iteration, 0); print_generic_stmt (outf, last_iteration, 0);
} }
fprintf (outf, " (Subscript distance: ");
print_generic_stmt (outf, SUB_DISTANCE (subscript), 0);
fprintf (outf, " )\n"); fprintf (outf, " )\n");
} fprintf (outf, " )\n");
}
/* Dump function for a DATA_DEPENDENCE_RELATION structure. */
void
dump_data_dependence_relation (FILE *outf,
struct data_dependence_relation *ddr)
{
struct data_reference *dra, *drb;
dra = DDR_A (ddr);
drb = DDR_B (ddr);
fprintf (outf, "(Data Dep: \n");
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
fprintf (outf, " (don't know)\n");
else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
fprintf (outf, " (no dependence)\n");
fprintf (outf, " (Distance Vector: \n"); else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
{
unsigned int i;
for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++) for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
{ {
struct subscript *subscript = DDR_SUBSCRIPT (ddr, i); fprintf (outf, " access_fn_A: ");
print_generic_stmt (outf, DR_ACCESS_FN (dra, i), 0);
fprintf (outf, "("); fprintf (outf, " access_fn_B: ");
print_generic_stmt (outf, SUB_DISTANCE (subscript), 0); print_generic_stmt (outf, DR_ACCESS_FN (drb, i), 0);
fprintf (outf, ")\n"); dump_subscript (outf, DDR_SUBSCRIPT (ddr, i));
}
if (DDR_DIST_VECT (ddr))
{
fprintf (outf, " distance_vect: ");
print_lambda_vector (outf, DDR_DIST_VECT (ddr), DDR_SIZE_VECT (ddr));
}
if (DDR_DIR_VECT (ddr))
{
fprintf (outf, " direction_vect: ");
print_lambda_vector (outf, DDR_DIR_VECT (ddr), DDR_SIZE_VECT (ddr));
} }
fprintf (outf, " )\n");
} }
fprintf (outf, ")\n"); fprintf (outf, ")\n");
...@@ -485,7 +418,119 @@ dump_data_dependence_direction (FILE *file, ...@@ -485,7 +418,119 @@ dump_data_dependence_direction (FILE *file,
} }
} }
/* Dumps the distance and direction vectors in FILE. DDRS contains
the dependence relations, and VECT_SIZE is the size of the
dependence vectors, or in other words the number of loops in the
considered nest. */
void
dump_dist_dir_vectors (FILE *file, varray_type ddrs)
{
unsigned int i;
for (i = 0; i < VARRAY_ACTIVE_SIZE (ddrs); i++)
{
struct data_dependence_relation *ddr =
(struct data_dependence_relation *)
VARRAY_GENERIC_PTR (ddrs, i);
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE
&& DDR_AFFINE_P (ddr))
{
fprintf (file, "DISTANCE_V (");
print_lambda_vector (file, DDR_DIST_VECT (ddr), DDR_SIZE_VECT (ddr));
fprintf (file, ")\n");
fprintf (file, "DIRECTION_V (");
print_lambda_vector (file, DDR_DIR_VECT (ddr), DDR_SIZE_VECT (ddr));
fprintf (file, ")\n");
}
}
fprintf (file, "\n\n");
}
/* Dumps the data dependence relations DDRS in FILE. */
void
dump_ddrs (FILE *file, varray_type ddrs)
{
unsigned int i;
for (i = 0; i < VARRAY_ACTIVE_SIZE (ddrs); i++)
{
struct data_dependence_relation *ddr =
(struct data_dependence_relation *)
VARRAY_GENERIC_PTR (ddrs, i);
dump_data_dependence_relation (file, ddr);
}
fprintf (file, "\n\n");
}
/* Compute the lowest iteration bound for LOOP. It is an
INTEGER_CST. */
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;
}
}
/* Estimate the number of iterations from the size of the data and the
access functions. */
static void
estimate_niter_from_size_of_data (struct loop *loop,
tree opnd0,
tree access_fn,
tree stmt)
{
tree estimation;
tree array_size, data_size, element_size;
tree init, step;
init = initial_condition (access_fn);
step = evolution_part_in_loop_num (access_fn, loop->num);
array_size = TYPE_SIZE (TREE_TYPE (opnd0));
element_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (opnd0)));
if (array_size == NULL_TREE
|| element_size == NULL_TREE)
return;
data_size = fold (build2 (EXACT_DIV_EXPR, integer_type_node,
array_size, element_size));
if (init != NULL_TREE
&& step != NULL_TREE
&& TREE_CODE (init) == INTEGER_CST
&& TREE_CODE (step) == INTEGER_CST)
{
estimation = fold (build2 (CEIL_DIV_EXPR, integer_type_node,
fold (build2 (MINUS_EXPR, integer_type_node,
data_size, init)), step));
record_estimate (loop, estimation, boolean_true_node, stmt);
}
}
/* Given an ARRAY_REF node REF, records its access functions. /* Given an ARRAY_REF node REF, records its access functions.
Example: given A[i][3], record in ACCESS_FNS the opnd1 function, Example: given A[i][3], record in ACCESS_FNS the opnd1 function,
...@@ -496,7 +541,7 @@ dump_data_dependence_direction (FILE *file, ...@@ -496,7 +541,7 @@ dump_data_dependence_direction (FILE *file,
static tree static tree
analyze_array_indexes (struct loop *loop, analyze_array_indexes (struct loop *loop,
varray_type *access_fns, varray_type *access_fns,
tree ref) tree ref, tree stmt)
{ {
tree opnd0, opnd1; tree opnd0, opnd1;
tree access_fn; tree access_fn;
...@@ -511,11 +556,14 @@ analyze_array_indexes (struct loop *loop, ...@@ -511,11 +556,14 @@ analyze_array_indexes (struct loop *loop,
access_fn = instantiate_parameters access_fn = instantiate_parameters
(loop, analyze_scalar_evolution (loop, opnd1)); (loop, analyze_scalar_evolution (loop, opnd1));
if (loop->estimated_nb_iterations == NULL_TREE)
estimate_niter_from_size_of_data (loop, opnd0, access_fn, stmt);
VARRAY_PUSH_TREE (*access_fns, access_fn); VARRAY_PUSH_TREE (*access_fns, access_fn);
/* Recursively record other array access functions. */ /* Recursively record other array access functions. */
if (TREE_CODE (opnd0) == ARRAY_REF) if (TREE_CODE (opnd0) == ARRAY_REF)
return analyze_array_indexes (loop, access_fns, opnd0); return analyze_array_indexes (loop, access_fns, opnd0, stmt);
/* Return the base name of the data access. */ /* Return the base name of the data access. */
else else
...@@ -546,7 +594,7 @@ analyze_array (tree stmt, tree ref, bool is_read) ...@@ -546,7 +594,7 @@ analyze_array (tree stmt, tree ref, bool is_read)
DR_REF (res) = ref; DR_REF (res) = ref;
VARRAY_TREE_INIT (DR_ACCESS_FNS (res), 3, "access_fns"); VARRAY_TREE_INIT (DR_ACCESS_FNS (res), 3, "access_fns");
DR_BASE_NAME (res) = analyze_array_indexes DR_BASE_NAME (res) = analyze_array_indexes
(loop_containing_stmt (stmt), &(DR_ACCESS_FNS (res)), ref); (loop_containing_stmt (stmt), &(DR_ACCESS_FNS (res)), ref, stmt);
DR_IS_READ (res) = is_read; DR_IS_READ (res) = is_read;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
...@@ -592,11 +640,31 @@ init_data_ref (tree stmt, ...@@ -592,11 +640,31 @@ init_data_ref (tree stmt,
/* When there exists a dependence relation, determine its distance /* Returns true when all the functions of a tree_vec CHREC are the
vector. */ same. */
static bool
all_chrecs_equal_p (tree chrec)
{
int j;
for (j = 0; j < TREE_VEC_LENGTH (chrec) - 1; j++)
{
tree chrec_j = TREE_VEC_ELT (chrec, j);
tree chrec_j_1 = TREE_VEC_ELT (chrec, j + 1);
if (!integer_zerop
(chrec_fold_minus
(integer_type_node, chrec_j, chrec_j_1)))
return false;
}
return true;
}
/* Determine for each subscript in the data dependence relation DDR
the distance. */
static void static void
compute_distance_vector (struct data_dependence_relation *ddr) compute_subscript_distance (struct data_dependence_relation *ddr)
{ {
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
{ {
...@@ -610,6 +678,29 @@ compute_distance_vector (struct data_dependence_relation *ddr) ...@@ -610,6 +678,29 @@ compute_distance_vector (struct data_dependence_relation *ddr)
subscript = DDR_SUBSCRIPT (ddr, i); subscript = DDR_SUBSCRIPT (ddr, i);
conflicts_a = SUB_CONFLICTS_IN_A (subscript); conflicts_a = SUB_CONFLICTS_IN_A (subscript);
conflicts_b = SUB_CONFLICTS_IN_B (subscript); conflicts_b = SUB_CONFLICTS_IN_B (subscript);
if (TREE_CODE (conflicts_a) == TREE_VEC)
{
if (!all_chrecs_equal_p (conflicts_a))
{
SUB_DISTANCE (subscript) = chrec_dont_know;
return;
}
else
conflicts_a = TREE_VEC_ELT (conflicts_a, 0);
}
if (TREE_CODE (conflicts_b) == TREE_VEC)
{
if (!all_chrecs_equal_p (conflicts_b))
{
SUB_DISTANCE (subscript) = chrec_dont_know;
return;
}
else
conflicts_b = TREE_VEC_ELT (conflicts_b, 0);
}
difference = chrec_fold_minus difference = chrec_fold_minus
(integer_type_node, conflicts_b, conflicts_a); (integer_type_node, conflicts_b, conflicts_a);
...@@ -649,8 +740,12 @@ initialize_data_dependence_relation (struct data_reference *a, ...@@ -649,8 +740,12 @@ initialize_data_dependence_relation (struct data_reference *a,
else else
{ {
unsigned int i; unsigned int i;
DDR_AFFINE_P (res) = true;
DDR_ARE_DEPENDENT (res) = NULL_TREE; DDR_ARE_DEPENDENT (res) = NULL_TREE;
DDR_SUBSCRIPTS_VECTOR_INIT (res, DR_NUM_DIMENSIONS (a)); DDR_SUBSCRIPTS_VECTOR_INIT (res, DR_NUM_DIMENSIONS (a));
DDR_SIZE_VECT (res) = 0;
DDR_DIST_VECT (res) = NULL;
DDR_DIR_VECT (res) = NULL;
for (i = 0; i < DR_NUM_DIMENSIONS (a); i++) for (i = 0; i < DR_NUM_DIMENSIONS (a); i++)
{ {
...@@ -659,8 +754,7 @@ initialize_data_dependence_relation (struct data_reference *a, ...@@ -659,8 +754,7 @@ initialize_data_dependence_relation (struct data_reference *a,
subscript = xmalloc (sizeof (struct subscript)); subscript = xmalloc (sizeof (struct subscript));
SUB_CONFLICTS_IN_A (subscript) = chrec_dont_know; SUB_CONFLICTS_IN_A (subscript) = chrec_dont_know;
SUB_CONFLICTS_IN_B (subscript) = chrec_dont_know; SUB_CONFLICTS_IN_B (subscript) = chrec_dont_know;
SUB_LAST_CONFLICT_IN_A (subscript) = chrec_dont_know; SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
SUB_LAST_CONFLICT_IN_B (subscript) = chrec_dont_know;
SUB_DISTANCE (subscript) = chrec_dont_know; SUB_DISTANCE (subscript) = chrec_dont_know;
VARRAY_PUSH_GENERIC_PTR (DDR_SUBSCRIPTS (res), subscript); VARRAY_PUSH_GENERIC_PTR (DDR_SUBSCRIPTS (res), subscript);
} }
...@@ -687,6 +781,18 @@ finalize_ddr_dependent (struct data_dependence_relation *ddr, ...@@ -687,6 +781,18 @@ finalize_ddr_dependent (struct data_dependence_relation *ddr,
varray_clear (DDR_SUBSCRIPTS (ddr)); varray_clear (DDR_SUBSCRIPTS (ddr));
} }
/* The dependence relation DDR cannot be represented by a distance
vector. */
static inline void
non_affine_dependence_relation (struct data_dependence_relation *ddr)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "(Dependence relation cannot be represented by distance vector.) \n");
DDR_AFFINE_P (ddr) = false;
}
/* This section contains the classic Banerjee tests. */ /* This section contains the classic Banerjee tests. */
...@@ -750,7 +856,8 @@ static void ...@@ -750,7 +856,8 @@ static void
analyze_ziv_subscript (tree chrec_a, analyze_ziv_subscript (tree chrec_a,
tree chrec_b, tree chrec_b,
tree *overlaps_a, tree *overlaps_a,
tree *overlaps_b) tree *overlaps_b,
tree *last_conflicts)
{ {
tree difference; tree difference;
...@@ -768,12 +875,14 @@ analyze_ziv_subscript (tree chrec_a, ...@@ -768,12 +875,14 @@ analyze_ziv_subscript (tree chrec_a,
overlaps for each iteration in the loop. */ overlaps for each iteration in the loop. */
*overlaps_a = integer_zero_node; *overlaps_a = integer_zero_node;
*overlaps_b = integer_zero_node; *overlaps_b = integer_zero_node;
*last_conflicts = chrec_dont_know;
} }
else else
{ {
/* The accesses do not overlap. */ /* The accesses do not overlap. */
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
} }
break; break;
...@@ -782,6 +891,7 @@ analyze_ziv_subscript (tree chrec_a, ...@@ -782,6 +891,7 @@ analyze_ziv_subscript (tree chrec_a,
conservatively answer "don't know". */ conservatively answer "don't know". */
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
break; break;
} }
...@@ -801,7 +911,8 @@ static void ...@@ -801,7 +911,8 @@ static void
analyze_siv_subscript_cst_affine (tree chrec_a, analyze_siv_subscript_cst_affine (tree chrec_a,
tree chrec_b, tree chrec_b,
tree *overlaps_a, tree *overlaps_a,
tree *overlaps_b) tree *overlaps_b,
tree *last_conflicts)
{ {
bool value0, value1, value2; bool value0, value1, value2;
tree difference = chrec_fold_minus tree difference = chrec_fold_minus
...@@ -811,6 +922,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -811,6 +922,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
{ {
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
return; return;
} }
else else
...@@ -821,6 +933,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -821,6 +933,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
{ {
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
return; return;
} }
else else
...@@ -840,6 +953,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -840,6 +953,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
(build (EXACT_DIV_EXPR, integer_type_node, (build (EXACT_DIV_EXPR, integer_type_node,
fold (build1 (ABS_EXPR, integer_type_node, difference)), fold (build1 (ABS_EXPR, integer_type_node, difference)),
CHREC_RIGHT (chrec_b))); CHREC_RIGHT (chrec_b)));
*last_conflicts = integer_one_node;
return; return;
} }
...@@ -849,6 +963,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -849,6 +963,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
{ {
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
return; return;
} }
} }
...@@ -862,6 +977,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -862,6 +977,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
In this case, chrec_a will not overlap with chrec_b. */ In this case, chrec_a will not overlap with chrec_b. */
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
return; return;
} }
} }
...@@ -872,6 +988,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -872,6 +988,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
{ {
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
return; return;
} }
else else
...@@ -889,6 +1006,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -889,6 +1006,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
*overlaps_b = fold *overlaps_b = fold
(build (EXACT_DIV_EXPR, integer_type_node, difference, (build (EXACT_DIV_EXPR, integer_type_node, difference,
CHREC_RIGHT (chrec_b))); CHREC_RIGHT (chrec_b)));
*last_conflicts = integer_one_node;
return; return;
} }
...@@ -898,6 +1016,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -898,6 +1016,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
{ {
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
return; return;
} }
} }
...@@ -910,6 +1029,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -910,6 +1029,7 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
In this case, chrec_a will not overlap with chrec_b. */ In this case, chrec_a will not overlap with chrec_b. */
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
return; return;
} }
} }
...@@ -917,21 +1037,193 @@ analyze_siv_subscript_cst_affine (tree chrec_a, ...@@ -917,21 +1037,193 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
} }
} }
/* Analyze a SIV (Single Index Variable) subscript where CHREC_A is an /* Helper recursive function for intializing the matrix A. Returns
affine function, and CHREC_B is a constant. *OVERLAPS_A and the initial value of CHREC. */
*OVERLAPS_B are initialized to the functions that describe the
relation between the elements accessed twice by CHREC_A and
CHREC_B. For k >= 0, the following property is verified:
CHREC_A (*OVERLAPS_A (k)) = CHREC_B (*OVERLAPS_B (k)). */ static int
initialize_matrix_A (lambda_matrix A, tree chrec, unsigned index, int mult)
{
gcc_assert (chrec);
if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
return int_cst_value (chrec);
A[index][0] = mult * int_cst_value (CHREC_RIGHT (chrec));
return initialize_matrix_A (A, CHREC_LEFT (chrec), index + 1, mult);
}
#define FLOOR_DIV(x,y) ((x) / (y))
/* Solves the special case of the Diophantine equation:
| {0, +, STEP_A}_x (OVERLAPS_A) = {0, +, STEP_B}_y (OVERLAPS_B)
Computes the descriptions OVERLAPS_A and OVERLAPS_B. NITER is the
number of iterations that loops X and Y run. The overlaps will be
constructed as evolutions in dimension DIM. */
static void static void
analyze_siv_subscript_affine_cst (tree chrec_a, compute_overlap_steps_for_affine_univar (int niter, int step_a, int step_b,
tree chrec_b, tree *overlaps_a, tree *overlaps_b,
tree *overlaps_a, tree *last_conflicts, int dim)
tree *overlaps_b)
{ {
analyze_siv_subscript_cst_affine (chrec_b, chrec_a, overlaps_b, overlaps_a); if (((step_a > 0 && step_b > 0)
|| (step_a < 0 && step_b < 0)))
{
int step_overlaps_a, step_overlaps_b;
int gcd_steps_a_b, last_conflict, tau2;
gcd_steps_a_b = gcd (step_a, step_b);
step_overlaps_a = step_b / gcd_steps_a_b;
step_overlaps_b = step_a / gcd_steps_a_b;
tau2 = FLOOR_DIV (niter, step_overlaps_a);
tau2 = MIN (tau2, FLOOR_DIV (niter, step_overlaps_b));
last_conflict = tau2;
*overlaps_a = build_polynomial_chrec
(dim, integer_zero_node,
build_int_cst (NULL_TREE, step_overlaps_a));
*overlaps_b = build_polynomial_chrec
(dim, integer_zero_node,
build_int_cst (NULL_TREE, step_overlaps_b));
*last_conflicts = build_int_cst (NULL_TREE, last_conflict);
}
else
{
*overlaps_a = integer_zero_node;
*overlaps_b = integer_zero_node;
*last_conflicts = integer_zero_node;
}
}
/* Solves the special case of a Diophantine equation where CHREC_A is
an affine bivariate function, and CHREC_B is an affine univariate
function. For example,
| {{0, +, 1}_x, +, 1335}_y = {0, +, 1336}_z
has the following overlapping functions:
| x (t, u, v) = {{0, +, 1336}_t, +, 1}_v
| y (t, u, v) = {{0, +, 1336}_u, +, 1}_v
| z (t, u, v) = {{{0, +, 1}_t, +, 1335}_u, +, 1}_v
FORNOW: This is a specialized implementation for a case occuring in
a common benchmark. Implement the general algorithm. */
static void
compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
tree *overlaps_a, tree *overlaps_b,
tree *last_conflicts)
{
bool xz_p, yz_p, xyz_p;
int step_x, step_y, step_z;
int niter_x, niter_y, niter_z, niter;
tree numiter_x, numiter_y, numiter_z;
tree overlaps_a_xz, overlaps_b_xz, last_conflicts_xz;
tree overlaps_a_yz, overlaps_b_yz, last_conflicts_yz;
tree overlaps_a_xyz, overlaps_b_xyz, last_conflicts_xyz;
step_x = int_cst_value (CHREC_RIGHT (CHREC_LEFT (chrec_a)));
step_y = int_cst_value (CHREC_RIGHT (chrec_a));
step_z = int_cst_value (CHREC_RIGHT (chrec_b));
numiter_x = number_of_iterations_in_loop
(current_loops->parray[CHREC_VARIABLE (CHREC_LEFT (chrec_a))]);
numiter_y = number_of_iterations_in_loop
(current_loops->parray[CHREC_VARIABLE (chrec_a)]);
numiter_z = number_of_iterations_in_loop
(current_loops->parray[CHREC_VARIABLE (chrec_b)]);
if (TREE_CODE (numiter_x) != INTEGER_CST)
numiter_x = current_loops->parray[CHREC_VARIABLE (CHREC_LEFT (chrec_a))]
->estimated_nb_iterations;
if (TREE_CODE (numiter_y) != INTEGER_CST)
numiter_y = current_loops->parray[CHREC_VARIABLE (chrec_a)]
->estimated_nb_iterations;
if (TREE_CODE (numiter_z) != INTEGER_CST)
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)
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
return;
}
niter_x = int_cst_value (numiter_x);
niter_y = int_cst_value (numiter_y);
niter_z = int_cst_value (numiter_z);
niter = MIN (niter_x, niter_z);
compute_overlap_steps_for_affine_univar (niter, step_x, step_z,
&overlaps_a_xz,
&overlaps_b_xz,
&last_conflicts_xz, 1);
niter = MIN (niter_y, niter_z);
compute_overlap_steps_for_affine_univar (niter, step_y, step_z,
&overlaps_a_yz,
&overlaps_b_yz,
&last_conflicts_yz, 2);
niter = MIN (niter_x, niter_z);
niter = MIN (niter_y, niter);
compute_overlap_steps_for_affine_univar (niter, step_x + step_y, step_z,
&overlaps_a_xyz,
&overlaps_b_xyz,
&last_conflicts_xyz, 3);
xz_p = !integer_zerop (last_conflicts_xz);
yz_p = !integer_zerop (last_conflicts_yz);
xyz_p = !integer_zerop (last_conflicts_xyz);
if (xz_p || yz_p || xyz_p)
{
*overlaps_a = make_tree_vec (2);
TREE_VEC_ELT (*overlaps_a, 0) = integer_zero_node;
TREE_VEC_ELT (*overlaps_a, 1) = integer_zero_node;
*overlaps_b = integer_zero_node;
if (xz_p)
{
TREE_VEC_ELT (*overlaps_a, 0) =
chrec_fold_plus (integer_type_node, TREE_VEC_ELT (*overlaps_a, 0),
overlaps_a_xz);
*overlaps_b =
chrec_fold_plus (integer_type_node, *overlaps_b, overlaps_b_xz);
*last_conflicts = last_conflicts_xz;
}
if (yz_p)
{
TREE_VEC_ELT (*overlaps_a, 1) =
chrec_fold_plus (integer_type_node, TREE_VEC_ELT (*overlaps_a, 1),
overlaps_a_yz);
*overlaps_b =
chrec_fold_plus (integer_type_node, *overlaps_b, overlaps_b_yz);
*last_conflicts = last_conflicts_yz;
}
if (xyz_p)
{
TREE_VEC_ELT (*overlaps_a, 0) =
chrec_fold_plus (integer_type_node, TREE_VEC_ELT (*overlaps_a, 0),
overlaps_a_xyz);
TREE_VEC_ELT (*overlaps_a, 1) =
chrec_fold_plus (integer_type_node, TREE_VEC_ELT (*overlaps_a, 1),
overlaps_a_xyz);
*overlaps_b =
chrec_fold_plus (integer_type_node, *overlaps_b, overlaps_b_xyz);
*last_conflicts = last_conflicts_xyz;
}
}
else
{
*overlaps_a = integer_zero_node;
*overlaps_b = integer_zero_node;
*last_conflicts = integer_zero_node;
}
} }
/* Determines the overlapping elements due to accesses CHREC_A and /* Determines the overlapping elements due to accesses CHREC_A and
...@@ -942,9 +1234,13 @@ static void ...@@ -942,9 +1234,13 @@ static void
analyze_subscript_affine_affine (tree chrec_a, analyze_subscript_affine_affine (tree chrec_a,
tree chrec_b, tree chrec_b,
tree *overlaps_a, tree *overlaps_a,
tree *overlaps_b) tree *overlaps_b,
tree *last_conflicts)
{ {
tree left_a, left_b, right_a, right_b; unsigned nb_vars_a, nb_vars_b, dim;
int init_a, init_b, gamma, gcd_alpha_beta;
int tau1, tau2;
lambda_matrix A, U, S;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "(analyze_subscript_affine_affine \n"); fprintf (dump_file, "(analyze_subscript_affine_affine \n");
...@@ -960,103 +1256,114 @@ analyze_subscript_affine_affine (tree chrec_a, ...@@ -960,103 +1256,114 @@ analyze_subscript_affine_affine (tree chrec_a,
there is no dependence. This function outputs a description of there is no dependence. This function outputs a description of
the iterations that hold the intersections. */ the iterations that hold the intersections. */
left_a = CHREC_LEFT (chrec_a);
left_b = CHREC_LEFT (chrec_b);
right_a = CHREC_RIGHT (chrec_a);
right_b = CHREC_RIGHT (chrec_b);
if (chrec_zerop (chrec_fold_minus (integer_type_node, left_a, left_b))) nb_vars_a = nb_vars_in_chrec (chrec_a);
nb_vars_b = nb_vars_in_chrec (chrec_b);
dim = nb_vars_a + nb_vars_b;
U = lambda_matrix_new (dim, dim);
A = lambda_matrix_new (dim, 1);
S = lambda_matrix_new (dim, 1);
init_a = initialize_matrix_A (A, chrec_a, 0, 1);
init_b = initialize_matrix_A (A, chrec_b, nb_vars_a, -1);
gamma = init_b - init_a;
/* Don't do all the hard work of solving the Diophantine equation
when we already know the solution: for example,
| {3, +, 1}_1
| {3, +, 4}_2
| gamma = 3 - 3 = 0.
Then the first overlap occurs during the first iterations:
| {3, +, 1}_1 ({0, +, 4}_x) = {3, +, 4}_2 ({0, +, 1}_x)
*/
if (gamma == 0)
{ {
/* The first element accessed twice is on the first if (nb_vars_a == 1 && nb_vars_b == 1)
iteration. */ {
*overlaps_a = build_polynomial_chrec int step_a, step_b;
(CHREC_VARIABLE (chrec_b), integer_zero_node, integer_one_node); int niter, niter_a, niter_b;
*overlaps_b = build_polynomial_chrec tree numiter_a, numiter_b;
(CHREC_VARIABLE (chrec_a), integer_zero_node, integer_one_node);
numiter_a = number_of_iterations_in_loop
(current_loops->parray[CHREC_VARIABLE (chrec_a)]);
numiter_b = number_of_iterations_in_loop
(current_loops->parray[CHREC_VARIABLE (chrec_b)]);
if (TREE_CODE (numiter_a) != INTEGER_CST)
numiter_a = current_loops->parray[CHREC_VARIABLE (chrec_a)]
->estimated_nb_iterations;
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)
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
return;
} }
else if (TREE_CODE (left_a) == INTEGER_CST niter_a = int_cst_value (numiter_a);
&& TREE_CODE (left_b) == INTEGER_CST niter_b = int_cst_value (numiter_b);
&& TREE_CODE (right_a) == INTEGER_CST niter = MIN (niter_a, niter_b);
&& TREE_CODE (right_b) == INTEGER_CST
/* Both functions should have the same evolution sign. */ step_a = int_cst_value (CHREC_RIGHT (chrec_a));
&& ((tree_int_cst_sgn (right_a) > 0 step_b = int_cst_value (CHREC_RIGHT (chrec_b));
&& tree_int_cst_sgn (right_b) > 0)
|| (tree_int_cst_sgn (right_a) < 0
&& tree_int_cst_sgn (right_b) < 0)))
{
/* Here we have to solve the Diophantine equation. Reference
book: "Loop Transformations for Restructuring Compilers - The
Foundations" by Utpal Banerjee, pages 59-80.
ALPHA * X0 = BETA * Y0 + GAMMA.
with:
ALPHA = RIGHT_A
BETA = RIGHT_B
GAMMA = LEFT_B - LEFT_A
CHREC_A = {LEFT_A, +, RIGHT_A}
CHREC_B = {LEFT_B, +, RIGHT_B}
The Diophantine equation has a solution if and only if gcd
(ALPHA, BETA) divides GAMMA. This is commonly known under
the name of the "gcd-test".
*/
tree alpha, beta, gamma;
tree la, lb;
tree gcd_alpha_beta;
tree u11, u12, u21, u22;
/* Both alpha and beta have to be integer_type_node. The gcd
function does not work correctly otherwise. */
alpha = copy_node (right_a);
beta = copy_node (right_b);
la = copy_node (left_a);
lb = copy_node (left_b);
TREE_TYPE (alpha) = integer_type_node;
TREE_TYPE (beta) = integer_type_node;
TREE_TYPE (la) = integer_type_node;
TREE_TYPE (lb) = integer_type_node;
gamma = fold (build (MINUS_EXPR, integer_type_node, lb, la));
/* FIXME: Use lambda_*_Hermite for implementing Bezout. */
gcd_alpha_beta = tree_fold_bezout
(alpha,
fold (build (MULT_EXPR, integer_type_node, beta,
integer_minus_one_node)),
&u11, &u12,
&u21, &u22);
if (dump_file && (dump_flags & TDF_DETAILS)) compute_overlap_steps_for_affine_univar (niter, step_a, step_b,
overlaps_a, overlaps_b,
last_conflicts, 1);
}
else if (nb_vars_a == 2 && nb_vars_b == 1)
compute_overlap_steps_for_affine_1_2
(chrec_a, chrec_b, overlaps_a, overlaps_b, last_conflicts);
else if (nb_vars_a == 1 && nb_vars_b == 2)
compute_overlap_steps_for_affine_1_2
(chrec_b, chrec_a, overlaps_b, overlaps_a, last_conflicts);
else
{ {
fprintf (dump_file, " (alpha = "); *overlaps_a = chrec_dont_know;
print_generic_expr (dump_file, alpha, 0); *overlaps_b = chrec_dont_know;
fprintf (dump_file, ")\n (beta = "); *last_conflicts = chrec_dont_know;
print_generic_expr (dump_file, beta, 0); }
fprintf (dump_file, ")\n (gamma = "); return;
print_generic_expr (dump_file, gamma, 0);
fprintf (dump_file, ")\n (gcd_alpha_beta = ");
print_generic_expr (dump_file, gcd_alpha_beta, 0);
fprintf (dump_file, ")\n");
} }
/* U.A = S */
lambda_matrix_right_hermite (A, dim, 1, S, U);
if (S[0][0] < 0)
{
S[0][0] *= -1;
lambda_matrix_row_negate (U, dim, 0);
}
gcd_alpha_beta = S[0][0];
/* The classic "gcd-test". */ /* The classic "gcd-test". */
if (!tree_fold_divides_p (integer_type_node, gcd_alpha_beta, gamma)) if (!int_divides_p (gcd_alpha_beta, gamma))
{ {
/* The "gcd-test" has determined that there is no integer /* The "gcd-test" has determined that there is no integer
solution, i.e. there is no dependence. */ solution, i.e. there is no dependence. */
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
} }
else /* Both access functions are univariate. This includes SIV and MIV cases. */
else if (nb_vars_a == 1 && nb_vars_b == 1)
{
/* Both functions should have the same evolution sign. */
if (((A[0][0] > 0 && -A[1][0] > 0)
|| (A[0][0] < 0 && -A[1][0] < 0)))
{ {
/* The solutions are given by: /* The solutions are given by:
| |
| [GAMMA/GCD_ALPHA_BETA t].[u11 u12] = [X] | [GAMMA/GCD_ALPHA_BETA t].[u11 u12] = [x0]
| [u21 u22] [Y] | [u21 u22] [y0]
For a given integer t. Using the following variables, For a given integer t. Using the following variables,
...@@ -1067,30 +1374,48 @@ analyze_subscript_affine_affine (tree chrec_a, ...@@ -1067,30 +1374,48 @@ analyze_subscript_affine_affine (tree chrec_a,
the solutions are: the solutions are:
| x = i0 + i1 * t, | x0 = i0 + i1 * t,
| y = j0 + j1 * t. */ | y0 = j0 + j1 * t. */
tree i0, j0, i1, j1, t; int i0, j0, i1, j1;
tree gamma_gcd;
/* X0 and Y0 are the first iterations for which there is a /* X0 and Y0 are the first iterations for which there is a
dependence. X0, Y0 are two solutions of the Diophantine dependence. X0, Y0 are two solutions of the Diophantine
equation: chrec_a (X0) = chrec_b (Y0). */ equation: chrec_a (X0) = chrec_b (Y0). */
tree x0, y0; int x0, y0;
int niter, niter_a, niter_b;
/* Exact div because in this case gcd_alpha_beta divides tree numiter_a, numiter_b;
gamma. */
gamma_gcd = fold (build (EXACT_DIV_EXPR, integer_type_node, gamma, numiter_a = number_of_iterations_in_loop
gcd_alpha_beta)); (current_loops->parray[CHREC_VARIABLE (chrec_a)]);
i0 = fold (build (MULT_EXPR, integer_type_node, u11, gamma_gcd)); numiter_b = number_of_iterations_in_loop
j0 = fold (build (MULT_EXPR, integer_type_node, u12, gamma_gcd)); (current_loops->parray[CHREC_VARIABLE (chrec_b)]);
i1 = u21;
j1 = u22; if (TREE_CODE (numiter_a) != INTEGER_CST)
numiter_a = current_loops->parray[CHREC_VARIABLE (chrec_a)]
if ((tree_int_cst_sgn (i1) == 0 ->estimated_nb_iterations;
&& tree_int_cst_sgn (i0) < 0) if (TREE_CODE (numiter_b) != INTEGER_CST)
|| (tree_int_cst_sgn (j1) == 0 numiter_b = current_loops->parray[CHREC_VARIABLE (chrec_b)]
&& tree_int_cst_sgn (j0) < 0)) ->estimated_nb_iterations;
if (numiter_a == NULL_TREE || numiter_b == NULL_TREE)
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
return;
}
niter_a = int_cst_value (numiter_a);
niter_b = int_cst_value (numiter_b);
niter = MIN (niter_a, niter_b);
i0 = U[0][0] * gamma / gcd_alpha_beta;
j0 = U[0][1] * gamma / gcd_alpha_beta;
i1 = U[1][0];
j1 = U[1][1];
if ((i1 == 0 && i0 < 0)
|| (j1 == 0 && j0 < 0))
{ {
/* There is no solution. /* There is no solution.
FIXME: The case "i0 > nb_iterations, j0 > nb_iterations" FIXME: The case "i0 > nb_iterations, j0 > nb_iterations"
...@@ -1098,42 +1423,36 @@ analyze_subscript_affine_affine (tree chrec_a, ...@@ -1098,42 +1423,36 @@ analyze_subscript_affine_affine (tree chrec_a,
upper bound of the iteration domain. */ upper bound of the iteration domain. */
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
} }
else else
{ {
if (tree_int_cst_sgn (i1) > 0) if (i1 > 0)
{ {
t = fold tau1 = CEIL (-i0, i1);
(build (CEIL_DIV_EXPR, integer_type_node, tau2 = FLOOR_DIV (niter - i0, i1);
fold (build (MULT_EXPR, integer_type_node, i0,
integer_minus_one_node)), if (j1 > 0)
i1)); {
int last_conflict;
if (tree_int_cst_sgn (j1) > 0) tau1 = MAX (tau1, CEIL (-j0, j1));
{ tau2 = MIN (tau2, FLOOR_DIV (niter - j0, j1));
t = fold
(build (MAX_EXPR, integer_type_node, t, x0 = (i1 * tau1 + i0) % i1;
fold (build (CEIL_DIV_EXPR, integer_type_node, y0 = (j1 * tau1 + j0) % j1;
fold (build tau1 = (x0 - i0)/i1;
(MULT_EXPR, last_conflict = tau2 - tau1;
integer_type_node, j0,
integer_minus_one_node)),
j1))));
x0 = fold
(build (PLUS_EXPR, integer_type_node, i0,
fold (build
(MULT_EXPR, integer_type_node, i1, t))));
y0 = fold
(build (PLUS_EXPR, integer_type_node, j0,
fold (build
(MULT_EXPR, integer_type_node, j1, t))));
*overlaps_a = build_polynomial_chrec *overlaps_a = build_polynomial_chrec
(CHREC_VARIABLE (chrec_b), x0, u21); (1,
build_int_cst (NULL_TREE, x0),
build_int_cst (NULL_TREE, i1));
*overlaps_b = build_polynomial_chrec *overlaps_b = build_polynomial_chrec
(CHREC_VARIABLE (chrec_a), y0, u22); (1,
build_int_cst (NULL_TREE, y0),
build_int_cst (NULL_TREE, j1));
*last_conflicts = build_int_cst (NULL_TREE, last_conflict);
} }
else else
{ {
...@@ -1141,6 +1460,7 @@ analyze_subscript_affine_affine (tree chrec_a, ...@@ -1141,6 +1460,7 @@ analyze_subscript_affine_affine (tree chrec_a,
iteration domain for j is not checked. */ iteration domain for j is not checked. */
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
} }
} }
...@@ -1150,18 +1470,26 @@ analyze_subscript_affine_affine (tree chrec_a, ...@@ -1150,18 +1470,26 @@ analyze_subscript_affine_affine (tree chrec_a,
iteration domain for i is not checked. */ iteration domain for i is not checked. */
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
}
} }
} }
else
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
} }
} }
else else
{ {
/* For the moment, "don't know". */
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
} }
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, " (overlaps_a = "); fprintf (dump_file, " (overlaps_a = ");
...@@ -1186,7 +1514,8 @@ static void ...@@ -1186,7 +1514,8 @@ static void
analyze_siv_subscript (tree chrec_a, analyze_siv_subscript (tree chrec_a,
tree chrec_b, tree chrec_b,
tree *overlaps_a, tree *overlaps_a,
tree *overlaps_b) tree *overlaps_b,
tree *last_conflicts)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "(analyze_siv_subscript \n"); fprintf (dump_file, "(analyze_siv_subscript \n");
...@@ -1194,22 +1523,22 @@ analyze_siv_subscript (tree chrec_a, ...@@ -1194,22 +1523,22 @@ analyze_siv_subscript (tree chrec_a,
if (evolution_function_is_constant_p (chrec_a) if (evolution_function_is_constant_p (chrec_a)
&& evolution_function_is_affine_p (chrec_b)) && evolution_function_is_affine_p (chrec_b))
analyze_siv_subscript_cst_affine (chrec_a, chrec_b, analyze_siv_subscript_cst_affine (chrec_a, chrec_b,
overlaps_a, overlaps_b); overlaps_a, overlaps_b, last_conflicts);
else if (evolution_function_is_affine_p (chrec_a) else if (evolution_function_is_affine_p (chrec_a)
&& evolution_function_is_constant_p (chrec_b)) && evolution_function_is_constant_p (chrec_b))
analyze_siv_subscript_affine_cst (chrec_a, chrec_b, analyze_siv_subscript_cst_affine (chrec_b, chrec_a,
overlaps_a, overlaps_b); overlaps_b, overlaps_a, last_conflicts);
else if (evolution_function_is_affine_p (chrec_a) else if (evolution_function_is_affine_p (chrec_a)
&& evolution_function_is_affine_p (chrec_b) && evolution_function_is_affine_p (chrec_b))
&& (CHREC_VARIABLE (chrec_a) == CHREC_VARIABLE (chrec_b)))
analyze_subscript_affine_affine (chrec_a, chrec_b, analyze_subscript_affine_affine (chrec_a, chrec_b,
overlaps_a, overlaps_b); overlaps_a, overlaps_b, last_conflicts);
else else
{ {
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
} }
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
...@@ -1246,7 +1575,8 @@ static void ...@@ -1246,7 +1575,8 @@ static void
analyze_miv_subscript (tree chrec_a, analyze_miv_subscript (tree chrec_a,
tree chrec_b, tree chrec_b,
tree *overlaps_a, tree *overlaps_a,
tree *overlaps_b) tree *overlaps_b,
tree *last_conflicts)
{ {
/* FIXME: This is a MIV subscript, not yet handled. /* FIXME: This is a MIV subscript, not yet handled.
Example: (A[{1, +, 1}_1] vs. A[{1, +, 1}_2]) that comes from Example: (A[{1, +, 1}_1] vs. A[{1, +, 1}_2]) that comes from
...@@ -1269,6 +1599,8 @@ analyze_miv_subscript (tree chrec_a, ...@@ -1269,6 +1599,8 @@ analyze_miv_subscript (tree chrec_a,
in the same order. */ in the same order. */
*overlaps_a = integer_zero_node; *overlaps_a = integer_zero_node;
*overlaps_b = integer_zero_node; *overlaps_b = integer_zero_node;
*last_conflicts = number_of_iterations_in_loop
(current_loops->parray[CHREC_VARIABLE (chrec_a)]);
} }
else if (evolution_function_is_constant_p (difference) else if (evolution_function_is_constant_p (difference)
...@@ -1283,25 +1615,28 @@ analyze_miv_subscript (tree chrec_a, ...@@ -1283,25 +1615,28 @@ analyze_miv_subscript (tree chrec_a,
consequently there are no overlapping elements. */ consequently there are no overlapping elements. */
*overlaps_a = chrec_known; *overlaps_a = chrec_known;
*overlaps_b = chrec_known; *overlaps_b = chrec_known;
*last_conflicts = integer_zero_node;
} }
else if (evolution_function_is_univariate_p (chrec_a) else if (evolution_function_is_affine_multivariate_p (chrec_a)
&& evolution_function_is_univariate_p (chrec_b)) && evolution_function_is_affine_multivariate_p (chrec_b))
{ {
/* testsuite/.../ssa-chrec-35.c /* testsuite/.../ssa-chrec-35.c
{0, +, 1}_2 vs. {0, +, 1}_3 {0, +, 1}_2 vs. {0, +, 1}_3
the overlapping elements are respectively located at iterations: the overlapping elements are respectively located at iterations:
{0, +, 1}_3 and {0, +, 1}_2. {0, +, 1}_x and {0, +, 1}_x,
in other words, we have the equality:
{0, +, 1}_2 ({0, +, 1}_x) = {0, +, 1}_3 ({0, +, 1}_x)
Other examples:
{{0, +, 1}_1, +, 2}_2 ({0, +, 1}_x, {0, +, 1}_y) =
{0, +, 1}_1 ({{0, +, 1}_x, +, 2}_y)
{{0, +, 2}_1, +, 3}_2 ({0, +, 1}_y, {0, +, 1}_x) =
{{0, +, 3}_1, +, 2}_2 ({0, +, 1}_x, {0, +, 1}_y)
*/ */
if (evolution_function_is_affine_p (chrec_a)
&& evolution_function_is_affine_p (chrec_b))
analyze_subscript_affine_affine (chrec_a, chrec_b, analyze_subscript_affine_affine (chrec_a, chrec_b,
overlaps_a, overlaps_b); overlaps_a, overlaps_b, last_conflicts);
else
{
*overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know;
}
} }
else else
...@@ -1309,6 +1644,7 @@ analyze_miv_subscript (tree chrec_a, ...@@ -1309,6 +1644,7 @@ analyze_miv_subscript (tree chrec_a,
/* When the analysis is too difficult, answer "don't know". */ /* When the analysis is too difficult, answer "don't know". */
*overlaps_a = chrec_dont_know; *overlaps_a = chrec_dont_know;
*overlaps_b = chrec_dont_know; *overlaps_b = chrec_dont_know;
*last_conflicts = chrec_dont_know;
} }
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
...@@ -1329,7 +1665,8 @@ static void ...@@ -1329,7 +1665,8 @@ static void
analyze_overlapping_iterations (tree chrec_a, analyze_overlapping_iterations (tree chrec_a,
tree chrec_b, tree chrec_b,
tree *overlap_iterations_a, tree *overlap_iterations_a,
tree *overlap_iterations_b) tree *overlap_iterations_b,
tree *last_conflicts)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -1354,15 +1691,18 @@ analyze_overlapping_iterations (tree chrec_a, ...@@ -1354,15 +1691,18 @@ analyze_overlapping_iterations (tree chrec_a,
else if (ziv_subscript_p (chrec_a, chrec_b)) else if (ziv_subscript_p (chrec_a, chrec_b))
analyze_ziv_subscript (chrec_a, chrec_b, analyze_ziv_subscript (chrec_a, chrec_b,
overlap_iterations_a, overlap_iterations_b); overlap_iterations_a, overlap_iterations_b,
last_conflicts);
else if (siv_subscript_p (chrec_a, chrec_b)) else if (siv_subscript_p (chrec_a, chrec_b))
analyze_siv_subscript (chrec_a, chrec_b, analyze_siv_subscript (chrec_a, chrec_b,
overlap_iterations_a, overlap_iterations_b); overlap_iterations_a, overlap_iterations_b,
last_conflicts);
else else
analyze_miv_subscript (chrec_a, chrec_b, analyze_miv_subscript (chrec_a, chrec_b,
overlap_iterations_a, overlap_iterations_b); overlap_iterations_a, overlap_iterations_b,
last_conflicts);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -1386,6 +1726,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr) ...@@ -1386,6 +1726,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr)
unsigned int i; unsigned int i;
struct data_reference *dra = DDR_A (ddr); struct data_reference *dra = DDR_A (ddr);
struct data_reference *drb = DDR_B (ddr); struct data_reference *drb = DDR_B (ddr);
tree last_conflicts;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "(subscript_dependence_tester \n"); fprintf (dump_file, "(subscript_dependence_tester \n");
...@@ -1397,7 +1738,8 @@ subscript_dependence_tester (struct data_dependence_relation *ddr) ...@@ -1397,7 +1738,8 @@ subscript_dependence_tester (struct data_dependence_relation *ddr)
analyze_overlapping_iterations (DR_ACCESS_FN (dra, i), analyze_overlapping_iterations (DR_ACCESS_FN (dra, i),
DR_ACCESS_FN (drb, i), DR_ACCESS_FN (drb, i),
&overlaps_a, &overlaps_b); &overlaps_a, &overlaps_b,
&last_conflicts);
if (chrec_contains_undetermined (overlaps_a) if (chrec_contains_undetermined (overlaps_a)
|| chrec_contains_undetermined (overlaps_b)) || chrec_contains_undetermined (overlaps_b))
...@@ -1417,6 +1759,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr) ...@@ -1417,6 +1759,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr)
{ {
SUB_CONFLICTS_IN_A (subscript) = overlaps_a; SUB_CONFLICTS_IN_A (subscript) = overlaps_a;
SUB_CONFLICTS_IN_B (subscript) = overlaps_b; SUB_CONFLICTS_IN_B (subscript) = overlaps_b;
SUB_LAST_CONFLICT (subscript) = last_conflicts;
} }
} }
...@@ -1428,7 +1771,8 @@ subscript_dependence_tester (struct data_dependence_relation *ddr) ...@@ -1428,7 +1771,8 @@ subscript_dependence_tester (struct data_dependence_relation *ddr)
DDR is the data dependence relation to build a vector from. DDR is the data dependence relation to build a vector from.
NB_LOOPS is the total number of loops we are considering. NB_LOOPS is the total number of loops we are considering.
FIRST_LOOP is the loop->num of the first loop. */ FIRST_LOOP is the loop->num of the first loop in the analyzed
loop nest. */
static void static void
build_classic_dist_vector (struct data_dependence_relation *ddr, build_classic_dist_vector (struct data_dependence_relation *ddr,
...@@ -1447,22 +1791,68 @@ build_classic_dist_vector (struct data_dependence_relation *ddr, ...@@ -1447,22 +1791,68 @@ build_classic_dist_vector (struct data_dependence_relation *ddr,
for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++) for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
{ {
tree access_fn_a, access_fn_b;
struct subscript *subscript = DDR_SUBSCRIPT (ddr, i); struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
if (chrec_contains_undetermined (SUB_DISTANCE (subscript))) if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
{
non_affine_dependence_relation (ddr);
return; return;
}
access_fn_a = DR_ACCESS_FN (DDR_A (ddr), i);
access_fn_b = DR_ACCESS_FN (DDR_B (ddr), i);
if (TREE_CODE (access_fn_a) == POLYNOMIAL_CHREC
&& TREE_CODE (access_fn_b) == POLYNOMIAL_CHREC)
{
int dist, loop_nb;
int loop_nb_a = CHREC_VARIABLE (access_fn_a);
int loop_nb_b = CHREC_VARIABLE (access_fn_b);
struct loop *loop_a = current_loops->parray[loop_nb_a];
struct loop *loop_b = current_loops->parray[loop_nb_b];
if (TREE_CODE (SUB_CONFLICTS_IN_A (subscript)) == POLYNOMIAL_CHREC) if (loop_nb_a != loop_nb_b
&& !flow_loop_nested_p (loop_a, loop_b)
&& !flow_loop_nested_p (loop_b, loop_a))
{ {
int dist; /* Example: when there are two consecutive loops,
int loop_nb;
loop_nb = CHREC_VARIABLE (SUB_CONFLICTS_IN_A (subscript)); | loop_1
| A[{0, +, 1}_1]
| endloop_1
| loop_2
| A[{0, +, 1}_2]
| endloop_2
the dependence relation cannot be captured by the
distance abstraction. */
non_affine_dependence_relation (ddr);
return;
}
/* The dependence is carried by the outermost loop. Example:
| loop_1
| A[{4, +, 1}_1]
| loop_2
| A[{5, +, 1}_2]
| endloop_2
| endloop_1
In this case, the dependence is carried by loop_1. */
loop_nb = loop_nb_a < loop_nb_b ? loop_nb_a : loop_nb_b;
loop_nb -= first_loop; loop_nb -= first_loop;
/* If the loop number is still greater than the number of /* If the loop number is still greater than the number of
loops we've been asked to analyze, or negative, loops we've been asked to analyze, or negative,
something is borked. */ something is borked. */
gcc_assert (loop_nb >= 0); gcc_assert (loop_nb >= 0);
gcc_assert (loop_nb < nb_loops); gcc_assert (loop_nb < nb_loops);
if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
{
non_affine_dependence_relation (ddr);
return;
}
dist = int_cst_value (SUB_DISTANCE (subscript)); dist = int_cst_value (SUB_DISTANCE (subscript));
/* This is the subscript coupling test. /* This is the subscript coupling test.
...@@ -1505,6 +1895,7 @@ build_classic_dist_vector (struct data_dependence_relation *ddr, ...@@ -1505,6 +1895,7 @@ build_classic_dist_vector (struct data_dependence_relation *ddr,
lca_nb -= first_loop; lca_nb -= first_loop;
gcc_assert (lca_nb >= 0); gcc_assert (lca_nb >= 0);
gcc_assert (lca_nb < nb_loops); gcc_assert (lca_nb < nb_loops);
/* For each outer loop where init_v is not set, the accesses are /* For each outer loop where init_v is not set, the accesses are
in dependence of distance 1 in the loop. */ in dependence of distance 1 in the loop. */
if (lca != loop_a if (lca != loop_a
...@@ -1519,8 +1910,13 @@ build_classic_dist_vector (struct data_dependence_relation *ddr, ...@@ -1519,8 +1910,13 @@ build_classic_dist_vector (struct data_dependence_relation *ddr,
lca_nb = lca->num - first_loop; lca_nb = lca->num - first_loop;
while (lca->depth != 0) while (lca->depth != 0)
{ {
gcc_assert (lca_nb >= 0); /* If we're considering just a sub-nest, then don't record
any information on the outer loops. */
if (lca_nb < 0)
break;
gcc_assert (lca_nb < nb_loops); gcc_assert (lca_nb < nb_loops);
if (init_v[lca_nb] == 0) if (init_v[lca_nb] == 0)
dist_v[lca_nb] = 1; dist_v[lca_nb] = 1;
lca = lca->outer; lca = lca->outer;
...@@ -1531,13 +1927,15 @@ build_classic_dist_vector (struct data_dependence_relation *ddr, ...@@ -1531,13 +1927,15 @@ build_classic_dist_vector (struct data_dependence_relation *ddr,
} }
DDR_DIST_VECT (ddr) = dist_v; DDR_DIST_VECT (ddr) = dist_v;
DDR_SIZE_VECT (ddr) = nb_loops;
} }
/* Compute the classic per loop direction vector. /* Compute the classic per loop direction vector.
DDR is the data dependence relation to build a vector from. DDR is the data dependence relation to build a vector from.
NB_LOOPS is the total number of loops we are considering. NB_LOOPS is the total number of loops we are considering.
FIRST_LOOP is the loop->num of the first loop. */ FIRST_LOOP is the loop->num of the first loop in the analyzed
loop nest. */
static void static void
build_classic_dir_vector (struct data_dependence_relation *ddr, build_classic_dir_vector (struct data_dependence_relation *ddr,
...@@ -1556,15 +1954,55 @@ build_classic_dir_vector (struct data_dependence_relation *ddr, ...@@ -1556,15 +1954,55 @@ build_classic_dir_vector (struct data_dependence_relation *ddr,
for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++) for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
{ {
tree access_fn_a, access_fn_b;
struct subscript *subscript = DDR_SUBSCRIPT (ddr, i); struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
if (TREE_CODE (SUB_CONFLICTS_IN_A (subscript)) == POLYNOMIAL_CHREC if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
&& TREE_CODE (SUB_CONFLICTS_IN_B (subscript)) == POLYNOMIAL_CHREC)
{ {
int loop_nb; non_affine_dependence_relation (ddr);
return;
}
access_fn_a = DR_ACCESS_FN (DDR_A (ddr), i);
access_fn_b = DR_ACCESS_FN (DDR_B (ddr), i);
if (TREE_CODE (access_fn_a) == POLYNOMIAL_CHREC
&& TREE_CODE (access_fn_b) == POLYNOMIAL_CHREC)
{
int dist, loop_nb;
enum data_dependence_direction dir = dir_star; enum data_dependence_direction dir = dir_star;
loop_nb = CHREC_VARIABLE (SUB_CONFLICTS_IN_A (subscript)); int loop_nb_a = CHREC_VARIABLE (access_fn_a);
int loop_nb_b = CHREC_VARIABLE (access_fn_b);
struct loop *loop_a = current_loops->parray[loop_nb_a];
struct loop *loop_b = current_loops->parray[loop_nb_b];
if (loop_nb_a != loop_nb_b
&& !flow_loop_nested_p (loop_a, loop_b)
&& !flow_loop_nested_p (loop_b, loop_a))
{
/* Example: when there are two consecutive loops,
| loop_1
| A[{0, +, 1}_1]
| endloop_1
| loop_2
| A[{0, +, 1}_2]
| endloop_2
the dependence relation cannot be captured by the
distance abstraction. */
non_affine_dependence_relation (ddr);
return;
}
/* The dependence is carried by the outermost loop. Example:
| loop_1
| A[{4, +, 1}_1]
| loop_2
| A[{5, +, 1}_2]
| endloop_2
| endloop_1
In this case, the dependence is carried by loop_1. */
loop_nb = loop_nb_a < loop_nb_b ? loop_nb_a : loop_nb_b;
loop_nb -= first_loop; loop_nb -= first_loop;
/* If the loop number is still greater than the number of /* If the loop number is still greater than the number of
...@@ -1572,9 +2010,14 @@ build_classic_dir_vector (struct data_dependence_relation *ddr, ...@@ -1572,9 +2010,14 @@ build_classic_dir_vector (struct data_dependence_relation *ddr,
something is borked. */ something is borked. */
gcc_assert (loop_nb >= 0); gcc_assert (loop_nb >= 0);
gcc_assert (loop_nb < nb_loops); gcc_assert (loop_nb < nb_loops);
if (!chrec_contains_undetermined (SUB_DISTANCE (subscript)))
if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
{ {
int dist = int_cst_value (SUB_DISTANCE (subscript)); non_affine_dependence_relation (ddr);
return;
}
dist = int_cst_value (SUB_DISTANCE (subscript));
if (dist == 0) if (dist == 0)
dir = dir_equal; dir = dir_equal;
...@@ -1582,7 +2025,6 @@ build_classic_dir_vector (struct data_dependence_relation *ddr, ...@@ -1582,7 +2025,6 @@ build_classic_dir_vector (struct data_dependence_relation *ddr,
dir = dir_positive; dir = dir_positive;
else if (dist < 0) else if (dist < 0)
dir = dir_negative; dir = dir_negative;
}
/* This is the subscript coupling test. /* This is the subscript coupling test.
| loop i = 0, N, 1 | loop i = 0, N, 1
...@@ -1625,6 +2067,7 @@ build_classic_dir_vector (struct data_dependence_relation *ddr, ...@@ -1625,6 +2067,7 @@ build_classic_dir_vector (struct data_dependence_relation *ddr,
gcc_assert (lca_nb >= 0); gcc_assert (lca_nb >= 0);
gcc_assert (lca_nb < nb_loops); gcc_assert (lca_nb < nb_loops);
/* For each outer loop where init_v is not set, the accesses are /* For each outer loop where init_v is not set, the accesses are
in dependence of distance 1 in the loop. */ in dependence of distance 1 in the loop. */
if (lca != loop_a if (lca != loop_a
...@@ -1638,8 +2081,13 @@ build_classic_dir_vector (struct data_dependence_relation *ddr, ...@@ -1638,8 +2081,13 @@ build_classic_dir_vector (struct data_dependence_relation *ddr,
lca_nb = lca->num - first_loop; lca_nb = lca->num - first_loop;
while (lca->depth != 0) while (lca->depth != 0)
{ {
gcc_assert (lca_nb >= 0); /* If we're considering just a sub-nest, then don't record
any information on the outer loops. */
if (lca_nb < 0)
break;
gcc_assert (lca_nb < nb_loops); gcc_assert (lca_nb < nb_loops);
if (init_v[lca_nb] == 0) if (init_v[lca_nb] == 0)
dir_v[lca_nb] = dir_positive; dir_v[lca_nb] = dir_positive;
lca = lca->outer; lca = lca->outer;
...@@ -1650,6 +2098,7 @@ build_classic_dir_vector (struct data_dependence_relation *ddr, ...@@ -1650,6 +2098,7 @@ build_classic_dir_vector (struct data_dependence_relation *ddr,
} }
DDR_DIR_VECT (ddr) = dir_v; DDR_DIR_VECT (ddr) = dir_v;
DDR_SIZE_VECT (ddr) = nb_loops;
} }
/* Returns true when all the access functions of A are affine or /* Returns true when all the access functions of A are affine or
...@@ -1734,12 +2183,11 @@ compute_all_dependences (varray_type datarefs, ...@@ -1734,12 +2183,11 @@ compute_all_dependences (varray_type datarefs,
a = VARRAY_GENERIC_PTR (datarefs, i); a = VARRAY_GENERIC_PTR (datarefs, i);
b = VARRAY_GENERIC_PTR (datarefs, j); b = VARRAY_GENERIC_PTR (datarefs, j);
ddr = initialize_data_dependence_relation (a, b); ddr = initialize_data_dependence_relation (a, b);
VARRAY_PUSH_GENERIC_PTR (*dependence_relations, ddr); VARRAY_PUSH_GENERIC_PTR (*dependence_relations, ddr);
compute_affine_dependence (ddr); compute_affine_dependence (ddr);
compute_distance_vector (ddr); compute_subscript_distance (ddr);
} }
} }
...@@ -1752,9 +2200,10 @@ compute_all_dependences (varray_type datarefs, ...@@ -1752,9 +2200,10 @@ compute_all_dependences (varray_type datarefs,
acceptable for the moment, since this function is used only for acceptable for the moment, since this function is used only for
debugging purposes. */ debugging purposes. */
static tree tree
find_data_references_in_loop (struct loop *loop, varray_type *datarefs) find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
{ {
bool dont_know_node_not_inserted = true;
basic_block bb; basic_block bb;
block_stmt_iterator bsi; block_stmt_iterator bsi;
...@@ -1789,11 +2238,33 @@ find_data_references_in_loop (struct loop *loop, varray_type *datarefs) ...@@ -1789,11 +2238,33 @@ find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
true)); true));
else else
return chrec_dont_know; {
if (dont_know_node_not_inserted)
{
struct data_reference *res;
res = xmalloc (sizeof (struct data_reference));
DR_STMT (res) = NULL_TREE;
DR_REF (res) = NULL_TREE;
DR_ACCESS_FNS (res) = NULL;
DR_BASE_NAME (res) = NULL;
DR_IS_READ (res) = false;
VARRAY_PUSH_GENERIC_PTR (*datarefs, res);
dont_know_node_not_inserted = false;
}
} }
/* When there are no defs in the loop, the loop is parallel. */
if (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) > 0
|| NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)) > 0)
bb->loop_father->parallel_p = false;
}
if (bb->loop_father->estimated_nb_iterations == NULL_TREE)
compute_estimated_nb_iterations (bb->loop_father);
} }
return NULL_TREE; return dont_know_node_not_inserted ? NULL_TREE : chrec_dont_know;
} }
...@@ -1881,31 +2352,11 @@ analyze_all_data_dependences (struct loops *loops) ...@@ -1881,31 +2352,11 @@ analyze_all_data_dependences (struct loops *loops)
{ {
dump_data_dependence_relations (dump_file, dependence_relations); dump_data_dependence_relations (dump_file, dependence_relations);
fprintf (dump_file, "\n\n"); fprintf (dump_file, "\n\n");
}
/* Don't dump distances in order to avoid to update the if (dump_flags & TDF_DETAILS)
testsuite. */ dump_dist_dir_vectors (dump_file, dependence_relations);
if (dump_file && (dump_flags & TDF_DETAILS))
{
for (i = 0; i < VARRAY_ACTIVE_SIZE (dependence_relations); i++)
{
struct data_dependence_relation *ddr =
(struct data_dependence_relation *)
VARRAY_GENERIC_PTR (dependence_relations, i);
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
{
fprintf (dump_file, "DISTANCE_V (");
print_lambda_vector (dump_file, DDR_DIST_VECT (ddr), loops->num);
fprintf (dump_file, ")\n");
fprintf (dump_file, "DIRECTION_V (");
print_lambda_vector (dump_file, DDR_DIR_VECT (ddr), loops->num);
fprintf (dump_file, ")\n");
}
}
fprintf (dump_file, "\n\n");
}
if (dump_file && (dump_flags & TDF_STATS)) if (dump_flags & TDF_STATS)
{ {
unsigned nb_top_relations = 0; unsigned nb_top_relations = 0;
unsigned nb_bot_relations = 0; unsigned nb_bot_relations = 0;
...@@ -1939,6 +2390,7 @@ analyze_all_data_dependences (struct loops *loops) ...@@ -1939,6 +2390,7 @@ analyze_all_data_dependences (struct loops *loops)
gather_stats_on_scev_database (); gather_stats_on_scev_database ();
} }
}
free_dependence_relations (dependence_relations); free_dependence_relations (dependence_relations);
free_data_refs (datarefs); free_data_refs (datarefs);
...@@ -1991,3 +2443,4 @@ free_data_refs (varray_type datarefs) ...@@ -1991,3 +2443,4 @@ free_data_refs (varray_type datarefs)
} }
varray_clear (datarefs); varray_clear (datarefs);
} }
...@@ -79,10 +79,9 @@ struct subscript ...@@ -79,10 +79,9 @@ struct subscript
tree conflicting_iterations_in_a; tree conflicting_iterations_in_a;
tree conflicting_iterations_in_b; tree conflicting_iterations_in_b;
/* These fields store the information about the iteration domain /* This field stores the information about the iteration domain
validity of the dependence relation. */ validity of the dependence relation. */
tree last_conflict_in_a; tree last_conflict;
tree last_conflict_in_b;
/* Distance from the iteration that access a conflicting element in /* Distance from the iteration that access a conflicting element in
A to the iteration that access this same conflicting element in A to the iteration that access this same conflicting element in
...@@ -93,8 +92,7 @@ struct subscript ...@@ -93,8 +92,7 @@ struct subscript
#define SUB_CONFLICTS_IN_A(SUB) SUB->conflicting_iterations_in_a #define SUB_CONFLICTS_IN_A(SUB) SUB->conflicting_iterations_in_a
#define SUB_CONFLICTS_IN_B(SUB) SUB->conflicting_iterations_in_b #define SUB_CONFLICTS_IN_B(SUB) SUB->conflicting_iterations_in_b
#define SUB_LAST_CONFLICT_IN_A(SUB) SUB->last_conflict_in_a #define SUB_LAST_CONFLICT(SUB) SUB->last_conflict
#define SUB_LAST_CONFLICT_IN_B(SUB) SUB->last_conflict_in_b
#define SUB_DISTANCE(SUB) SUB->distance #define SUB_DISTANCE(SUB) SUB->distance
/* A data_dependence_relation represents a relation between two /* A data_dependence_relation represents a relation between two
...@@ -106,6 +104,10 @@ struct data_dependence_relation ...@@ -106,6 +104,10 @@ struct data_dependence_relation
struct data_reference *a; struct data_reference *a;
struct data_reference *b; struct data_reference *b;
/* When the dependence relation is affine, it can be represented by
a distance vector. */
bool affine_p;
/* A "yes/no/maybe" field for the dependence relation: /* A "yes/no/maybe" field for the dependence relation:
- when "ARE_DEPENDENT == NULL_TREE", there exist a dependence - when "ARE_DEPENDENT == NULL_TREE", there exist a dependence
...@@ -124,6 +126,9 @@ struct data_dependence_relation ...@@ -124,6 +126,9 @@ struct data_dependence_relation
the data_dependence_relation. */ the data_dependence_relation. */
varray_type subscripts; varray_type subscripts;
/* The size of the direction/distance vectors. */
int size_vect;
/* The classic direction vector. */ /* The classic direction vector. */
lambda_vector dir_vect; lambda_vector dir_vect;
...@@ -133,26 +138,32 @@ struct data_dependence_relation ...@@ -133,26 +138,32 @@ struct data_dependence_relation
#define DDR_A(DDR) DDR->a #define DDR_A(DDR) DDR->a
#define DDR_B(DDR) DDR->b #define DDR_B(DDR) DDR->b
#define DDR_AFFINE_P(DDR) DDR->affine_p
#define DDR_ARE_DEPENDENT(DDR) DDR->are_dependent #define DDR_ARE_DEPENDENT(DDR) DDR->are_dependent
#define DDR_SUBSCRIPTS(DDR) DDR->subscripts #define DDR_SUBSCRIPTS(DDR) DDR->subscripts
#define DDR_SUBSCRIPTS_VECTOR_INIT(DDR, N) \ #define DDR_SUBSCRIPTS_VECTOR_INIT(DDR, N) \
VARRAY_GENERIC_PTR_INIT (DDR_SUBSCRIPTS (DDR), N, "subscripts_vector"); VARRAY_GENERIC_PTR_INIT (DDR_SUBSCRIPTS (DDR), N, "subscripts_vector");
#define DDR_SUBSCRIPT(DDR, I) VARRAY_GENERIC_PTR (DDR_SUBSCRIPTS (DDR), I) #define DDR_SUBSCRIPT(DDR, I) VARRAY_GENERIC_PTR (DDR_SUBSCRIPTS (DDR), I)
#define DDR_NUM_SUBSCRIPTS(DDR) VARRAY_ACTIVE_SIZE (DDR_SUBSCRIPTS (DDR)) #define DDR_NUM_SUBSCRIPTS(DDR) VARRAY_ACTIVE_SIZE (DDR_SUBSCRIPTS (DDR))
#define DDR_SIZE_VECT(DDR) DDR->size_vect
#define DDR_DIR_VECT(DDR) DDR->dir_vect #define DDR_DIR_VECT(DDR) DDR->dir_vect
#define DDR_DIST_VECT(DDR) DDR->dist_vect #define DDR_DIST_VECT(DDR) DDR->dist_vect
struct data_dependence_relation *initialize_data_dependence_relation extern tree find_data_references_in_loop (struct loop *, varray_type *);
extern struct data_dependence_relation *initialize_data_dependence_relation
(struct data_reference *, struct data_reference *); (struct data_reference *, struct data_reference *);
void compute_affine_dependence (struct data_dependence_relation *); extern void compute_affine_dependence (struct data_dependence_relation *);
extern void analyze_all_data_dependences (struct loops *); extern void analyze_all_data_dependences (struct loops *);
extern void compute_data_dependences_for_loop (unsigned, struct loop *, extern void compute_data_dependences_for_loop (unsigned, struct loop *,
varray_type *, varray_type *); varray_type *, varray_type *);
extern struct data_reference * init_data_ref (tree, tree, tree, tree, bool); extern struct data_reference * init_data_ref (tree, tree, tree, tree, bool);
extern struct data_reference *analyze_array (tree, tree, bool); extern struct data_reference *analyze_array (tree, tree, bool);
extern void dump_subscript (FILE *, struct subscript *);
extern void dump_ddrs (FILE *, varray_type);
extern void dump_dist_dir_vectors (FILE *, varray_type);
extern void dump_data_reference (FILE *, struct data_reference *); extern void dump_data_reference (FILE *, struct data_reference *);
extern void dump_data_references (FILE *, varray_type); extern void dump_data_references (FILE *, varray_type);
extern void dump_data_dependence_relation (FILE *, extern void dump_data_dependence_relation (FILE *,
...@@ -161,11 +172,12 @@ extern void dump_data_dependence_relations (FILE *, varray_type); ...@@ -161,11 +172,12 @@ extern void dump_data_dependence_relations (FILE *, varray_type);
extern void dump_data_dependence_direction (FILE *, extern void dump_data_dependence_direction (FILE *,
enum data_dependence_direction); enum data_dependence_direction);
extern bool array_base_name_differ_p (struct data_reference *, extern bool array_base_name_differ_p (struct data_reference *,
struct data_reference *, bool *p); struct data_reference *, bool *);
extern void free_dependence_relation (struct data_dependence_relation *); extern void free_dependence_relation (struct data_dependence_relation *);
extern void free_dependence_relations (varray_type); extern void free_dependence_relations (varray_type);
extern void free_data_refs (varray_type); extern void free_data_refs (varray_type);
#endif /* GCC_TREE_DATA_REF_H */ #endif /* GCC_TREE_DATA_REF_H */
...@@ -36,6 +36,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -36,6 +36,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h" #include "ggc.h"
#include "tree-chrec.h" #include "tree-chrec.h"
#include "tree-scalar-evolution.h" #include "tree-scalar-evolution.h"
#include "tree-data-ref.h"
#include "params.h" #include "params.h"
#include "flags.h" #include "flags.h"
#include "tree-inline.h" #include "tree-inline.h"
...@@ -943,24 +944,10 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit) ...@@ -943,24 +944,10 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit)
*/ */
/* The structure describing a bound on number of iterations of a loop. */
struct nb_iter_bound
{
tree bound; /* The expression whose value is an upper bound on the
number of executions of anything after ... */
tree at_stmt; /* ... this statement during one execution of loop. */
tree additional; /* A conjunction of conditions the operands of BOUND
satisfy. The additional information about the value
of the bound may be derived from it. */
struct nb_iter_bound *next;
/* The next bound in a list. */
};
/* Records that AT_STMT is executed at most BOUND times in LOOP. The /* Records that AT_STMT is executed at most BOUND times in LOOP. The
additional condition ADDITIONAL is recorded with the bound. */ additional condition ADDITIONAL is recorded with the bound. */
static void void
record_estimate (struct loop *loop, tree bound, tree additional, tree at_stmt) record_estimate (struct loop *loop, tree bound, tree additional, tree at_stmt)
{ {
struct nb_iter_bound *elt = xmalloc (sizeof (struct nb_iter_bound)); struct nb_iter_bound *elt = xmalloc (sizeof (struct nb_iter_bound));
...@@ -1010,8 +997,14 @@ estimate_numbers_of_iterations_loop (struct loop *loop) ...@@ -1010,8 +997,14 @@ estimate_numbers_of_iterations_loop (struct loop *loop)
} }
free (exits); free (exits);
/* TODO Here we could use other possibilities, like bounds of arrays accessed /* Analyzes the bounds of arrays accessed in the loop. */
in the loop. */ if (loop->estimated_nb_iterations == NULL_TREE)
{
varray_type datarefs;
VARRAY_GENERIC_PTR_INIT (datarefs, 3, "datarefs");
find_data_references_in_loop (loop, &datarefs);
free_data_refs (datarefs);
}
} }
/* Records estimates on numbers of iterations of LOOPS. */ /* Records estimates on numbers of iterations of LOOPS. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment