This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Data dependence merge


Here is the updated patch, bootstrapped and tested on i686-pc-linux-gnu.
I verified by hand, I mean using gdb, that we still get the interchange 
matrix validated.

Daniel, I remember that you have worked on adding some testsuite
infrastructure for catching the linear loop transform regressions.
Is there something I can help for getting it work?


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.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1409
diff -d -u -p -r1.1409 Makefile.in
--- Makefile.in	7 Oct 2004 05:28:46 -0000	1.1409
+++ Makefile.in	11 Oct 2004 11:01:46 -0000
@@ -1706,7 +1706,7 @@ tree-ssa-loop-unswitch.o : tree-ssa-loop
 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 \
    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) \
    $(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) \
Index: cfgloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.c,v
retrieving revision 1.40
diff -d -u -p -r1.40 cfgloop.c
--- cfgloop.c	28 Sep 2004 07:59:42 -0000	1.40
+++ cfgloop.c	11 Oct 2004 11:01:46 -0000
@@ -780,6 +780,20 @@ canonicalize_loop_headers (void)
 #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
    recalculate loop_depth information in basic block structures.  FLAGS
    controls which loop information is collected.  Return the number of natural
@@ -945,6 +959,7 @@ flow_loops_find (struct loops *loops, in
 	flow_loop_scan (loops->parray[i], flags);
 
       loops->num = num_loops;
+      initialize_loops_parallel_p (loops);
     }
 
   sbitmap_free (headers);
Index: cfgloop.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.h,v
retrieving revision 1.32
diff -d -u -p -r1.32 cfgloop.h
--- cfgloop.h	23 Sep 2004 12:21:17 -0000	1.32
+++ cfgloop.h	11 Oct 2004 11:01:46 -0000
@@ -43,6 +43,20 @@ struct lpt_decision
   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.  */
 struct loop
 {
@@ -173,12 +187,22 @@ struct loop
      information in this field.  */
   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.  */
   struct nb_iter_bound *bounds;
 
   /* If not NULL, loop has just single exit edge stored here (edges to the
      EXIT_BLOCK_PTR do not count.  */
   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.  */
@@ -462,6 +486,7 @@ enum
 extern void unroll_and_peel_loops (struct loops *, int);
 extern void doloop_optimize_loops (struct loops *);
 extern void move_loop_invariants (struct loops *);
+extern void record_estimate (struct loop *, tree, tree, tree);
 
 /* Old loop optimizer interface.  */
 
Index: tree-chrec.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.c,v
retrieving revision 2.10
diff -d -u -p -r2.10 tree-chrec.c
--- tree-chrec.c	1 Oct 2004 09:05:57 -0000	2.10
+++ tree-chrec.c	11 Oct 2004 11:01:46 -0000
@@ -636,7 +636,7 @@ chrec_component_in_loop_num (tree chrec,
 }
 
 /* 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  */
 
 tree 
@@ -647,7 +647,7 @@ evolution_part_in_loop_num (tree chrec, 
 }
 
 /* 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  */
 
 tree 
@@ -932,6 +932,26 @@ evolution_function_is_univariate_p (tree
     }
 }
 
+/* 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.  */
Index: tree-chrec.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.h,v
retrieving revision 2.4
diff -d -u -p -r2.4 tree-chrec.h
--- tree-chrec.h	19 Sep 2004 18:01:47 -0000	2.4
+++ tree-chrec.h	11 Oct 2004 11:01:46 -0000
@@ -91,6 +91,7 @@ extern bool chrec_contains_undetermined 
 extern bool tree_contains_chrecs (tree);
 extern bool evolution_function_is_affine_multivariate_p (tree);
 extern bool evolution_function_is_univariate_p (tree);
+extern unsigned nb_vars_in_chrec (tree);
 
 
 
Index: tree-data-ref.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-data-ref.c,v
retrieving revision 2.10
diff -d -u -p -r2.10 tree-data-ref.c
--- tree-data-ref.c	4 Oct 2004 11:57:09 -0000	2.10
+++ tree-data-ref.c	11 Oct 2004 11:01:46 -0000
@@ -44,7 +44,7 @@ Software Foundation, 59 Temple Place - S
        - polyhedron dependence
      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,
      
    - to define an interface to access this data.
@@ -94,7 +94,6 @@ Software Foundation, 59 Temple Place - S
 #include "tree-data-ref.h"
 #include "tree-scalar-evolution.h"
 #include "tree-pass.h"
-#include "lambda.h"
 
 /* This is the simplest data dependence test: determines whether the
    data references A and B access the same array/region.  Returns
@@ -113,6 +112,7 @@ array_base_name_differ_p (struct data_re
   tree ta = TREE_TYPE (base_a);
   tree tb = TREE_TYPE (base_b);
 
+
   /* Determine if same base.  Example: for the array accesses
      a[i], b[i] or pointer accesses *a, *b, bases are a, b.  */
   if (base_a == base_b)
@@ -130,7 +130,7 @@ array_base_name_differ_p (struct data_re
       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
       && TREE_OPERAND (base_a, 0) == TREE_OPERAND (base_b, 0)
       && TREE_OPERAND (base_a, 1) == TREE_OPERAND (base_b, 1))
@@ -139,6 +139,7 @@ array_base_name_differ_p (struct data_re
       return true;
     }
 
+
   /* Determine if different bases.  */
 
   /* At this point we know that base_a != base_b.  However, pointer
@@ -206,109 +207,39 @@ tree_fold_divides_p (tree type, 
 		     tree a, 
 		     tree b)
 {
-  if (integer_onep (a))
-    return true;
-  
   /* Determines whether (A == gcd (A, B)).  */
   return integer_zerop 
     (fold (build (MINUS_EXPR, type, a, tree_fold_gcd (a, b))));
 }
 
