OSDN Git Service

PR fortran/31266
[pf3gnuchains/gcc-fork.git] / gcc / tree-data-ref.c
index d49d682..ac5aa50 100644 (file)
@@ -1,5 +1,5 @@
 /* Data references and dependences detectors.
-   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    Contributed by Sebastian Pop <pop@cri.ensmp.fr>
 
 This file is part of GCC.
@@ -125,10 +125,6 @@ static struct datadep_stats
 static tree object_analysis (tree, tree, bool, struct data_reference **, 
                             tree *, tree *, tree *, tree *, tree *,
                             struct ptr_info_def **, subvar_t *);
-static struct data_reference * init_data_ref (tree, tree, tree, tree, bool, 
-                                             tree, tree, tree, tree, tree, 
-                                             struct ptr_info_def *,
-                                             enum  data_ref_type);
 static bool subscript_dependence_tester_1 (struct data_dependence_relation *,
                                           struct data_reference *,
                                           struct data_reference *);
@@ -172,6 +168,7 @@ ptr_ptr_may_alias_p (tree ptr_a, tree ptr_b,
   tree tag_a = NULL_TREE, tag_b = NULL_TREE;
   struct ptr_info_def *pi_a = DR_PTR_INFO (dra);  
   struct ptr_info_def *pi_b = DR_PTR_INFO (drb);  
+  bitmap bal1, bal2;
 
   if (pi_a && pi_a->name_mem_tag && pi_b && pi_b->name_mem_tag)
     {
@@ -192,7 +189,19 @@ ptr_ptr_may_alias_p (tree ptr_a, tree ptr_b,
       if (!tag_b)
        return false;
     }
-  *aliased = (tag_a == tag_b);
+  bal1 = BITMAP_ALLOC (NULL);
+  bitmap_set_bit (bal1, DECL_UID (tag_a));
+  if (MTAG_P (tag_a) && MTAG_ALIASES (tag_a))
+    bitmap_ior_into (bal1, MTAG_ALIASES (tag_a));
+
+  bal2 = BITMAP_ALLOC (NULL);
+  bitmap_set_bit (bal2, DECL_UID (tag_b));
+  if (MTAG_P (tag_b) && MTAG_ALIASES (tag_b))
+    bitmap_ior_into (bal2, MTAG_ALIASES (tag_b));
+  *aliased = bitmap_intersect_p (bal1, bal2);
+
+  BITMAP_FREE (bal1);
+  BITMAP_FREE (bal2);
   return true;
 }
 
@@ -819,6 +828,7 @@ dump_data_dependence_relation (FILE *outf,
          dump_subscript (outf, DDR_SUBSCRIPT (ddr, i));
        }
 
+      fprintf (outf, "  inner loop index: %d\n", DDR_INNER_LOOP (ddr));
       fprintf (outf, "  loop nest: (");
       for (i = 0; VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
        fprintf (outf, "%d ", loopi->num);
@@ -972,27 +982,24 @@ analyze_array_indexes (struct loop *loop,
    set to true when REF is in the right hand side of an
    assignment.  */
 
-struct data_reference *
-analyze_array (tree stmt, tree ref, bool is_read)
+static struct data_reference *
+init_array_ref (tree stmt, tree ref, bool is_read)
 {
-  struct data_reference *res;
-  VEC(tree,heap) *acc_fns;
+  struct loop *loop = loop_containing_stmt (stmt);
+  VEC(tree,heap) *acc_fns = VEC_alloc (tree, heap, 3);
+  struct data_reference *res = XNEW (struct data_reference);;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
-      fprintf (dump_file, "(analyze_array \n");
+      fprintf (dump_file, "(init_array_ref \n");
       fprintf (dump_file, "  (ref = ");
       print_generic_stmt (dump_file, ref, 0);
       fprintf (dump_file, ")\n");
     }
 
-  res = XNEW (struct data_reference);
-
   DR_STMT (res) = stmt;
   DR_REF (res) = ref;
-  acc_fns = VEC_alloc (tree, heap, 3);
-  DR_BASE_OBJECT (res) = analyze_array_indexes
-    (loop_containing_stmt (stmt), &acc_fns, ref, stmt);
+  DR_BASE_OBJECT (res) = analyze_array_indexes (loop, &acc_fns, ref, stmt);
   DR_TYPE (res) = ARRAY_REF_TYPE;
   DR_SET_ACCESS_FNS (res, acc_fns);
   DR_IS_READ (res) = is_read;
@@ -1010,6 +1017,45 @@ analyze_array (tree stmt, tree ref, bool is_read)
   return res;
 }
 
