OSDN Git Service

PR fortran/31266
[pf3gnuchains/gcc-fork.git] / gcc / tree-data-ref.c
index d59278c..ac5aa50 100644 (file)
@@ -2069,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),
@@ -2123,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.  */
 
@@ -2552,37 +2562,27 @@ analyze_ziv_subscript (tree chrec_a,
    large as the number of iterations.  If we have no reliable estimate,
    the function returns false, otherwise returns true.  */
 
-static bool
+bool
 estimated_loop_iterations (struct loop *loop, bool conservative,
                           double_int *nit)
 {
-  tree numiter = number_of_exit_cond_executions (loop);
-
-  /* If we have an exact value, use it.  */
-  if (TREE_CODE (numiter) == INTEGER_CST)
+  estimate_numbers_of_iterations_loop (loop);
+  if (conservative)
     {
-      *nit = tree_to_double_int (numiter);
-      return true;
-    }
+      if (!loop->any_upper_bound)
+       return false;
 
-  /* If we have a measured profile and we do not ask for a conservative bound,
-     use it.  */
-  if (!conservative && loop->header->count != 0)
-    {
-      *nit = uhwi_to_double_int (expected_loop_iterations (loop) + 1);
-      return true;
+      *nit = loop->nb_iterations_upper_bound;
     }
-
-  /* Finally, try using a reliable estimate on number of iterations according
-     to the size of the accessed data, if available.  */
-  estimate_numbers_of_iterations_loop (loop);
-  if (loop->estimate_state == EST_AVAILABLE)
+  else
     {
-      *nit = loop->estimated_nb_iterations;
-      return true;
+      if (!loop->any_estimate)
+       return false;
+
+      *nit = loop->nb_iterations_estimate;
     }
 
-  return false;
+  return true;
 }
 
 /* Similar to estimated_loop_iterations, but returns the estimate only
@@ -3462,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
@@ -3516,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))
@@ -3540,14 +3532,13 @@ analyze_miv_subscript (tree chrec_a,
   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;
@@ -3856,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.  */
 
@@ -3866,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)
@@ -3879,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);
@@ -3924,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.  */
@@ -3944,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);
 
@@ -4882,8 +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, arg, call;
-  call_expr_arg_iterator iter;
+  tree *op0, *op1, call;
 
   *references = NULL;
 
@@ -4924,9 +4993,12 @@ get_references_in_stmt (tree stmt, VEC (data_ref_loc, heap) **references)
 
   if (call)
     {
-      FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
+      unsigned i, n = call_expr_nargs (call);
+
+      for (i = 0; i < n; i++)
        {
-         op0 = &arg;
+         op0 = &CALL_EXPR_ARG (call, i);
+
          if (DECL_P (*op0)
              || REFERENCE_CLASS_P (*op0))
            {