OSDN Git Service

2005-06-14 Ed Schonberg <schonberg@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-data-ref.c
index 112522e..e4917df 100644 (file)
@@ -1,5 +1,5 @@
 /* Data references and dependences detectors.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Sebastian Pop <s.pop@laposte.net>
 
 This file is part of GCC.
@@ -78,7 +78,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "errors.h"
 #include "ggc.h"
 #include "tree.h"
 
@@ -109,9 +108,9 @@ array_base_name_differ_p (struct data_reference *a,
 {
   tree base_a = DR_BASE_NAME (a);
   tree base_b = DR_BASE_NAME (b);
-  tree ta = TREE_TYPE (base_a);
-  tree tb = TREE_TYPE (base_b);
 
+  if (!base_a || !base_b)
+    return false;
 
   /* Determine if same base.  Example: for the array accesses
      a[i], b[i] or pointer accesses *a, *b, bases are a, b.  */
@@ -179,24 +178,6 @@ array_base_name_differ_p (struct data_reference *a,
       return true;
     }
 
-  if (!alias_sets_conflict_p (get_alias_set (base_a), get_alias_set (base_b)))
-    {
-      *differ_p = true;
-      return true;
-    }
-
-  /* An instruction writing through a restricted pointer is
-     "independent" of any instruction reading or writing through a
-     different pointer, in the same block/scope.  */
-  if ((TREE_CODE (ta) == POINTER_TYPE && TYPE_RESTRICT (ta)
-       && !DR_IS_READ(a))
-      || (TREE_CODE (tb) == POINTER_TYPE && TYPE_RESTRICT (tb)
-         && !DR_IS_READ(b)))
-    {
-      *differ_p = true;
-      return true;
-    }
-
   return false;
 }
 
@@ -466,32 +447,21 @@ dump_ddrs (FILE *file, varray_type ddrs)
 
 \f
 
-/* Compute the lowest iteration bound for LOOP.  It is an
-   INTEGER_CST.  */
+/* Initialize LOOP->ESTIMATED_NB_ITERATIONS with the lowest safe
+   approximation of the number of iterations for LOOP.  */
 
 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;
-    }
+  struct nb_iter_bound *bound;
+  
+  for (bound = loop->bounds; bound; bound = bound->next)
+    if (TREE_CODE (bound->bound) == INTEGER_CST
+       /* Update only when there is no previous estimation.  */
+       && (chrec_contains_undetermined (loop->estimated_nb_iterations)
+           /* Or when the current estimation is smaller.  */
+           || tree_int_cst_lt (bound->bound, loop->estimated_nb_iterations)))
+      loop->estimated_nb_iterations = bound->bound;
 }
 
 /* Estimate the number of iterations from the size of the data and the
@@ -541,7 +511,7 @@ estimate_niter_from_size_of_data (struct loop *loop,
 
 static tree
 analyze_array_indexes (struct loop *loop,
-                      varray_type *access_fns, 
+                      VEC(tree,heap) **access_fns, 
                       tree ref, tree stmt)
 {
   tree opnd0, opnd1;
@@ -557,10 +527,10 @@ analyze_array_indexes (struct loop *loop,
   access_fn = instantiate_parameters 
     (loop, analyze_scalar_evolution (loop, opnd1));
 
-  if (loop->estimated_nb_iterations == NULL_TREE)
+  if (chrec_contains_undetermined (loop->estimated_nb_iterations))
     estimate_niter_from_size_of_data (loop, opnd0, access_fn, stmt);
   
-  VARRAY_PUSH_TREE (*access_fns, access_fn);
+  VEC_safe_push (tree, heap, *access_fns, access_fn);
   
   /* Recursively record other array access functions.  */
   if (TREE_CODE (opnd0) == ARRAY_REF)
@@ -593,7 +563,7 @@ analyze_array (tree stmt, tree ref, bool is_read)
   
   DR_STMT (res) = stmt;
   DR_REF (res) = ref;