+/* For a data reference REF contained in the statement STMT, initialize
+   a DATA_REFERENCE structure, and return it.  */
+
+static struct data_reference *
+init_pointer_ref (tree stmt, tree ref, tree access_fn, bool is_read,
+                 tree base_address, tree step, struct ptr_info_def *ptr_info)
+{
+  struct data_reference *res = XNEW (struct data_reference);
+  VEC(tree,heap) *acc_fns = VEC_alloc (tree, heap, 3);
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "(init_pointer_ref \n");
+      fprintf (dump_file, "  (ref = ");
+      print_generic_stmt (dump_file, ref, 0);
+      fprintf (dump_file, ")\n");
+    }
+
+  DR_STMT (res) = stmt;
+  DR_REF (res) = ref;
+  DR_BASE_OBJECT (res) = NULL_TREE;
+  DR_TYPE (res) = POINTER_REF_TYPE;
+  DR_SET_ACCESS_FNS (res, acc_fns);
+  VEC_quick_push (tree, DR_ACCESS_FNS (res), access_fn);
+  DR_IS_READ (res) = is_read;
+  DR_BASE_ADDRESS (res) = base_address;
+  DR_OFFSET (res) = NULL_TREE;
+  DR_INIT (res) = NULL_TREE;
+  DR_STEP (res) = step;
+  DR_OFFSET_MISALIGNMENT (res) = NULL_TREE;
+  DR_MEMTAG (res) = NULL_TREE;
+  DR_PTR_INFO (res) = ptr_info;
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, ")\n");
+
+  return res;
+}
+
 /* Analyze an indirect memory reference, REF, that comes from STMT.
    IS_READ is true if this is an indirect load, and false if it is
    an indirect store.
@@ -1050,7 +1096,7 @@ analyze_indirect_ref (tree stmt, tree ref, bool is_read)
 
   if (!expr_invariant_in_loop_p (loop, init))
     {
-    if (dump_file && (dump_flags & TDF_DETAILS))
+      if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "\ninitial condition is not loop invariant.\n");    
     }
   else
@@ -1074,61 +1120,8 @@ analyze_indirect_ref (tree stmt, tree ref, bool is_read)
        if (dump_file && (dump_flags & TDF_DETAILS))
          fprintf (dump_file, "\nunknown evolution of ptr.\n"); 
     }
-  return init_data_ref (stmt, ref, NULL_TREE, access_fn, is_read, base_address, 
-                       NULL_TREE, step, NULL_TREE, NULL_TREE, 
-                       ptr_info, POINTER_REF_TYPE);
-}
-
-/* For a data reference REF contained in the statement STMT, initialize
-   a DATA_REFERENCE structure, and return it.  */
-
-struct data_reference *
-init_data_ref (tree stmt, 
-              tree ref,
-              tree base,
-              tree access_fn,
-              bool is_read,
-              tree base_address,
-              tree init_offset,
-              tree step,
-              tree misalign,
-              tree memtag,
-               struct ptr_info_def *ptr_info,
-              enum data_ref_type type)
-{
-  struct data_reference *res;
-  VEC(tree,heap) *acc_fns;
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "(init_data_ref \n");
-      fprintf (dump_file, "  (ref = ");
-      print_generic_stmt (dump_file, ref, 0);
-      fprintf (dump_file, ")\n");
-    }
-
-  res = XNEW (struct data_reference);
-
-  DR_STMT (res) = stmt;
-  DR_REF (res) = ref;
-  DR_BASE_OBJECT (res) = base;
-  DR_TYPE (res) = type;
-  acc_fns = VEC_alloc (tree, heap, 3);
-  DR_SET_ACCESS_FNS (res, acc_fns);
-  VEC_quick_push (tree, DR_ACCESS_FNS (res), access_fn);
-  DR_IS_READ (res) = is_read;
-  DR_BASE_ADDRESS (res) = base_address;
-  DR_OFFSET (res) = init_offset;
-  DR_INIT (res) = NULL_TREE;
-  DR_STEP (res) = step;
-  DR_OFFSET_MISALIGNMENT (res) = misalign;
-  DR_MEMTAG (res) = memtag;
-  DR_PTR_INFO (res) = ptr_info;
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, ")\n");
-
-  return res;
+  return init_pointer_ref (stmt, ref, access_fn, is_read, base_address, 
+                          step, ptr_info);
 }
 
 /* Function strip_conversions
@@ -1585,7 +1578,7 @@ object_analysis (tree memref, tree stmt, bool is_read,
       if (!(*dr))
        { 
          if (TREE_CODE (memref) == ARRAY_REF)
-           *dr = analyze_array (stmt, memref, is_read);          
+           *dr = init_array_ref (stmt, memref, is_read);         
          else if (TREE_CODE (memref) == COMPONENT_REF)
            comp_ref = memref;
          else  
@@ -1658,7 +1651,7 @@ object_analysis (tree memref, tree stmt, bool is_read,
        {
          if (comp_ref && TREE_CODE (TREE_OPERAND (comp_ref, 0)) == ARRAY_REF)
            {
-             *dr = analyze_array (stmt, TREE_OPERAND (comp_ref, 0), is_read);                
+             *dr = init_array_ref (stmt, TREE_OPERAND (comp_ref, 0), is_read);               
              if (DR_NUM_DIMENSIONS (*dr) != 1)
                {
                  if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1842,7 +1835,7 @@ object_analysis (tree memref, tree stmt, bool is_read,
    Extract INVARIANT and CONSTANT parts from OFFSET. 
 
 */
-static void 
+static bool 
 analyze_offset (tree offset, tree *invariant, tree *constant)
 {
   tree op0, op1, constant_0, constant_1, invariant_0, invariant_1;
@@ -1858,23 +1851,36 @@ analyze_offset (tree offset, tree *invariant, tree *constant)
        *constant = offset;
       else
        *invariant = offset;
-      return;
+      return true;
     }
 
   op0 = TREE_OPERAND (offset, 0);
   op1 = TREE_OPERAND (offset, 1);
 
   /* Recursive call with the operands.  */
-  analyze_offset (op0, &invariant_0, &constant_0);
-  analyze_offset (op1, &invariant_1, &constant_1);
+  if (!analyze_offset (op0, &invariant_0, &constant_0)
+      || !analyze_offset (op1, &invariant_1, &constant_1))
+    return false;
 
-  /* Combine the results.  */
+  /* Combine the results. Add negation to the subtrahend in case of 
+     subtraction.  */
+  if (constant_0 && constant_1)
+    return false;
   *constant = constant_0 ? constant_0 : constant_1;
+  if (code == MINUS_EXPR && constant_1)
+    *constant = fold_build1 (NEGATE_EXPR, TREE_TYPE (*constant), *constant);
+
   if (invariant_0 && invariant_1)
     *invariant = 
       fold_build2 (code, TREE_TYPE (invariant_0), invariant_0, invariant_1);
   else
-    *invariant = invariant_0 ? invariant_0 : invariant_1;
+    {
+      *invariant = invariant_0 ? invariant_0 : invariant_1;
+      if (code == MINUS_EXPR && invariant_1)
+        *invariant = 
+           fold_build1 (NEGATE_EXPR, TREE_TYPE (*invariant), *invariant);
+    }
+  return true;
 }
 
 /* Free the memory used by the data reference DR.  */
@@ -1948,7 +1954,17 @@ create_data_ref (tree memref, tree stmt, bool is_read)
   STRIP_NOPS (offset);
   if (offset != orig_offset)
     type = TREE_TYPE (orig_offset);
-  analyze_offset (offset, &invariant, &constant);
+  if (!analyze_offset (offset, &invariant, &constant))
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+        {
+          fprintf (dump_file, "\ncreate_data_ref: failed to analyze dr's");
+          fprintf (dump_file, " offset for ");
+          print_generic_expr (dump_file, memref, TDF_SLIM);
+          fprintf (dump_file, "\n");
+        }
+      return NULL;
+    }
   if (type && invariant)
     invariant = fold_convert (type, invariant);
 