-/* Bezout: Let A1 and A2 be two integers; there exist two integers U11
-   and U12 such that, 
-   
-   |  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
-   
-   |  (U11 U12) (A1) = (gcd)
-   |  (U21 U22) (A2)   (0)
-   
-   FIXME: Use lambda_..._hermite for implementing this function.
-*/
+/* Compute the greatest common denominator of two numbers using
+   Euclid's algorithm.  */
 
-static tree 
-tree_fold_bezout (tree a1, 
-		  tree a2,
-		  tree *u11, tree *u12,
-		  tree *u21, tree *u22)
+static int 
+gcd (int a, int b)
 {
-  tree s1, s2;
-  
-  /* Initialize S with the coefficients of A.  */
-  s1 = a1;
-  s2 = a2;
-  
-  /* Initialize the U matrix */
-  *u11 = integer_one_node; 
-  *u12 = integer_zero_node;
-  *u21 = integer_zero_node;
-  *u22 = integer_one_node;
   
-  if (integer_zerop (a1)
-      || integer_zerop (a2))
-    return integer_zero_node;
+  int x, y, z;
   
-  while (!integer_zerop (s2))
-    {
-      int sign;
-      tree z, zu21, zu22, zs2;
-      
-      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.  */
-      {
-	tree flip;
-	
-	flip = *u11;
-	*u11 = *u21;
-	*u21 = flip;
+  x = abs (a);
+  y = abs (b);
 
-	flip = *u12;
-	*u12 = *u22;
-	*u22 = flip;
-	
-	flip = s1;
-	s1 = s2;
-	s2 = flip;
-      }
-    }
-  
-  if (tree_int_cst_sgn (s1) < 0)
+  while (x>0)
     {
-      *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));
+      z = y % x;
+      y = x;
+      x = z;
     }
-  
-  return s1;
+
+  return (y);
+}
+
+/* Returns true iff A divides B.  */
+
+static inline bool 
+int_divides_p (int a, int b)
+{
+  return ((b % a) == 0);
 }
 
 
@@ -360,83 +291,85 @@ dump_data_reference (FILE *outf, 
   fprintf (outf, ")\n");
 }
 