-  VARRAY_TREE_INIT (DR_ACCESS_FNS (res), 3, "access_fns");
+  DR_ACCESS_FNS (res) = VEC_alloc (tree, heap, 3);
   DR_BASE_NAME (res) = analyze_array_indexes 
     (loop_containing_stmt (stmt), &(DR_ACCESS_FNS (res)), ref, stmt);
   DR_IS_READ (res) = is_read;
@@ -628,9 +598,9 @@ init_data_ref (tree stmt,
   
   DR_STMT (res) = stmt;
   DR_REF (res) = ref;
-  VARRAY_TREE_INIT (DR_ACCESS_FNS (res), 5, "access_fns");
+  DR_ACCESS_FNS (res) = VEC_alloc (tree, heap, 5);
   DR_BASE_NAME (res) = base;
-  VARRAY_PUSH_TREE (DR_ACCESS_FNS (res), access_fn);
+  VEC_quick_push (tree, DR_ACCESS_FNS (res), access_fn);
   DR_IS_READ (res) = is_read;
   
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -664,7 +634,7 @@ all_chrecs_equal_p (tree chrec)
 /* Determine for each subscript in the data dependence relation DDR
    the distance.  */
 
-static void
+void
 compute_subscript_distance (struct data_dependence_relation *ddr)
 {
   if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
@@ -1111,7 +1081,7 @@ compute_overlap_steps_for_affine_univar (int niter, int step_a, int step_b,
    | 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
+   FORNOW: This is a specialized implementation for a case occurring in
    a common benchmark.  Implement the general algorithm.  */
 
 static void
@@ -1148,8 +1118,12 @@ compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
     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)
+  if (chrec_contains_undetermined (numiter_x)
+      || chrec_contains_undetermined (numiter_y)
+      || chrec_contains_undetermined (numiter_z)
+      || TREE_CODE (numiter_x) != INTEGER_CST
+      || TREE_CODE (numiter_y) != INTEGER_CST
+      || TREE_CODE (numiter_z) != INTEGER_CST)
     {
       *overlaps_a = chrec_dont_know;
       *overlaps_b = chrec_dont_know;
@@ -1297,7 +1271,10 @@ analyze_subscript_affine_affine (tree chrec_a,
          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)
+         if (chrec_contains_undetermined (numiter_a)
+             || chrec_contains_undetermined (numiter_b)
+             || TREE_CODE (numiter_a) != INTEGER_CST
+             || TREE_CODE (numiter_b) != INTEGER_CST)
            {
              *overlaps_a = chrec_dont_know;
              *overlaps_b = chrec_dont_know;
@@ -1398,7 +1375,10 @@ analyze_subscript_affine_affine (tree chrec_a,
          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)
+         if (chrec_contains_undetermined (numiter_a)
+             || chrec_contains_undetermined (numiter_b)
+             || TREE_CODE (numiter_a) != INTEGER_CST
+             || TREE_CODE (numiter_b) != INTEGER_CST)
            {
              *overlaps_a = chrec_dont_know;
              *overlaps_b = chrec_dont_know;
@@ -1787,7 +1767,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr)
    starting at FIRST_LOOP_DEPTH. 
    Return TRUE otherwise.  */
 
-static bool
+bool
 build_classic_dist_vector (struct data_dependence_relation *ddr, 
                           int nb_loops, int first_loop_depth)
 {
@@ -2142,11 +2122,12 @@ static bool
 access_functions_are_affine_or_constant_p (struct data_reference *a)
 {
   unsigned int i;
-  varray_type fns = DR_ACCESS_FNS (a);
+  VEC(tree,heap) **fns = &DR_ACCESS_FNS (a);
+  tree t;
   
-  for (i = 0; i < VARRAY_ACTIVE_SIZE (fns); i++)
-    if (!evolution_function_is_constant_p (VARRAY_TREE (fns, i))
-       && !evolution_function_is_affine_multivariate_p (VARRAY_TREE (fns, 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;
   
   return true;
@@ -2195,6 +2176,30 @@ compute_affine_dependence (struct data_dependence_relation *ddr)
     fprintf (dump_file, ")\n");
 }
 
+/* This computes the dependence relation for the same data
+   reference into DDR.  */
+
+static void
+compute_self_dependence (struct data_dependence_relation *ddr)
+{
+  unsigned int i;
+
+  for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
+    {
+      struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
+      
+      /* The accessed index overlaps for each iteration.  */
+      SUB_CONFLICTS_IN_A (subscript) = integer_zero_node;
+      SUB_CONFLICTS_IN_B (subscript) = integer_zero_node;
+      SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
+    }
+}
+
+
+typedef struct data_dependence_relation *ddr_p;
+DEF_VEC_P(ddr_p);
+DEF_VEC_ALLOC_P(ddr_p,heap);
+
 /* Compute a subset of the data dependence relation graph.  Don't
    compute read-read relations, and avoid the computation of the
    opposite relation, i.e. when AB has been computed, don't compute BA.
@@ -2203,14 +2208,17 @@ compute_affine_dependence (struct data_dependence_relation *ddr)
 
 static void 
 compute_all_dependences (varray_type datarefs, 
-                        varray_type *dependence_relations)
+                        VEC(ddr_p,heap) **dependence_relations)
 {
   unsigned int i, j, N;
 
   N = VARRAY_ACTIVE_SIZE (datarefs);
 
+  /* Note that we specifically skip i == j because it's a self dependence, and
+     use compute_self_dependence below.  */
+
   for (i = 0; i < N; i++)
-    for (j = i; j < N; j++)
+    for (j = i + 1; j < N; j++)
       {
        struct data_reference *a, *b;
        struct data_dependence_relation *ddr;
@@ -2219,10 +2227,26 @@ compute_all_dependences (varray_type datarefs,
        b = VARRAY_GENERIC_PTR (datarefs, j);
        ddr = initialize_data_dependence_relation (a, b);
 
-       VARRAY_PUSH_GENERIC_PTR (*dependence_relations, ddr);
+       VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
        compute_affine_dependence (ddr);
        compute_subscript_distance (ddr);
       }
+
+  /* Compute self dependence relation of each dataref to itself.  */
+
+  for (i = 0; i < N; i++)
+    {
+      struct data_reference *a, *b;
+      struct data_dependence_relation *ddr;
+
+      a = VARRAY_GENERIC_PTR (datarefs, i);
+      b = VARRAY_GENERIC_PTR (datarefs, i);
+      ddr = initialize_data_dependence_relation (a, b);
+
+      VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
+      compute_self_dependence (ddr);
+      compute_subscript_distance (ddr);
+    }
 }
 
 /* Search the data references in LOOP, and record the information into
@@ -2235,7 +2259,6 @@ compute_all_dependences (varray_type datarefs,
 tree 
 find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
 {
-  bool dont_know_node_not_inserted = true;
   basic_block bb, *bbs;
   unsigned int i;
   block_stmt_iterator bsi;
@@ -2249,32 +2272,62 @@ find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
         {
          tree stmt = bsi_stmt (bsi);
-         stmt_ann_t ann = stmt_ann (stmt);
 
-         if (TREE_CODE (stmt) != MODIFY_EXPR)
-           continue;
+         /* ASM_EXPR and CALL_EXPR may embed arbitrary side effects.
+            Calls have side-effects, except those to const or pure
+            functions.  */
+         if ((TREE_CODE (stmt) == CALL_EXPR
+              && !(call_expr_flags (stmt) & (ECF_CONST | ECF_PURE)))
+             || (TREE_CODE (stmt) == ASM_EXPR
+                 && ASM_VOLATILE_P (stmt)))
+           goto insert_dont_know_node;
 
-         if (!VUSE_OPS (ann)
-             && !V_MUST_DEF_OPS (ann)
-             && !V_MAY_DEF_OPS (ann))
+         if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
            continue;
-         
-         /* In the GIMPLE representation, a modify expression
-            contains a single load or store to memory.  */
-         if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF)
-           VARRAY_PUSH_GENERIC_PTR 
-                   (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 0), 
-                                              false));
-
-         else if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ARRAY_REF)
-           VARRAY_PUSH_GENERIC_PTR 
-                   (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 1), 
-                                              true));
-         else
+
+         switch (TREE_CODE (stmt))
            {
-             if (dont_know_node_not_inserted)
+           case MODIFY_EXPR:
+             if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF)
+               VARRAY_PUSH_GENERIC_PTR 
+                 (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 0),
+                                            false));
+
+             if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ARRAY_REF)
+               VARRAY_PUSH_GENERIC_PTR 
+                 (*datarefs, analyze_array (stmt, TREE_OPERAND (stmt, 1),
+                                            true));
+
+             if (TREE_CODE (TREE_OPERAND (stmt, 0)) != ARRAY_REF
+                 && TREE_CODE (TREE_OPERAND (stmt, 1)) != ARRAY_REF)
+               goto insert_dont_know_node;
+
+             break;
+
+           case CALL_EXPR:
+             {
+               tree args;
+               bool one_inserted = false;
+
+               for (args = TREE_OPERAND (stmt, 1); args; args = TREE_CHAIN (args))
+                 if (TREE_CODE (TREE_VALUE (args)) == ARRAY_REF)
+                   {
+                     VARRAY_PUSH_GENERIC_PTR 
+                       (*datarefs, analyze_array (stmt, TREE_VALUE (args), true));
+                     one_inserted = true;
+                   }
+
+               if (!one_inserted)
+                 goto insert_dont_know_node;
+
+               break;
+             }
+
+           default:
                {
                  struct data_reference *res;
+
+               insert_dont_know_node:;
                  res = xmalloc (sizeof (struct data_reference));
                  DR_STMT (res) = NULL_TREE;
                  DR_REF (res) = NULL_TREE;
@@ -2282,23 +2335,24 @@ find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
                  DR_BASE_NAME (res) = NULL;
                  DR_IS_READ (res) = false;
                  VARRAY_PUSH_GENERIC_PTR (*datarefs, res);
-                 dont_know_node_not_inserted = false;
+
+                 free (bbs);
+                 return chrec_dont_know;
                }
            }
 
          /* 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 (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+           loop->parallel_p = false;
        }
 
-      if (bb->loop_father->estimated_nb_iterations == NULL_TREE)
-       compute_estimated_nb_iterations (bb->loop_father);
+      if (chrec_contains_undetermined (loop->estimated_nb_iterations))
+       compute_estimated_nb_iterations (loop);
     }
 
   free (bbs);
 
-  return dont_know_node_not_inserted ? NULL_TREE : chrec_dont_know;
+  return NULL_TREE;
 }
 
 \f
@@ -2316,7 +2370,8 @@ compute_data_dependences_for_loop (unsigned nb_loops,
                                   varray_type *dependence_relations)
 {
   unsigned int i;
-  varray_type allrelations;
+  VEC(ddr_p,heap) *allrelations;
+  struct data_dependence_relation *ddr;
 
   /* If one of the data references is not computable, give up without
      spending time to compute other dependences.  */
@@ -2333,13 +2388,11 @@ compute_data_dependences_for_loop (unsigned nb_loops,
       return;
     }
 
-  VARRAY_GENERIC_PTR_INIT (allrelations, 1, "Data dependence relations");
+  allrelations = NULL;
   compute_all_dependences (*datarefs, &allrelations);
 
-  for (i = 0; i < VARRAY_ACTIVE_SIZE (allrelations); i++)
+  for (i = 0; VEC_iterate (ddr_p, allrelations, i, ddr); i++)
     {
-      struct data_dependence_relation *ddr;
-      ddr = VARRAY_GENERIC_PTR (allrelations, i);
       if (build_classic_dist_vector (ddr, nb_loops, loop->depth))
        {
          VARRAY_PUSH_GENERIC_PTR (*dependence_relations, ddr);
@@ -2479,8 +2532,7 @@ free_data_refs (varray_type datarefs)
        VARRAY_GENERIC_PTR (datarefs, i);
       if (dr)
        {
-         if (DR_ACCESS_FNS (dr))
-           varray_clear (DR_ACCESS_FNS (dr));
+         VEC_free (tree, heap, DR_ACCESS_FNS (dr));
          free (dr);
        }
     }