@@ -2053,7 +2069,8 @@ affine_function_equal_p (affine_fn fna, affine_fn fnb)
 {
   unsigned i, n = VEC_length (tree, fna);
 
-  gcc_assert (n == VEC_length (tree, fnb));
+  if (n != VEC_length (tree, fnb))
+    return false;
 
   for (i = 0; i < n; i++)
     if (!operand_equal_p (VEC_index (tree, fna, i),
@@ -2107,6 +2124,15 @@ affine_function_constant_p (affine_fn fn)
   return true;
 }
 
+/* Returns true if FN is the zero constant function.  */
+
+static bool
+affine_function_zero_p (affine_fn fn)
+{
+  return (integer_zerop (affine_function_base (fn))
+         && affine_function_constant_p (fn));
+}
+
 /* Applies operation OP on affine functions FNA and FNB, and returns the
    result.  */
 
@@ -2289,6 +2315,7 @@ initialize_data_dependence_relation (struct data_reference *a,
   DDR_ARE_DEPENDENT (res) = NULL_TREE;
   DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a));
   DDR_LOOP_NEST (res) = loop_nest;
+  DDR_INNER_LOOP (res) = 0;
   DDR_DIR_VECTS (res) = NULL;
   DDR_DIST_VECTS (res) = NULL;
 
@@ -2530,29 +2557,75 @@ analyze_ziv_subscript (tree chrec_a,
     fprintf (dump_file, ")\n");
 }
 
-/* Get the real or estimated number of iterations for LOOPNUM, whichever is
-   available. Return the number of iterations as a tree, or NULL_TREE if
-   we don't know.  */
+/* Sets NIT to the estimated number of executions of the statements in
+   LOOP.  If CONSERVATIVE is true, we must be sure that NIT is at least as
+   large as the number of iterations.  If we have no reliable estimate,
+   the function returns false, otherwise returns true.  */
 
-static tree
-get_number_of_iters_for_loop (int loopnum)
+bool
+estimated_loop_iterations (struct loop *loop, bool conservative,
+                          double_int *nit)
 {
-  struct loop *loop = get_loop (loopnum);
-  tree numiter = number_of_exit_cond_executions (loop);
-
-  if (TREE_CODE (numiter) == INTEGER_CST)
-    return numiter;
+  estimate_numbers_of_iterations_loop (loop);
+  if (conservative)
+    {
+      if (!loop->any_upper_bound)
+       return false;
 
-  if (loop->estimate_state == EST_AVAILABLE)
+      *nit = loop->nb_iterations_upper_bound;
+    }
+  else
     {
-      tree type = lang_hooks.types.type_for_size (INT_TYPE_SIZE, true);
-      if (double_int_fits_to_tree_p (type, loop->estimated_nb_iterations))
-       return double_int_to_tree (type, loop->estimated_nb_iterations);
+      if (!loop->any_estimate)
+       return false;
+
+      *nit = loop->nb_iterations_estimate;
     }
 
-  return NULL_TREE;
+  return true;
+}
+
+/* Similar to estimated_loop_iterations, but returns the estimate only
+   if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
+   on the number of iterations of LOOP could not be derived, returns -1.  */
+
+HOST_WIDE_INT
+estimated_loop_iterations_int (struct loop *loop, bool conservative)
+{
+  double_int nit;
+  HOST_WIDE_INT hwi_nit;
+
+  if (!estimated_loop_iterations (loop, conservative, &nit))
+    return -1;
+
+  if (!double_int_fits_in_shwi_p (nit))
+    return -1;
+  hwi_nit = double_int_to_shwi (nit);
+
+  return hwi_nit < 0 ? -1 : hwi_nit;
 }
     
+/* Similar to estimated_loop_iterations, but returns the estimate as a tree,
+   and only if it fits to the int type.  If this is not the case, or the
+   estimate on the number of iterations of LOOP could not be derived, returns
+   chrec_dont_know.  */
+
+static tree
+estimated_loop_iterations_tree (struct loop *loop, bool conservative)
+{
+  double_int nit;
+  tree type;
+
+  if (!estimated_loop_iterations (loop, conservative, &nit))
+    return chrec_dont_know;
+
+  type = lang_hooks.types.type_for_size (INT_TYPE_SIZE, true);
+  if (!double_int_fits_to_tree_p (type, nit))
+    return chrec_dont_know;
+
+  return double_int_to_tree (type, nit);
+}
+
 /* Analyze a SIV (Single Index Variable) subscript where CHREC_A is a
    constant, and CHREC_B is an affine function.  *OVERLAPS_A and
    *OVERLAPS_B are initialized to the functions that describe the
@@ -2613,8 +2686,8 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
                  
                  if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference))
                    {
-                     tree numiter;
-                     int loopnum = CHREC_VARIABLE (chrec_b);
+                     HOST_WIDE_INT numiter;
+                     struct loop *loop = get_chrec_loop (chrec_b);
 
                      *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
                      tmp = fold_build2 (EXACT_DIV_EXPR, integer_type_node,
@@ -2628,11 +2701,10 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
 
                      /* Perform weak-zero siv test to see if overlap is
                         outside the loop bounds.  */
-                     numiter = get_number_of_iters_for_loop (loopnum);
+                     numiter = estimated_loop_iterations_int (loop, true);
 
-                     if (numiter != NULL_TREE
-                         && TREE_CODE (tmp) == INTEGER_CST
-                         && tree_int_cst_lt (numiter, tmp))
+                     if (numiter >= 0
+                         && compare_tree_int (tmp, numiter) > 0)
                        {
                          free_conflict_function (*overlaps_a);
                          free_conflict_function (*overlaps_b);
@@ -2696,8 +2768,8 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
                  */
                  if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference))
                    {
-                     tree numiter;
-                     int loopnum = CHREC_VARIABLE (chrec_b);
+                     HOST_WIDE_INT numiter;
+                     struct loop *loop = get_chrec_loop (chrec_b);
 
                      *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
                      tmp = fold_build2 (EXACT_DIV_EXPR,
@@ -2708,11 +2780,10 @@ analyze_siv_subscript_cst_affine (tree chrec_a,
 
                      /* Perform weak-zero siv test to see if overlap is
                         outside the loop bounds.  */
-                     numiter = get_number_of_iters_for_loop (loopnum);
+                     numiter = estimated_loop_iterations_int (loop, true);
 
-                     if (numiter != NULL_TREE
-                         && TREE_CODE (tmp) == INTEGER_CST
-                         && tree_int_cst_lt (numiter, tmp))
+                     if (numiter >= 0
+                         && compare_tree_int (tmp, numiter) > 0)
                        {
                          free_conflict_function (*overlaps_a);
                          free_conflict_function (*overlaps_b);
@@ -2839,8 +2910,7 @@ compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
 {
   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;
+  HOST_WIDE_INT niter_x, niter_y, niter_z, niter;
   affine_fn overlaps_a_xz, overlaps_b_xz;
   affine_fn overlaps_a_yz, overlaps_b_yz;
   affine_fn overlaps_a_xyz, overlaps_b_xyz;
@@ -2851,12 +2921,12 @@ compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
   step_y = int_cst_value (CHREC_RIGHT (chrec_a));
   step_z = int_cst_value (CHREC_RIGHT (chrec_b));
 
-  numiter_x = get_number_of_iters_for_loop (CHREC_VARIABLE (CHREC_LEFT (chrec_a)));
-  numiter_y = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
-  numiter_z = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_b));
+  niter_x = estimated_loop_iterations_int
+               (get_chrec_loop (CHREC_LEFT (chrec_a)), true);
+  niter_y = estimated_loop_iterations_int (get_chrec_loop (chrec_a), true);
+  niter_z = estimated_loop_iterations_int (get_chrec_loop (chrec_b), true);
   
-  if (numiter_x == NULL_TREE || numiter_y == NULL_TREE 
-      || numiter_z == NULL_TREE)
+  if (niter_x < 0 || niter_y < 0 || niter_z < 0)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "overlap steps test failed: no iteration counts.\n");
@@ -2867,10 +2937,6 @@ compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
       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,
@@ -3016,13 +3082,14 @@ analyze_subscript_affine_affine (tree chrec_a,
       if (nb_vars_a == 1 && nb_vars_b == 1)
        {
          int step_a, step_b;
-         int niter, niter_a, niter_b;
-         tree numiter_a, numiter_b;
+         HOST_WIDE_INT niter, niter_a, niter_b;
          affine_fn ova, ovb;
 
-         numiter_a = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
-         numiter_b = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_b));
-         if (numiter_a == NULL_TREE || numiter_b == NULL_TREE)
+         niter_a = estimated_loop_iterations_int
+                       (get_chrec_loop (chrec_a), true);
+         niter_b = estimated_loop_iterations_int
+                       (get_chrec_loop (chrec_b), true);
+         if (niter_a < 0 || niter_b < 0)
            {
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "affine-affine test failed: missing iteration counts.\n");
@@ -3032,8 +3099,6 @@ analyze_subscript_affine_affine (tree chrec_a,
              goto end_analyze_subs_aa;
            }
 
-         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));
@@ -3127,12 +3192,13 @@ analyze_subscript_affine_affine (tree chrec_a,
             equation: chrec_a (X0) = chrec_b (Y0).  */
          int x0, y0;
          int niter, niter_a, niter_b;
-         tree numiter_a, numiter_b;
 
-         numiter_a = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
-         numiter_b = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_b));
+         niter_a = estimated_loop_iterations_int
+                       (get_chrec_loop (chrec_a), true);
+         niter_b = estimated_loop_iterations_int
+                       (get_chrec_loop (chrec_b), true);
 