+/* Dump function for a SUBSCRIPT structure.  */
+
+void 
+dump_subscript (FILE *outf, struct subscript *subscript)
+{
+  tree chrec = SUB_CONFLICTS_IN_A (subscript);
+
+  fprintf (outf, "\n (subscript \n");
+  fprintf (outf, "  iterations_that_access_an_element_twice_in_A: ");
+  print_generic_stmt (outf, chrec, 0);
+  if (chrec == chrec_known)
+    fprintf (outf, "    (no dependence)\n");
+  else if (chrec_contains_undetermined (chrec))
+    fprintf (outf, "    (don't know)\n");
+  else
+    {
+      tree last_iteration = SUB_LAST_CONFLICT (subscript);
+      fprintf (outf, "  last_conflict: ");
+      print_generic_stmt (outf, last_iteration, 0);
+    }
+	  
+  chrec = SUB_CONFLICTS_IN_B (subscript);
+  fprintf (outf, "  iterations_that_access_an_element_twice_in_B: ");
+  print_generic_stmt (outf, chrec, 0);
+  if (chrec == chrec_known)
+    fprintf (outf, "    (no dependence)\n");
+  else if (chrec_contains_undetermined (chrec))
+    fprintf (outf, "    (don't know)\n");
+  else
+    {
+      tree last_iteration = SUB_LAST_CONFLICT (subscript);
+      fprintf (outf, "  last_conflict: ");
+      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");
+}
+
 /* Dump function for a DATA_DEPENDENCE_RELATION structure.  */
 
 void 
 dump_data_dependence_relation (FILE *outf, 
 			       struct data_dependence_relation *ddr)
 {
-  unsigned int i;
   struct data_reference *dra, *drb;
-  
+
   dra = DDR_A (ddr);
   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, "(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");
   
-  else
+  else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
     {
+      unsigned int i;
       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: ");
-	  print_generic_stmt (outf, chrec, 0);
-	  if (chrec == chrec_known)
-	    fprintf (outf, "    (no dependence)\n");
-	  else if (chrec_contains_undetermined (chrec))
-	    fprintf (outf, "    (don't know)\n");
-	  else
-	    {
-	      tree last_iteration = SUB_LAST_CONFLICT_IN_A (subscript);
-	      fprintf (outf, "  last_iteration_that_access_an_element_twice_in_A: ");
-	      print_generic_stmt (outf, last_iteration, 0);
-	    }
-	  
-	  chrec = SUB_CONFLICTS_IN_B (subscript);
-	  fprintf (outf, "  iterations_that_access_an_element_twice_in_B: ");
-	  print_generic_stmt (outf, chrec, 0);
-	  if (chrec == chrec_known)
-	    fprintf (outf, "    (no dependence)\n");
-	  else if (chrec_contains_undetermined (chrec))
-	    fprintf (outf, "    (don't know)\n");
-	  else
-	    {
-	      tree last_iteration = SUB_LAST_CONFLICT_IN_B (subscript);
-	      fprintf (outf, "  last_iteration_that_access_an_element_twice_in_B: ");
-	      print_generic_stmt (outf, last_iteration, 0);
-	    }
-      
-	  fprintf (outf, " )\n");
+	  dump_subscript (outf, DDR_SUBSCRIPT (ddr, i));
 	}
-  
-      fprintf (outf, " (Distance Vector: \n");
-      for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
+      if (DDR_DIST_VECT (ddr))
 	{
-	  struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
-      
-	  fprintf (outf, "(");
-	  print_generic_stmt (outf, SUB_DISTANCE (subscript), 0);
-	  fprintf (outf, ")\n");
+	  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");
@@ -485,8 +418,120 @@ dump_data_dependence_direction (FILE *fi
     }
 }
 
+/* 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.
    Example: given A[i][3], record in ACCESS_FNS the opnd1 function,
    i.e. the constant "3", then recursively call the function on opnd0,
@@ -496,7 +541,7 @@ dump_data_dependence_direction (FILE *fi
 static tree
 analyze_array_indexes (struct loop *loop,
 		       varray_type *access_fns, 
-		       tree ref)
+		       tree ref, tree stmt)
 {
   tree opnd0, opnd1;
   tree access_fn;
@@ -510,12 +555,15 @@ analyze_array_indexes (struct loop *loop
      the optimizers.  */
   access_fn = instantiate_parameters 
     (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);
   
   /* Recursively record other array access functions.  */
   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.  */
   else
@@ -546,7 +594,7 @@ analyze_array (tree stmt, tree ref, bool
   DR_REF (res) = ref;
   VARRAY_TREE_INIT (DR_ACCESS_FNS (res), 3, "access_fns");
   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;
   
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -592,11 +640,31 @@ init_data_ref (tree stmt, 
 
 
 
-/* When there exists a dependence relation, determine its distance
-   vector.  */
+/* Returns true when all the functions of a tree_vec CHREC are the
+   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
-compute_distance_vector (struct data_dependence_relation *ddr)
+compute_subscript_distance (struct data_dependence_relation *ddr)
 {
   if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
     {
@@ -610,7 +678,30 @@ compute_distance_vector (struct data_dep
  	  subscript = DDR_SUBSCRIPT (ddr, i);
  	  conflicts_a = SUB_CONFLICTS_IN_A (subscript);
  	  conflicts_b = SUB_CONFLICTS_IN_B (subscript);
- 	  difference = chrec_fold_minus 
+
+	  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 
 	    (integer_type_node, conflicts_b, conflicts_a);
  	  
  	  if (evolution_function_is_constant_p (difference))
@@ -649,8 +740,12 @@ initialize_data_dependence_relation (str
   else
     {
       unsigned int i;
+      DDR_AFFINE_P (res) = true;
       DDR_ARE_DEPENDENT (res) = NULL_TREE;
       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++)
 	{
@@ -659,8 +754,7 @@ initialize_data_dependence_relation (str
 	  subscript = xmalloc (sizeof (struct subscript));
 	  SUB_CONFLICTS_IN_A (subscript) = chrec_dont_know;
 	  SUB_CONFLICTS_IN_B (subscript) = chrec_dont_know;
-	  SUB_LAST_CONFLICT_IN_A (subscript) = chrec_dont_know;
-	  SUB_LAST_CONFLICT_IN_B (subscript) = chrec_dont_know;
+	  SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
 	  SUB_DISTANCE (subscript) = chrec_dont_know;
 	  VARRAY_PUSH_GENERIC_PTR (DDR_SUBSCRIPTS (res), subscript);
 	}
@@ -687,6 +781,18 @@ finalize_ddr_dependent (struct data_depe
   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.  */
@@ -750,7 +856,8 @@ static void 
 analyze_ziv_subscript (tree chrec_a, 
 		       tree chrec_b, 
 		       tree *overlaps_a,
-		       tree *overlaps_b)
+		       tree *overlaps_b, 
+		       tree *last_conflicts)
 {
   tree difference;
   
@@ -768,12 +875,14 @@ analyze_ziv_subscript (tree chrec_a, 
 	     overlaps for each iteration in the loop.  */
 	  *overlaps_a = integer_zero_node;
 	  *overlaps_b = integer_zero_node;
+	  *last_conflicts = chrec_dont_know;
 	}
       else
 	{
 	  /* The accesses do not overlap.  */
 	  *overlaps_a = chrec_known;
-	  *overlaps_b = chrec_known;	  
+	  *overlaps_b = chrec_known;
+	  *last_conflicts = integer_zero_node;
 	}
       break;
       
@@ -781,7 +890,8 @@ analyze_ziv_subscript (tree chrec_a, 
       /* We're not sure whether the indexes overlap.  For the moment, 
 	 conservatively answer "don't know".  */
       *overlaps_a = chrec_dont_know;
-      *overlaps_b = chrec_dont_know;	  
+      *overlaps_b = chrec_dont_know;
+      *last_conflicts = chrec_dont_know;
       break;
     }
   
@@ -801,7 +911,8 @@ static void
 analyze_siv_subscript_cst_affine (tree chrec_a, 
 				  tree chrec_b,
 				  tree *overlaps_a, 
-				  tree *overlaps_b)
+				  tree *overlaps_b, 
+				  tree *last_conflicts)
 {
   bool value0, value1, value2;
   tree difference = chrec_fold_minus 
@@ -811,6 +922,7 @@ analyze_siv_subscript_cst_affine (tree c
     {
       *overlaps_a = chrec_dont_know;
       *overlaps_b = chrec_dont_know;
+      *last_conflicts = chrec_dont_know;
       return;
     }
   else
@@ -821,6 +933,7 @@ analyze_siv_subscript_cst_affine (tree c
 	    {
 	      *overlaps_a = chrec_dont_know;
 	      *overlaps_b = chrec_dont_know;      
+	      *last_conflicts = chrec_dont_know;
 	      return;
 	    }
 	  else
@@ -840,6 +953,7 @@ analyze_siv_subscript_cst_affine (tree c
 			(build (EXACT_DIV_EXPR, integer_type_node, 
 				fold (build1 (ABS_EXPR, integer_type_node, difference)), 
 				CHREC_RIGHT (chrec_b)));
+		      *last_conflicts = integer_one_node;
 		      return;
 		    }
 		  
@@ -849,6 +963,7 @@ analyze_siv_subscript_cst_affine (tree c
 		    {
 		      *overlaps_a = chrec_known;
 		      *overlaps_b = chrec_known;      
+		      *last_conflicts = integer_zero_node;
 		      return;
 		    }
 		}
@@ -862,6 +977,7 @@ analyze_siv_subscript_cst_affine (tree c
 		     In this case, chrec_a will not overlap with chrec_b.  */
 		  *overlaps_a = chrec_known;
 		  *overlaps_b = chrec_known;
+		  *last_conflicts = integer_zero_node;
 		  return;
 		}
 	    }
@@ -872,6 +988,7 @@ analyze_siv_subscript_cst_affine (tree c
 	    {
 	      *overlaps_a = chrec_dont_know;
 	      *overlaps_b = chrec_dont_know;      
+	      *last_conflicts = chrec_dont_know;
 	      return;
 	    }
 	  else
@@ -889,6 +1006,7 @@ analyze_siv_subscript_cst_affine (tree c
 		      *overlaps_b = fold 
 			(build (EXACT_DIV_EXPR, integer_type_node, difference, 
 				CHREC_RIGHT (chrec_b)));
+		      *last_conflicts = integer_one_node;
 		      return;
 		    }
 		  
@@ -898,6 +1016,7 @@ analyze_siv_subscript_cst_affine (tree c
 		    {
 		      *overlaps_a = chrec_known;
 		      *overlaps_b = chrec_known;      
+		      *last_conflicts = integer_zero_node;
 		      return;
 		    }
 		}
@@ -910,6 +1029,7 @@ analyze_siv_subscript_cst_affine (tree c
 		     In this case, chrec_a will not overlap with chrec_b.  */
 		  *overlaps_a = chrec_known;
 		  *overlaps_b = chrec_known;
+		  *last_conflicts = integer_zero_node;
 		  return;
 		}
 	    }
@@ -917,21 +1037,193 @@ analyze_siv_subscript_cst_affine (tree c
     }
 }
 
-/* Analyze a SIV (Single Index Variable) subscript where CHREC_A is an
-   affine function, and CHREC_B is a constant.  *OVERLAPS_A and
-   *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:
+/* Helper recursive function for intializing the matrix A.  Returns
+   the initial value of CHREC.  */
 
-   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(x,y) (CEIL (x, y) - ((int_divides_p (y, x)) ? 0 : 1))
+
+/* 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
-analyze_siv_subscript_affine_cst (tree chrec_a, 
-				  tree chrec_b,
-				  tree *overlaps_a, 
-				  tree *overlaps_b)
+compute_overlap_steps_for_affine_univar (int niter, int step_a, int step_b, 
+					 tree *overlaps_a, tree *overlaps_b, 
+					 tree *last_conflicts, int dim)
 {
-  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 (niter, step_overlaps_a);
+      tau2 = MIN (tau2, FLOOR (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
@@ -942,10 +1234,14 @@ static void
 analyze_subscript_affine_affine (tree chrec_a, 
 				 tree chrec_b,
 				 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))
     fprintf (dump_file, "(analyze_subscript_affine_affine \n");
   
@@ -960,137 +1256,166 @@ analyze_subscript_affine_affine (tree ch
      there is no dependence.  This function outputs a description of
      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)))
-    {
-      /* The first element accessed twice is on the first
-	 iteration.  */
-      *overlaps_a = build_polynomial_chrec 
-	(CHREC_VARIABLE (chrec_b), integer_zero_node, integer_one_node);
-      *overlaps_b = build_polynomial_chrec 
-	(CHREC_VARIABLE (chrec_a), integer_zero_node, integer_one_node);
-    }
-  
-  else if (TREE_CODE (left_a) == INTEGER_CST
-	   && TREE_CODE (left_b) == INTEGER_CST
-	   && TREE_CODE (right_a) == INTEGER_CST 
-	   && TREE_CODE (right_b) == INTEGER_CST
-	   
-	   /* Both functions should have the same evolution sign.  */
-	   && ((tree_int_cst_sgn (right_a) > 0 
-		&& 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;
+  nb_vars_a = nb_vars_in_chrec (chrec_a);
+  nb_vars_b = nb_vars_in_chrec (chrec_b);
 
-      /* 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))
+  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)
+    {
+      if (nb_vars_a == 1 && nb_vars_b == 1)
 	{
-	  fprintf (dump_file, "  (alpha = ");
-	  print_generic_expr (dump_file, alpha, 0);
-	  fprintf (dump_file, ")\n  (beta = ");
-	  print_generic_expr (dump_file, beta, 0);
-	  fprintf (dump_file, ")\n  (gamma = ");
-	  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");
+	  int step_a, step_b;
+	  int niter, niter_a, niter_b;
+	  tree numiter_a, numiter_b;
+
+	  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;
+	    }
+
+	  niter_a = int_cst_value (numiter_a);
+	  niter_b = int_cst_value (numiter_b);
+	  niter = MIN (niter_a, niter_b);
+
+	  step_a = int_cst_value (CHREC_RIGHT (chrec_a));
+	  step_b = int_cst_value (CHREC_RIGHT (chrec_b));
+
+	  compute_overlap_steps_for_affine_univar (niter, step_a, step_b, 
+						   overlaps_a, overlaps_b, 
+						   last_conflicts, 1);
 	}
-      
-      /* The classic "gcd-test".  */
-      if (!tree_fold_divides_p (integer_type_node, gcd_alpha_beta, gamma))
+
+      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
 	{
-	  /* The "gcd-test" has determined that there is no integer
-	     solution, i.e. there is no dependence.  */
-	  *overlaps_a = chrec_known;
-	  *overlaps_b = chrec_known;
+	  *overlaps_a = chrec_dont_know;
+	  *overlaps_b = chrec_dont_know;
+	  *last_conflicts = chrec_dont_know;
 	}
-      
-      else
+      return;
+    }
+
+  /* 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".  */
+  if (!int_divides_p (gcd_alpha_beta, gamma))
+    {
+      /* The "gcd-test" has determined that there is no integer
+	 solution, i.e. there is no dependence.  */
+      *overlaps_a = chrec_known;
+      *overlaps_b = chrec_known;
+      *last_conflicts = integer_zero_node;
+    }
+
+  /* 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:
 	     | 
-	     | [GAMMA/GCD_ALPHA_BETA  t].[u11 u12]  = [X]
-	     |                           [u21 u22]    [Y]
-	     
+	     | [GAMMA/GCD_ALPHA_BETA  t].[u11 u12]  = [x0]
+	     |                           [u21 u22]    [y0]
+	 
 	     For a given integer t.  Using the following variables,
-	     
+	 
 	     | i0 = u11 * gamma / gcd_alpha_beta
 	     | j0 = u12 * gamma / gcd_alpha_beta
 	     | i1 = u21
 	     | j1 = u22
-	     
+	 
 	     the solutions are:
-	     
-	     | x = i0 + i1 * t, 
-	     | y = j0 + j1 * t.  */
-	  
-	  tree i0, j0, i1, j1, t;
-	  tree gamma_gcd;
-	  
+	 
+	     | x0 = i0 + i1 * t, 
+	     | y0 = j0 + j1 * t.  */
+      
+	  int i0, j0, i1, j1;
+
 	  /* X0 and Y0 are the first iterations for which there is a
 	     dependence.  X0, Y0 are two solutions of the Diophantine
 	     equation: chrec_a (X0) = chrec_b (Y0).  */
-	  tree x0, y0;
-      
-	  /* Exact div because in this case gcd_alpha_beta divides
-	     gamma.  */
-	  gamma_gcd = fold (build (EXACT_DIV_EXPR, integer_type_node, gamma, 
-				   gcd_alpha_beta));
-	  i0 = fold (build (MULT_EXPR, integer_type_node, u11, gamma_gcd));
-	  j0 = fold (build (MULT_EXPR, integer_type_node, u12, gamma_gcd));
-	  i1 = u21;
-	  j1 = u22;
-	  
-	  if ((tree_int_cst_sgn (i1) == 0
-	       && tree_int_cst_sgn (i0) < 0)
-	      || (tree_int_cst_sgn (j1) == 0
-		  && tree_int_cst_sgn (j0) < 0))
+	  int x0, y0;
+	  int niter, niter_a, niter_b;
+	  tree numiter_a, numiter_b;
+
+	  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;
+	    }
+
+	  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.  
 		 FIXME: The case "i0 > nb_iterations, j0 > nb_iterations" 
@@ -1098,42 +1423,36 @@ analyze_subscript_affine_affine (tree ch
 		 upper bound of the iteration domain.  */
 	      *overlaps_a = chrec_known;
 	      *overlaps_b = chrec_known;
-  	    }
-	  
+	      *last_conflicts = integer_zero_node;
+	    }
+
 	  else 
 	    {
-	      if (tree_int_cst_sgn (i1) > 0)
+	      if (i1 > 0)
 		{
-		  t = fold 
-		    (build (CEIL_DIV_EXPR, integer_type_node, 
-			    fold (build (MULT_EXPR, integer_type_node, i0, 
-					 integer_minus_one_node)), 
-			    i1));
-		  
-		  if (tree_int_cst_sgn (j1) > 0)
+		  tau1 = CEIL (-i0, i1);
+		  tau2 = FLOOR (niter - i0, i1);
+
+		  if (j1 > 0)
 		    {
-		      t = fold 
-			(build (MAX_EXPR, integer_type_node, t,
-				fold (build (CEIL_DIV_EXPR, integer_type_node,
-					     fold (build 
-						   (MULT_EXPR,
-						    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 
-			(CHREC_VARIABLE (chrec_b), x0, u21);
-		      *overlaps_b = build_polynomial_chrec 
-			(CHREC_VARIABLE (chrec_a), y0, u22);
+		      int last_conflict;
+		      tau1 = MAX (tau1, CEIL (-j0, j1));
+		      tau2 = MIN (tau2, FLOOR (niter - j0, j1));
+
+		      x0 = (i1 * tau1 + i0) % i1;
+		      y0 = (j1 * tau1 + j0) % j1;
+		      tau1 = (x0 - i0)/i1;
+		      last_conflict = tau2 - tau1;
+
+		      *overlaps_a = build_polynomial_chrec
+			(1,
+			 build_int_cst (NULL_TREE, x0),
+			 build_int_cst (NULL_TREE, i1));
+		      *overlaps_b = build_polynomial_chrec
+			(1,
+			 build_int_cst (NULL_TREE, y0),
+			 build_int_cst (NULL_TREE, j1));
+		      *last_conflicts = build_int_cst (NULL_TREE, last_conflict);
 		    }
 		  else
 		    {
@@ -1141,27 +1460,36 @@ analyze_subscript_affine_affine (tree ch
 			 iteration domain for j is not checked. */
 		      *overlaps_a = chrec_dont_know;
 		      *overlaps_b = chrec_dont_know;
+		      *last_conflicts = chrec_dont_know;
 		    }
 		}
-	      
+	  
 	      else
 		{
 		  /* FIXME: For the moment, the upper bound of the
 		     iteration domain for i is not checked. */
 		  *overlaps_a = 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
     {
-      /* For the moment, "don't know".  */
       *overlaps_a = chrec_dont_know;
       *overlaps_b = chrec_dont_know;
+      *last_conflicts = chrec_dont_know;
     }
-  
+
+
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "  (overlaps_a = ");
@@ -1186,7 +1514,8 @@ static void
 analyze_siv_subscript (tree chrec_a, 
 		       tree chrec_b,
 		       tree *overlaps_a, 
-		       tree *overlaps_b)
+		       tree *overlaps_b, 
+		       tree *last_conflicts)
 {
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "(analyze_siv_subscript \n");
@@ -1194,22 +1523,22 @@ analyze_siv_subscript (tree chrec_a, 
   if (evolution_function_is_constant_p (chrec_a)
       && evolution_function_is_affine_p (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)
 	   && evolution_function_is_constant_p (chrec_b))
-    analyze_siv_subscript_affine_cst (chrec_a, chrec_b, 
-				      overlaps_a, overlaps_b);
+    analyze_siv_subscript_cst_affine (chrec_b, chrec_a, 
+				      overlaps_b, overlaps_a, last_conflicts);
   
   else if (evolution_function_is_affine_p (chrec_a)
-	   && evolution_function_is_affine_p (chrec_b)
-	   && (CHREC_VARIABLE (chrec_a) == CHREC_VARIABLE (chrec_b)))
+	   && evolution_function_is_affine_p (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;
+      *last_conflicts = chrec_dont_know;
     }
   
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1246,7 +1575,8 @@ static void
 analyze_miv_subscript (tree chrec_a, 
 		       tree chrec_b, 
 		       tree *overlaps_a, 
-		       tree *overlaps_b)
+		       tree *overlaps_b, 
+		       tree *last_conflicts)
 {
   /* FIXME:  This is a MIV subscript, not yet handled.
      Example: (A[{1, +, 1}_1] vs. A[{1, +, 1}_2]) that comes from 
@@ -1269,6 +1599,8 @@ analyze_miv_subscript (tree chrec_a, 
 	 in the same order.  */
       *overlaps_a = 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)
@@ -1283,25 +1615,28 @@ analyze_miv_subscript (tree chrec_a, 
 	 consequently there are no overlapping elements.  */
       *overlaps_a = chrec_known;
       *overlaps_b = chrec_known;
+      *last_conflicts = integer_zero_node;
     }
   
-  else if (evolution_function_is_univariate_p (chrec_a)
-	   && evolution_function_is_univariate_p (chrec_b))
+  else if (evolution_function_is_affine_multivariate_p (chrec_a)
+	   && evolution_function_is_affine_multivariate_p (chrec_b))
     {
       /* testsuite/.../ssa-chrec-35.c
 	 {0, +, 1}_2  vs.  {0, +, 1}_3
 	 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, 
-					 overlaps_a, overlaps_b);
-      else
-	{
-	  *overlaps_a = chrec_dont_know;
-	  *overlaps_b = chrec_dont_know;
-	}
+      analyze_subscript_affine_affine (chrec_a, chrec_b, 
+				       overlaps_a, overlaps_b, last_conflicts);
     }
   
   else
@@ -1309,6 +1644,7 @@ analyze_miv_subscript (tree chrec_a, 
       /* When the analysis is too difficult, answer "don't know".  */
       *overlaps_a = chrec_dont_know;
       *overlaps_b = chrec_dont_know;
+      *last_conflicts = chrec_dont_know;
     }
   
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1329,7 +1665,8 @@ static void 
 analyze_overlapping_iterations (tree chrec_a, 
 				tree chrec_b, 
 				tree *overlap_iterations_a, 
-				tree *overlap_iterations_b)
+				tree *overlap_iterations_b, 
+				tree *last_conflicts)
 {
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -1354,15 +1691,18 @@ analyze_overlapping_iterations (tree chr
   
   else if (ziv_subscript_p (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))
     analyze_siv_subscript (chrec_a, chrec_b, 
-			   overlap_iterations_a, overlap_iterations_b);
+			   overlap_iterations_a, overlap_iterations_b, 
+			   last_conflicts);
   
   else
     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))
     {
@@ -1386,6 +1726,7 @@ subscript_dependence_tester (struct data
   unsigned int i;
   struct data_reference *dra = DDR_A (ddr);
   struct data_reference *drb = DDR_B (ddr);
+  tree last_conflicts;
   
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "(subscript_dependence_tester \n");
@@ -1397,7 +1738,8 @@ subscript_dependence_tester (struct data
       
       analyze_overlapping_iterations (DR_ACCESS_FN (dra, i), 
 				      DR_ACCESS_FN (drb, i),
-				      &overlaps_a, &overlaps_b);
+				      &overlaps_a, &overlaps_b, 
+				      &last_conflicts);
       
       if (chrec_contains_undetermined (overlaps_a)
  	  || chrec_contains_undetermined (overlaps_b))
@@ -1417,6 +1759,7 @@ subscript_dependence_tester (struct data
  	{
  	  SUB_CONFLICTS_IN_A (subscript) = overlaps_a;
  	  SUB_CONFLICTS_IN_B (subscript) = overlaps_b;
+	  SUB_LAST_CONFLICT (subscript) = last_conflicts;
  	}
     }
   
@@ -1428,7 +1771,8 @@ subscript_dependence_tester (struct data
 
    DDR is the data dependence relation to build a vector from.
    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
 build_classic_dist_vector (struct data_dependence_relation *ddr, 
@@ -1447,22 +1791,68 @@ build_classic_dist_vector (struct data_d
   
   for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
     {
+      tree access_fn_a, access_fn_b;
       struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
 
       if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
-	return;
+	{
+	  non_affine_dependence_relation (ddr);
+	  return;
+	}
 
-      if (TREE_CODE (SUB_CONFLICTS_IN_A (subscript)) == POLYNOMIAL_CHREC)
+      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;
-	  int loop_nb;
-	  loop_nb = CHREC_VARIABLE (SUB_CONFLICTS_IN_A (subscript));
+	  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 (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;
+
 	  /* If the loop number is still greater than the number of
 	     loops we've been asked to analyze, or negative,
 	     something is borked.  */
 	  gcc_assert (loop_nb >= 0);
 	  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));
 
 	  /* This is the subscript coupling test.  
@@ -1505,6 +1895,7 @@ build_classic_dist_vector (struct data_d
     lca_nb -= first_loop;
     gcc_assert (lca_nb >= 0);
     gcc_assert (lca_nb < nb_loops);
+
     /* For each outer loop where init_v is not set, the accesses are
        in dependence of distance 1 in the loop.  */
     if (lca != loop_a
@@ -1519,8 +1910,13 @@ build_classic_dist_vector (struct data_d
 	lca_nb = lca->num - first_loop;
 	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);
+
 	    if (init_v[lca_nb] == 0)
 	      dist_v[lca_nb] = 1;
 	    lca = lca->outer;
@@ -1531,13 +1927,15 @@ build_classic_dist_vector (struct data_d
   }
   
   DDR_DIST_VECT (ddr) = dist_v;
+  DDR_SIZE_VECT (ddr) = nb_loops;
 }
 
 /* Compute the classic per loop direction vector.  
 
    DDR is the data dependence relation to build a vector from.
    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
 build_classic_dir_vector (struct data_dependence_relation *ddr, 
@@ -1556,15 +1954,55 @@ build_classic_dir_vector (struct data_de
   
   for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
     {
+      tree access_fn_a, access_fn_b;
       struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
 
-      if (TREE_CODE (SUB_CONFLICTS_IN_A (subscript)) == POLYNOMIAL_CHREC
-	  && TREE_CODE (SUB_CONFLICTS_IN_B (subscript)) == POLYNOMIAL_CHREC)
+      if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
 	{
-	  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;
-	  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;
 
 	  /* If the loop number is still greater than the number of
@@ -1572,17 +2010,21 @@ build_classic_dir_vector (struct data_de
 	     something is borked.  */
 	  gcc_assert (loop_nb >= 0);
 	  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));
-	      
-	      if (dist == 0)
-		dir = dir_equal;
-	      else if (dist > 0)
-		dir = dir_positive;
-	      else if (dist < 0)
-		dir = dir_negative;
+	      non_affine_dependence_relation (ddr);
+	      return;
 	    }
+
+	  dist = int_cst_value (SUB_DISTANCE (subscript));
+
+	  if (dist == 0)
+	    dir = dir_equal;
+	  else if (dist > 0)
+	    dir = dir_positive;
+	  else if (dist < 0)
+	    dir = dir_negative;
 	  
 	  /* This is the subscript coupling test.  
 	     | loop i = 0, N, 1
@@ -1625,6 +2067,7 @@ build_classic_dir_vector (struct data_de
 
     gcc_assert (lca_nb >= 0);
     gcc_assert (lca_nb < nb_loops);
+
     /* For each outer loop where init_v is not set, the accesses are
        in dependence of distance 1 in the loop.  */
     if (lca != loop_a
@@ -1638,8 +2081,13 @@ build_classic_dir_vector (struct data_de
 	lca_nb = lca->num - first_loop;
 	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);
+
 	    if (init_v[lca_nb] == 0)
 	      dir_v[lca_nb] = dir_positive;
 	    lca = lca->outer;
@@ -1650,6 +2098,7 @@ build_classic_dir_vector (struct data_de
   }
   
   DDR_DIR_VECT (ddr) = dir_v;
+  DDR_SIZE_VECT (ddr) = nb_loops;
 }
 
 /* Returns true when all the access functions of A are affine or
@@ -1734,12 +2183,11 @@ compute_all_dependences (varray_type dat
 
 	a = VARRAY_GENERIC_PTR (datarefs, i);
 	b = VARRAY_GENERIC_PTR (datarefs, j);
-
 	ddr = initialize_data_dependence_relation (a, b);
 
 	VARRAY_PUSH_GENERIC_PTR (*dependence_relations, ddr);
 	compute_affine_dependence (ddr);
-	compute_distance_vector (ddr);
+	compute_subscript_distance (ddr);
       }
 }
 
@@ -1752,12 +2200,13 @@ compute_all_dependences (varray_type dat
    acceptable for the moment, since this function is used only for
    debugging purposes.  */
 
-static tree 
+tree 
 find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
 {
+  bool dont_know_node_not_inserted = true;
   basic_block bb;
   block_stmt_iterator bsi;
-  
+
   FOR_EACH_BB (bb)
     {
       if (!flow_bb_inside_loop_p (loop, bb))
@@ -1789,11 +2238,33 @@ find_data_references_in_loop (struct loo
 					       true));
 
   	  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,63 +2352,44 @@ analyze_all_data_dependences (struct loo
     {
       dump_data_dependence_relations (dump_file, dependence_relations);
       fprintf (dump_file, "\n\n");
-    }
 
-  /* Don't dump distances in order to avoid to update the
-     testsuite.  */
-  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))
-    {
-      unsigned nb_top_relations = 0;
-      unsigned nb_bot_relations = 0;
-      unsigned nb_basename_differ = 0;
-      unsigned nb_chrec_relations = 0;
+      if (dump_flags & TDF_DETAILS)
+	dump_dist_dir_vectors (dump_file, dependence_relations);
 
-      for (i = 0; i < VARRAY_ACTIVE_SIZE (dependence_relations); i++)
+      if (dump_flags & TDF_STATS)
 	{
-	  struct data_dependence_relation *ddr;
-	  ddr = VARRAY_GENERIC_PTR (dependence_relations, i);
+	  unsigned nb_top_relations = 0;
+	  unsigned nb_bot_relations = 0;
+	  unsigned nb_basename_differ = 0;
+	  unsigned nb_chrec_relations = 0;
+
+	  for (i = 0; i < VARRAY_ACTIVE_SIZE (dependence_relations); i++)
+	    {
+	      struct data_dependence_relation *ddr;
+	      ddr = VARRAY_GENERIC_PTR (dependence_relations, i);
 	  
-	  if (chrec_contains_undetermined (DDR_ARE_DEPENDENT (ddr)))
-	    nb_top_relations++;
+	      if (chrec_contains_undetermined (DDR_ARE_DEPENDENT (ddr)))
+		nb_top_relations++;
 	  
-	  else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
-	    {
-	      struct data_reference *a = DDR_A (ddr);
-	      struct data_reference *b = DDR_B (ddr);
-	      bool differ_p;	
+	      else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
+		{
+		  struct data_reference *a = DDR_A (ddr);
+		  struct data_reference *b = DDR_B (ddr);
+		  bool differ_p;	
 	      
-	      if (DR_NUM_DIMENSIONS (a) != DR_NUM_DIMENSIONS (b)
-		  || (array_base_name_differ_p (a, b, &differ_p) && differ_p))
-		nb_basename_differ++;
-	      else
-		nb_bot_relations++;
-	    }
+		  if (DR_NUM_DIMENSIONS (a) != DR_NUM_DIMENSIONS (b)
+		      || (array_base_name_differ_p (a, b, &differ_p) && differ_p))
+		    nb_basename_differ++;
+		  else
+		    nb_bot_relations++;
+		}
 	  
-	  else 
-	    nb_chrec_relations++;
-	}
+	      else 
+		nb_chrec_relations++;
+	    }
       
-      gather_stats_on_scev_database ();
+	  gather_stats_on_scev_database ();
+	}
     }
 
   free_dependence_relations (dependence_relations);
@@ -1991,3 +2443,4 @@ free_data_refs (varray_type datarefs)
     }
   varray_clear (datarefs);
 }
+
Index: tree-data-ref.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-data-ref.h,v
retrieving revision 2.4
diff -d -u -p -r2.4 tree-data-ref.h
--- tree-data-ref.h	10 Sep 2004 15:09:38 -0000	2.4
+++ tree-data-ref.h	11 Oct 2004 11:01:46 -0000
@@ -79,10 +79,9 @@ struct subscript
   tree conflicting_iterations_in_a;
   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.  */
-  tree last_conflict_in_a;
-  tree last_conflict_in_b;
+  tree last_conflict;
   
   /* Distance from the iteration that access a conflicting element in
      A to the iteration that access this same conflicting element in
@@ -93,8 +92,7 @@ struct subscript
 
 #define SUB_CONFLICTS_IN_A(SUB) SUB->conflicting_iterations_in_a
 #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_IN_B(SUB) SUB->last_conflict_in_b
+#define SUB_LAST_CONFLICT(SUB) SUB->last_conflict
 #define SUB_DISTANCE(SUB) SUB->distance
 
 /* A data_dependence_relation represents a relation between two
@@ -106,6 +104,10 @@ struct data_dependence_relation
   struct data_reference *a;
   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:
      
      - when "ARE_DEPENDENT == NULL_TREE", there exist a dependence
@@ -124,6 +126,9 @@ struct data_dependence_relation
      the data_dependence_relation.  */
   varray_type subscripts;
 
+  /* The size of the direction/distance vectors.  */
+  int size_vect;
+
   /* The classic direction vector.  */
   lambda_vector dir_vect;
 
@@ -133,26 +138,32 @@ struct data_dependence_relation
 
 #define DDR_A(DDR) DDR->a
 #define DDR_B(DDR) DDR->b
+#define DDR_AFFINE_P(DDR) DDR->affine_p
 #define DDR_ARE_DEPENDENT(DDR) DDR->are_dependent
 #define DDR_SUBSCRIPTS(DDR) DDR->subscripts
 #define DDR_SUBSCRIPTS_VECTOR_INIT(DDR, N) \
   VARRAY_GENERIC_PTR_INIT (DDR_SUBSCRIPTS (DDR), N, "subscripts_vector");
 #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_SIZE_VECT(DDR) DDR->size_vect
 #define DDR_DIR_VECT(DDR) DDR->dir_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 *);
-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 compute_data_dependences_for_loop (unsigned, struct loop *, 
 					       varray_type *, varray_type *);
 extern struct data_reference * init_data_ref (tree, tree, 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_references (FILE *, varray_type);
 extern void dump_data_dependence_relation (FILE *, 
@@ -161,11 +172,12 @@ extern void dump_data_dependence_relatio
 extern void dump_data_dependence_direction (FILE *, 
 					    enum data_dependence_direction);
 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_relations (varray_type);
 extern void free_data_refs (varray_type);
 
+
 
 
 #endif  /* GCC_TREE_DATA_REF_H  */
Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-niter.c,v
retrieving revision 2.10
diff -d -u -p -r2.10 tree-ssa-loop-niter.c
--- tree-ssa-loop-niter.c	1 Oct 2004 09:06:06 -0000	2.10
+++ tree-ssa-loop-niter.c	11 Oct 2004 11:01:47 -0000
@@ -36,6 +36,7 @@ Software Foundation, 59 Temple Place - S
 #include "ggc.h"
 #include "tree-chrec.h"
 #include "tree-scalar-evolution.h"
+#include "tree-data-ref.h"
 #include "params.h"
 #include "flags.h"
 #include "tree-inline.h"
@@ -943,24 +944,10 @@ find_loop_niter_by_eval (struct loop *lo
 
 */
 
-/* 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
    additional condition ADDITIONAL is recorded with the bound.  */
 
-static void
+void
 record_estimate (struct loop *loop, tree bound, tree additional, tree at_stmt)
 {
   struct nb_iter_bound *elt = xmalloc (sizeof (struct nb_iter_bound));
@@ -1010,8 +997,14 @@ estimate_numbers_of_iterations_loop (str
     }
   free (exits);
   
-  /* TODO Here we could use other possibilities, like bounds of arrays accessed
-     in the loop.  */
+  /* Analyzes the bounds of arrays accessed 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.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]