-         if (numiter_a == NULL_TREE || numiter_b == NULL_TREE)
+         if (niter_a < 0 || niter_b < 0)
            {
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "affine-affine test failed: missing iteration counts.\n");
@@ -3142,8 +3208,6 @@ analyze_subscript_affine_affine (tree chrec_a,
              goto end_analyze_subs_aa;
            }
 
-         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;
@@ -3398,36 +3462,29 @@ analyze_siv_subscript (tree chrec_a,
     fprintf (dump_file, ")\n");
 }
 
-/* Return true when the property can be computed.  RES should contain
-   true when calling the first time this function, then it is set to
-   false when one of the evolution steps of an affine CHREC does not
-   divide the constant CST.  */
+/* Returns false if we can prove that the greatest common divisor of the steps
+   of CHREC does not divide CST, false otherwise.  */
 
 static bool
-chrec_steps_divide_constant_p (tree chrec, 
-                              tree cst, 
-                              bool *res)
+gcd_of_steps_may_divide_p (tree chrec, tree cst)
 {
-  switch (TREE_CODE (chrec))
-    {
-    case POLYNOMIAL_CHREC:
-      if (evolution_function_is_constant_p (CHREC_RIGHT (chrec)))
-       {
-         if (tree_fold_divides_p (CHREC_RIGHT (chrec), cst))
-           /* Keep RES to true, and iterate on other dimensions.  */
-           return chrec_steps_divide_constant_p (CHREC_LEFT (chrec), cst, res);
-         
-         *res = false;
-         return true;
-       }
-      else
-       /* When the step is a parameter the result is undetermined.  */
-       return false;
+  HOST_WIDE_INT cd = 0, val;
+  tree step;
 
-    default:
-      /* On the initial condition, return true.  */
-      return true;
+  if (!host_integerp (cst, 0))
+    return true;
+  val = tree_low_cst (cst, 0);
+
+  while (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
+    {
+      step = CHREC_RIGHT (chrec);
+      if (!host_integerp (step, 0))
+       return true;
+      cd = gcd (cd, tree_low_cst (step, 0));
+      chrec = CHREC_LEFT (chrec);
     }
+
+  return val % cd == 0;
 }
 
 /* Analyze a MIV (Multiple Index Variable) subscript.  *OVERLAPS_A and
@@ -3452,7 +3509,6 @@ analyze_miv_subscript (tree chrec_a,
      variables.  In the MIV case we have to solve a Diophantine
      equation with 2*n variables (if the subscript uses n IVs).
   */
-  bool divide_p = true;
   tree difference;
   dependence_stats.num_miv++;
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3468,21 +3524,21 @@ analyze_miv_subscript (tree chrec_a,
         in the same order.  */
       *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
       *overlaps_b = conflict_fn (1, affine_fn_cst (integer_zero_node));
-      *last_conflicts = get_number_of_iters_for_loop (CHREC_VARIABLE (chrec_a));
+      *last_conflicts = estimated_loop_iterations_tree
+                               (get_chrec_loop (chrec_a), true);
       dependence_stats.num_miv_dependent++;
     }
   
   else if (evolution_function_is_constant_p (difference)
           /* For the moment, the following is verified:
              evolution_function_is_affine_multivariate_p (chrec_a) */
-          && chrec_steps_divide_constant_p (chrec_a, difference, &divide_p)
-          && !divide_p)
+          && !gcd_of_steps_may_divide_p (chrec_a, difference))
     {
       /* testsuite/.../ssa-chrec-33.c
         {{21, +, 2}_1, +, -2}_2  vs.  {{20, +, 2}_1, +, -2}_2 
         
-        The difference is 1, and the evolution steps are equal to 2,
-        consequently there are no overlapping elements.  */
+        The difference is 1, and all the evolution steps are multiples
+        of 2, consequently there are no overlapping elements.  */
       *overlaps_a = conflict_fn_no_dependence ();
       *overlaps_b = conflict_fn_no_dependence ();
       *last_conflicts = integer_zero_node;
@@ -3791,6 +3847,22 @@ same_access_functions (struct data_dependence_relation *ddr)
   return true;
 }
 
+/* Return true when the DDR contains only constant access functions.  */
+
+static bool
+constant_access_functions (struct data_dependence_relation *ddr)
+{
+  unsigned i;
+
+  for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
+    if (!evolution_function_is_constant_p (DR_ACCESS_FN (DDR_A (ddr), i))
+       || !evolution_function_is_constant_p (DR_ACCESS_FN (DDR_B (ddr), i)))
+      return false;
+
+  return true;
+}
+
+
 /* Helper function for the case where DDR_A and DDR_B are the same
    multivariate access function.  */
 
@@ -3801,6 +3873,7 @@ add_multivariate_self_dist (struct data_dependence_relation *ddr, tree c_2)
   tree c_1 = CHREC_LEFT (c_2);
   tree c_0 = CHREC_LEFT (c_1);
   lambda_vector dist_v;
+  int v1, v2, cd;
 
   /* Polynomials with more than 2 variables are not handled yet.  */
   if (TREE_CODE (c_0) != INTEGER_CST)
@@ -3814,8 +3887,20 @@ add_multivariate_self_dist (struct data_dependence_relation *ddr, tree c_2)
 
   /* For "{{0, +, 2}_1, +, 3}_2" the distance vector is (3, -2).  */
   dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
-  dist_v[x_1] = int_cst_value (CHREC_RIGHT (c_2));
-  dist_v[x_2] = -int_cst_value (CHREC_RIGHT (c_1));
+  v1 = int_cst_value (CHREC_RIGHT (c_1));
+  v2 = int_cst_value (CHREC_RIGHT (c_2));
+  cd = gcd (v1, v2);
+  v1 /= cd;
+  v2 /= cd;
+
+  if (v2 < 0)
+    {
+      v2 = -v2;
+      v1 = -v1;
+    }
+
+  dist_v[x_1] = v2;
+  dist_v[x_2] = -v1;
   save_dist_v (ddr, dist_v);
 
   add_outer_distances (ddr, dist_v, x_1);
@@ -3859,6 +3944,53 @@ add_other_self_distances (struct data_dependence_relation *ddr)
   add_outer_distances (ddr, dist_v, index_carry);
 }
 
+static void
+insert_innermost_unit_dist_vector (struct data_dependence_relation *ddr)
+{
+  lambda_vector dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
+
+  dist_v[DDR_INNER_LOOP (ddr)] = 1;
+  save_dist_v (ddr, dist_v);
+}
+
+/* Adds a unit distance vector to DDR when there is a 0 overlap.  This
+   is the case for example when access functions are the same and
+   equal to a constant, as in:
+
+   | loop_1
+   |   A[3] = ...
+   |   ... = A[3]
+   | endloop_1
+
+   in which case the distance vectors are (0) and (1).  */
+
+static void
+add_distance_for_zero_overlaps (struct data_dependence_relation *ddr)
+{
+  unsigned i, j;
+
+  for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
+    {
+      subscript_p sub = DDR_SUBSCRIPT (ddr, i);
+      conflict_function *ca = SUB_CONFLICTS_IN_A (sub);
+      conflict_function *cb = SUB_CONFLICTS_IN_B (sub);
+
+      for (j = 0; j < ca->n; j++)
+       if (affine_function_zero_p (ca->fns[j]))
+         {
+           insert_innermost_unit_dist_vector (ddr);
+           return;
+         }
+
+      for (j = 0; j < cb->n; j++)
+       if (affine_function_zero_p (cb->fns[j]))
+         {
+           insert_innermost_unit_dist_vector (ddr);
+           return;
+         }
+    }
+}
+
 /* Compute the classic per loop distance vector.  DDR is the data
    dependence relation to build a vector from.  Return false when fail
    to represent the data dependence as a distance vector.  */
@@ -3879,6 +4011,9 @@ build_classic_dist_vector (struct data_dependence_relation *ddr)
       dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
       save_dist_v (ddr, dist_v);
 
+      if (constant_access_functions (ddr))
+       add_distance_for_zero_overlaps (ddr);
+
       if (DDR_NB_LOOPS (ddr) > 1)
        add_other_self_distances (ddr);
 
@@ -4115,10 +4250,10 @@ static bool
 access_functions_are_affine_or_constant_p (struct data_reference *a)
 {
   unsigned int i;
-  VEC(tree,heap) **fns = DR_ACCESS_FNS_ADDR (a);
+  VEC(tree,heap) *fns = DR_ACCESS_FNS (a);
   tree t;
-  
-  for (i = 0; VEC_iterate (tree, *fns, i, t); i++)
+
+  for (i = 0; VEC_iterate (tree, fns, i, t); i++)
     if (!evolution_function_is_constant_p (t)
        && !evolution_function_is_affine_multivariate_p (t))
       return false;
@@ -4126,6 +4261,530 @@ access_functions_are_affine_or_constant_p (struct data_reference *a)
   return true;
 }
 
+/* Initializes an equation for an OMEGA problem using the information
+   contained in the ACCESS_FUN.  Returns true when the operation
+   succeeded.
+
+   PB is the omega constraint system.
+   EQ is the number of the equation to be initialized.
+   OFFSET is used for shifting the variables names in the constraints:
+   a constrain is composed of 2 * the number of variables surrounding
+   dependence accesses.  OFFSET is set either to 0 for the first n variables,
+   then it is set to n.
+   ACCESS_FUN is expected to be an affine chrec.  */
+
+static bool
+init_omega_eq_with_af (omega_pb pb, unsigned eq, 
+                      unsigned int offset, tree access_fun, 
+                      struct data_dependence_relation *ddr)
+{
+  switch (TREE_CODE (access_fun))
+    {
+    case POLYNOMIAL_CHREC:
+      {
+       tree left = CHREC_LEFT (access_fun);
+       tree right = CHREC_RIGHT (access_fun);
+       int var = CHREC_VARIABLE (access_fun);
+       unsigned var_idx;
+
+       if (TREE_CODE (right) != INTEGER_CST)
+         return false;
+
+       var_idx = index_in_loop_nest (var, DDR_LOOP_NEST (ddr));
+       pb->eqs[eq].coef[offset + var_idx + 1] = int_cst_value (right);
+
+       /* Compute the innermost loop index.  */
+       DDR_INNER_LOOP (ddr) = MAX (DDR_INNER_LOOP (ddr), var_idx);
+
+       if (offset == 0)
+         pb->eqs[eq].coef[var_idx + DDR_NB_LOOPS (ddr) + 1] 
+           += int_cst_value (right);
+
+       switch (TREE_CODE (left))
+         {
+         case POLYNOMIAL_CHREC:
+           return init_omega_eq_with_af (pb, eq, offset, left, ddr);
+
+         case INTEGER_CST:
+           pb->eqs[eq].coef[0] += int_cst_value (left);
+           return true;
+
+         default:
+           return false;
+         }
+      }
+
+    case INTEGER_CST:
+      pb->eqs[eq].coef[0] += int_cst_value (access_fun);
+      return true;
+
+    default:
+      return false;
+    }
+}
+
+/* As explained in the comments preceding init_omega_for_ddr, we have
+   to set up a system for each loop level, setting outer loops
+   variation to zero, and current loop variation to positive or zero.
+   Save each lexico positive distance vector.  */
+
+static void
+omega_extract_distance_vectors (omega_pb pb,
+                               struct data_dependence_relation *ddr)
+{
+  int eq, geq;
+  unsigned i, j;
+  struct loop *loopi, *loopj;
+  enum omega_result res;
+
+  /* Set a new problem for each loop in the nest.  The basis is the
+     problem that we have initialized until now.  On top of this we
+     add new constraints.  */
+  for (i = 0; i <= DDR_INNER_LOOP (ddr) 
+        && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
+    {
+      int dist = 0;
+      omega_pb copy = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr),
+                                          DDR_NB_LOOPS (ddr));
+
+      omega_copy_problem (copy, pb);
+
+      /* For all the outer loops "loop_j", add "dj = 0".  */
+      for (j = 0;
+          j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++)
+       {
+         eq = omega_add_zero_eq (copy, omega_black);
+         copy->eqs[eq].coef[j + 1] = 1;
+       }
+
+      /* For "loop_i", add "0 <= di".  */
+      geq = omega_add_zero_geq (copy, omega_black);
+      copy->geqs[geq].coef[i + 1] = 1;
+
+      /* Reduce the constraint system, and test that the current
+        problem is feasible.  */
+      res = omega_simplify_problem (copy);
+      if (res == omega_false 
+         || res == omega_unknown
+         || copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
+       goto next_problem;
+
+      for (eq = 0; eq < copy->num_subs; eq++)
+       if (copy->subs[eq].key == (int) i + 1)
+         {
+           dist = copy->subs[eq].coef[0];
+           goto found_dist;
+         }
+
+      if (dist == 0)
+       {
+         /* Reinitialize problem...  */
+         omega_copy_problem (copy, pb);
+         for (j = 0;
+              j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++)
+           {
+             eq = omega_add_zero_eq (copy, omega_black);
+             copy->eqs[eq].coef[j + 1] = 1;
+           }
+
+         /* ..., but this time "di = 1".  */
+         eq = omega_add_zero_eq (copy, omega_black);
+         copy->eqs[eq].coef[i + 1] = 1;
+         copy->eqs[eq].coef[0] = -1;
+
+         res = omega_simplify_problem (copy);
+         if (res == omega_false 
+             || res == omega_unknown
+             || copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
+           goto next_problem;
+
+         for (eq = 0; eq < copy->num_subs; eq++)
+           if (copy->subs[eq].key == (int) i + 1)
+             {
+               dist = copy->subs[eq].coef[0];
+               goto found_dist;
+             }
+       }
+
+    found_dist:;
+      /* Save the lexicographically positive distance vector.  */
+      if (dist >= 0)
+       {
+         lambda_vector dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
+         lambda_vector dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
+
+         dist_v[i] = dist;
+
+         for (eq = 0; eq < copy->num_subs; eq++)
+           if (copy->subs[eq].key > 0)
+             {
+               dist = copy->subs[eq].coef[0];
+               dist_v[copy->subs[eq].key - 1] = dist;
+             }
+
+         for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
+           dir_v[j] = dir_from_dist (dist_v[j]);
+
+         save_dist_v (ddr, dist_v);
+         save_dir_v (ddr, dir_v);
+       }
+
+    next_problem:;
+      omega_free_problem (copy);
+    }
+}
+
+/* This is called for each subscript of a tuple of data references:
+   insert an equality for representing the conflicts.  */
+
+static bool
+omega_setup_subscript (tree access_fun_a, tree access_fun_b,
+                      struct data_dependence_relation *ddr,
+                      omega_pb pb, bool *maybe_dependent)
+{
+  int eq;
+  tree fun_a = chrec_convert (integer_type_node, access_fun_a, NULL_TREE);
+  tree fun_b = chrec_convert (integer_type_node, access_fun_b, NULL_TREE);
+  tree difference = chrec_fold_minus (integer_type_node, fun_a, fun_b);
+
+  /* When the fun_a - fun_b is not constant, the dependence is not
+     captured by the classic distance vector representation.  */
+  if (TREE_CODE (difference) != INTEGER_CST)
+    return false;
+
+  /* ZIV test.  */
+  if (ziv_subscript_p (fun_a, fun_b) && !integer_zerop (difference))
+    {
+      /* There is no dependence.  */
+      *maybe_dependent = false;
+      return true;
+    }
+
+  fun_b = chrec_fold_multiply (integer_type_node, fun_b, 
+                              integer_minus_one_node);
+
+  eq = omega_add_zero_eq (pb, omega_black);
+  if (!init_omega_eq_with_af (pb, eq, DDR_NB_LOOPS (ddr), fun_a, ddr)
+      || !init_omega_eq_with_af (pb, eq, 0, fun_b, ddr))
+    /* There is probably a dependence, but the system of
+       constraints cannot be built: answer "don't know".  */
+    return false;
+
+  /* GCD test.  */
+  if (DDR_NB_LOOPS (ddr) != 0 && pb->eqs[eq].coef[0]
+      && !int_divides_p (lambda_vector_gcd 
+                        ((lambda_vector) &(pb->eqs[eq].coef[1]),
+                         2 * DDR_NB_LOOPS (ddr)),
+                        pb->eqs[eq].coef[0]))
+    {
+      /* There is no dependence.  */
+      *maybe_dependent = false;
+      return true;
+    }
+
+  return true;
+}
+
+/* Helper function, same as init_omega_for_ddr but specialized for
+   data references A and B.  */
+
+static bool
+init_omega_for_ddr_1 (struct data_reference *dra, struct data_reference *drb,
+                     struct data_dependence_relation *ddr,
+                     omega_pb pb, bool *maybe_dependent)
+{
+  unsigned i;
+  int ineq;
+  struct loop *loopi;
+  unsigned nb_loops = DDR_NB_LOOPS (ddr);
+
+  /* Insert an equality per subscript.  */
+  for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
+    {
+      if (!omega_setup_subscript (DR_ACCESS_FN (dra, i), DR_ACCESS_FN (drb, i),
+                                 ddr, pb, maybe_dependent))
+       return false;
+      else if (*maybe_dependent == false)
+       {
+         /* There is no dependence.  */
+         DDR_ARE_DEPENDENT (ddr) = chrec_known;
+         return true;
+       }
+    }
+
+  /* Insert inequalities: constraints corresponding to the iteration
+     domain, i.e. the loops surrounding the references "loop_x" and
+     the distance variables "dx".  The layout of the OMEGA
+     representation is as follows:
+     - coef[0] is the constant
+     - coef[1..nb_loops] are the protected variables that will not be
+     removed by the solver: the "dx"
+     - coef[nb_loops + 1, 2*nb_loops] are the loop variables: "loop_x".
+  */
+  for (i = 0; i <= DDR_INNER_LOOP (ddr) 
+        && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
+    {
+      HOST_WIDE_INT nbi = estimated_loop_iterations_int (loopi, true);
+
+      /* 0 <= loop_x */
+      ineq = omega_add_zero_geq (pb, omega_black);
+      pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
+
+      /* 0 <= loop_x + dx */
+      ineq = omega_add_zero_geq (pb, omega_black);
+      pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
+      pb->geqs[ineq].coef[i + 1] = 1;
+
+      if (nbi != -1)
+       {
+         /* loop_x <= nb_iters */
+         ineq = omega_add_zero_geq (pb, omega_black);
+         pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
+         pb->geqs[ineq].coef[0] = nbi;
+
+         /* loop_x + dx <= nb_iters */
+         ineq = omega_add_zero_geq (pb, omega_black);
+         pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
+         pb->geqs[ineq].coef[i + 1] = -1;
+         pb->geqs[ineq].coef[0] = nbi;
+
+         /* A step "dx" bigger than nb_iters is not feasible, so
+            add "0 <= nb_iters + dx",  */
+         ineq = omega_add_zero_geq (pb, omega_black);
+         pb->geqs[ineq].coef[i + 1] = 1;
+         pb->geqs[ineq].coef[0] = nbi;
+         /* and "dx <= nb_iters".  */
+         ineq = omega_add_zero_geq (pb, omega_black);
+         pb->geqs[ineq].coef[i + 1] = -1;
+         pb->geqs[ineq].coef[0] = nbi;
+       }
+    }
+
+  omega_extract_distance_vectors (pb, ddr);
+
+  return true;
+}
+
+/* Sets up the Omega dependence problem for the data dependence
+   relation DDR.  Returns false when the constraint system cannot be
+   built, ie. when the test answers "don't know".  Returns true
+   otherwise, and when independence has been proved (using one of the
+   trivial dependence test), set MAYBE_DEPENDENT to false, otherwise
+   set MAYBE_DEPENDENT to true.
+
+   Example: for setting up the dependence system corresponding to the
+   conflicting accesses 
+
+   | loop_i
+   |   loop_j
+   |     A[i, i+1] = ...
+   |     ... A[2*j, 2*(i + j)]
+   |   endloop_j
+   | endloop_i
+   
+   the following constraints come from the iteration domain:
+
+   0 <= i <= Ni
+   0 <= i + di <= Ni
+   0 <= j <= Nj
+   0 <= j + dj <= Nj
+
+   where di, dj are the distance variables.  The constraints
+   representing the conflicting elements are:
+
+   i = 2 * (j + dj)
+   i + 1 = 2 * (i + di + j + dj)
+
+   For asking that the resulting distance vector (di, dj) be
+   lexicographically positive, we insert the constraint "di >= 0".  If
+   "di = 0" in the solution, we fix that component to zero, and we
+   look at the inner loops: we set a new problem where all the outer
+   loop distances are zero, and fix this inner component to be
+   positive.  When one of the components is positive, we save that
+   distance, and set a new problem where the distance on this loop is
+   zero, searching for other distances in the inner loops.  Here is
+   the classic example that illustrates that we have to set for each
+   inner loop a new problem:
+
+   | loop_1
+   |   loop_2
+   |     A[10]
+   |   endloop_2
+   | endloop_1
+
+   we have to save two distances (1, 0) and (0, 1).
+
+   Given two array references, refA and refB, we have to set the
+   dependence problem twice, refA vs. refB and refB vs. refA, and we
+   cannot do a single test, as refB might occur before refA in the
+   inner loops, and the contrary when considering outer loops: ex.
+
+   | loop_0
+   |   loop_1
+   |     loop_2
+   |       T[{1,+,1}_2][{1,+,1}_1]  // refA
+   |       T[{2,+,1}_2][{0,+,1}_1]  // refB
+   |     endloop_2
+   |   endloop_1
+   | endloop_0
+
+   refB touches the elements in T before refA, and thus for the same
+   loop_0 refB precedes refA: ie. the distance vector (0, 1, -1)
+   but for successive loop_0 iterations, we have (1, -1, 1)
+
+   The Omega solver expects the distance variables ("di" in the
+   previous example) to come first in the constraint system (as
+   variables to be protected, or "safe" variables), the constraint
+   system is built using the following layout:
+
+   "cst | distance vars | index vars".
+*/
+
+static bool
+init_omega_for_ddr (struct data_dependence_relation *ddr,
+                   bool *maybe_dependent)
+{
+  omega_pb pb;
+  bool res = false;
+
+  *maybe_dependent = true;
+
+  if (same_access_functions (ddr))
+    {
+      unsigned j;
+      lambda_vector dir_v;
+
+      /* Save the 0 vector.  */
+      save_dist_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
+      dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
+      for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
+       dir_v[j] = dir_equal;
+      save_dir_v (ddr, dir_v);
+
+      /* Save the dependences carried by outer loops.  */
+      pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
+      res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
+                                 maybe_dependent);
+      omega_free_problem (pb);
+      return res;
+    }
+
+  /* Omega expects the protected variables (those that have to be kept
+     after elimination) to appear first in the constraint system.
+     These variables are the distance variables.  In the following
+     initialization we declare NB_LOOPS safe variables, and the total
+     number of variables for the constraint system is 2*NB_LOOPS.  */
+  pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
+  res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
+                             maybe_dependent);
+  omega_free_problem (pb);
+
+  /* Stop computation if not decidable, or no dependence.  */
+  if (res == false || *maybe_dependent == false)
+    return res;
+
+  pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
+  res = init_omega_for_ddr_1 (DDR_B (ddr), DDR_A (ddr), ddr, pb,
+                             maybe_dependent);
+  omega_free_problem (pb);
+
+  return res;
+}
+
+/* Return true when DDR contains the same information as that stored
+   in DIR_VECTS and in DIST_VECTS, return false otherwise.   */
+
+static bool
+ddr_consistent_p (FILE *file,
+                 struct data_dependence_relation *ddr,
+                 VEC (lambda_vector, heap) *dist_vects,
+                 VEC (lambda_vector, heap) *dir_vects)
+{
+  unsigned int i, j;
+
+  /* If dump_file is set, output there.  */
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    file = dump_file;
+
+  if (VEC_length (lambda_vector, dist_vects) != DDR_NUM_DIST_VECTS (ddr))
+    {
+      lambda_vector b_dist_v;
+      fprintf (file, "\n(Number of distance vectors differ: Banerjee has %d, Omega has %d.\n",
+              VEC_length (lambda_vector, dist_vects),
+              DDR_NUM_DIST_VECTS (ddr));
+
+      fprintf (file, "Banerjee dist vectors:\n");
+      for (i = 0; VEC_iterate (lambda_vector, dist_vects, i, b_dist_v); i++)
+       print_lambda_vector (file, b_dist_v, DDR_NB_LOOPS (ddr));
+
+      fprintf (file, "Omega dist vectors:\n");
+      for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
+       print_lambda_vector (file, DDR_DIST_VECT (ddr, i), DDR_NB_LOOPS (ddr));
+
+      fprintf (file, "data dependence relation:\n");
+      dump_data_dependence_relation (file, ddr);
+
+      fprintf (file, ")\n");
+      return false;
+    }
+
+  if (VEC_length (lambda_vector, dir_vects) != DDR_NUM_DIR_VECTS (ddr))
+    {
+      fprintf (file, "\n(Number of direction vectors differ: Banerjee has %d, Omega has %d.)\n",
+              VEC_length (lambda_vector, dir_vects),
+              DDR_NUM_DIR_VECTS (ddr));
+      return false;
+    }
+
+  for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
+    {
+      lambda_vector a_dist_v;
+      lambda_vector b_dist_v = DDR_DIST_VECT (ddr, i);
+
+      /* Distance vectors are not ordered in the same way in the DDR
+        and in the DIST_VECTS: search for a matching vector.  */
+      for (j = 0; VEC_iterate (lambda_vector, dist_vects, j, a_dist_v); j++)
+       if (lambda_vector_equal (a_dist_v, b_dist_v, DDR_NB_LOOPS (ddr)))
+         break;
+
+      if (j == VEC_length (lambda_vector, dist_vects))
+       {
+         fprintf (file, "\n(Dist vectors from the first dependence analyzer:\n");
+         print_dist_vectors (file, dist_vects, DDR_NB_LOOPS (ddr));
+         fprintf (file, "not found in Omega dist vectors:\n");
+         print_dist_vectors (file, DDR_DIST_VECTS (ddr), DDR_NB_LOOPS (ddr));
+         fprintf (file, "data dependence relation:\n");
+         dump_data_dependence_relation (file, ddr);
+         fprintf (file, ")\n");
+       }
+    }
+
+  for (i = 0; i < DDR_NUM_DIR_VECTS (ddr); i++)
+    {
+      lambda_vector a_dir_v;
+      lambda_vector b_dir_v = DDR_DIR_VECT (ddr, i);
+
+      /* Direction vectors are not ordered in the same way in the DDR
+        and in the DIR_VECTS: search for a matching vector.  */
+      for (j = 0; VEC_iterate (lambda_vector, dir_vects, j, a_dir_v); j++)
+       if (lambda_vector_equal (a_dir_v, b_dir_v, DDR_NB_LOOPS (ddr)))
+         break;
+
+      if (j == VEC_length (lambda_vector, dist_vects))
+       {
+         fprintf (file, "\n(Dir vectors from the first dependence analyzer:\n");
+         print_dir_vectors (file, dir_vects, DDR_NB_LOOPS (ddr));
+         fprintf (file, "not found in Omega dir vectors:\n");
+         print_dir_vectors (file, DDR_DIR_VECTS (ddr), DDR_NB_LOOPS (ddr));
+         fprintf (file, "data dependence relation:\n");
+         dump_data_dependence_relation (file, ddr);
+         fprintf (file, ")\n");
+       }
+    }
+
+  return true;  
+}
+
 /* This computes the affine dependence relation between A and B.
    CHREC_KNOWN is used for representing the independence between two
    accesses, while CHREC_DONT_KNOW is used for representing the unknown
@@ -4158,13 +4817,57 @@ compute_affine_dependence (struct data_dependence_relation *ddr)
 
       if (access_functions_are_affine_or_constant_p (dra)
          && access_functions_are_affine_or_constant_p (drb))
-       subscript_dependence_tester (ddr);
-      
+       {
+         if (flag_check_data_deps)
+           {
+             /* Compute the dependences using the first algorithm.  */
+             subscript_dependence_tester (ddr);
+
+             if (dump_file && (dump_flags & TDF_DETAILS))
+               {
+                 fprintf (dump_file, "\n\nBanerjee Analyzer\n");
+                 dump_data_dependence_relation (dump_file, ddr);
+               }
+
+             if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
+               {
+                 bool maybe_dependent;
+                 VEC (lambda_vector, heap) *dir_vects, *dist_vects;
+
+                 /* Save the result of the first DD analyzer.  */
+                 dist_vects = DDR_DIST_VECTS (ddr);
+                 dir_vects = DDR_DIR_VECTS (ddr);
+
+                 /* Reset the information.  */
+                 DDR_DIST_VECTS (ddr) = NULL;
+                 DDR_DIR_VECTS (ddr) = NULL;
+
+                 /* Compute the same information using Omega.  */
+                 if (!init_omega_for_ddr (ddr, &maybe_dependent))
+                   goto csys_dont_know;
+
+                 if (dump_file && (dump_flags & TDF_DETAILS))
+                   {
+                     fprintf (dump_file, "Omega Analyzer\n");
+                     dump_data_dependence_relation (dump_file, ddr);
+                   }
+
+                 /* Check that we get the same information.  */
+                 if (maybe_dependent)
+                   gcc_assert (ddr_consistent_p (stderr, ddr, dist_vects,
+                                                 dir_vects));
+               }
+           }
+         else
+           subscript_dependence_tester (ddr);
+       }
+     
       /* As a last case, if the dependence cannot be determined, or if
         the dependence is considered too difficult to determine, answer
         "don't know".  */
       else
        {
+       csys_dont_know:;
          dependence_stats.num_dependence_undetermined++;
 
          if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4249,7 +4952,7 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references)
 {
   bool clobbers_memory = false;
   data_ref_loc *ref;
-  tree *op0, *op1, args, call;
+  tree *op0, *op1, call;
 
   *references = NULL;
 
@@ -4290,9 +4993,12 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references)
 
   if (call)
     {
-      for (args = TREE_OPERAND (call, 1); args; args = TREE_CHAIN (args))
+      unsigned i, n = call_expr_nargs (call);
+
+      for (i = 0; i < n; i++)
        {
-         op0 = &TREE_VALUE (args);
+         op0 = &CALL_EXPR_ARG (call, i);
+
          if (DECL_P (*op0)
              || REFERENCE_CLASS_P (*op0))
            {
@@ -4522,7 +5228,7 @@ compute_data_dependences_for_loop (struct loop *loop,
 }
 
 /* Entry point (for testing only).  Analyze all the data references
-   and the dependence relations.
+   and the dependence relations in LOOP.
 
    The data references are computed first.  
    
@@ -4542,9 +5248,8 @@ compute_data_dependences_for_loop (struct loop *loop,
    recompute the same information.  The implementation of this KB is
    transparent to the optimizer, and thus the KB can be changed with a
    more efficient implementation, or the KB could be disabled.  */
-#if 0
 static void 
-analyze_all_data_dependences (struct loops *loops)
+analyze_all_data_dependences (struct loop *loop)
 {
   unsigned int i;
   int nb_data_refs = 10;
@@ -4554,8 +5259,8 @@ analyze_all_data_dependences (struct loops *loops)
     VEC_alloc (ddr_p, heap, nb_data_refs * nb_data_refs);
 
   /* Compute DDs on the whole function.  */
-  compute_data_dependences_for_loop (loops->parray[0], false,
-                                    &datarefs, &dependence_relations);
+  compute_data_dependences_for_loop (loop, false, &datarefs,
+                                    &dependence_relations);
 
   if (dump_file)
     {
@@ -4604,7 +5309,19 @@ analyze_all_data_dependences (struct loops *loops)
   free_dependence_relations (dependence_relations);
   free_data_refs (datarefs);
 }
-#endif
+
+/* Computes all the data dependences and check that the results of
+   several analyzers are the same.  */
+
+void
+tree_check_data_deps (void)
+{
+  loop_iterator li;
+  struct loop *loop_nest;
+
+  FOR_EACH_LOOP (li, loop_nest, 0)
+    analyze_all_data_dependences (loop_nest);
+}
 
 /* Free the memory used by a data dependence relation DDR.  */