OSDN Git Service

PR target/45670
[pf3gnuchains/gcc-fork.git] / gcc / tree-loop-distribution.c
index 920ab8c..bc3f54d 100644 (file)
@@ -1,5 +1,6 @@
 /* Loop distribution.
-   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
    Contributed by Georges-Andre Silber <Georges-Andre.Silber@ensmp.fr>
    and Sebastian Pop <sebastian.pop@amd.com>.
 
@@ -45,19 +46,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "ggc.h"
 #include "tree.h"
-#include "target.h"
-
-#include "rtl.h"
 #include "basic-block.h"
-#include "diagnostic.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "timevar.h"
 #include "cfgloop.h"
-#include "expr.h"
-#include "optabs.h"
 #include "tree-chrec.h"
 #include "tree-data-ref.h"
 #include "tree-scalar-evolution.h"
@@ -201,18 +195,28 @@ generate_loops_for_partition (struct loop *loop, bitmap partition, bool copy_p)
 
       for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi);)
        if (!bitmap_bit_p (partition, x++))
-         remove_phi_node (&bsi, true);
+         {
+           gimple phi = gsi_stmt (bsi);
+           if (!is_gimple_reg (gimple_phi_result (phi)))
+             mark_virtual_phi_result_for_renaming (phi);
+           remove_phi_node (&bsi, true);
+         }
        else
          gsi_next (&bsi);
 
       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi);)
-       if (gimple_code (gsi_stmt (bsi)) != GIMPLE_LABEL
-           && !bitmap_bit_p (partition, x++))
-         gsi_remove (&bsi, false);
-       else
-         gsi_next (&bsi);
-
-       mark_virtual_ops_in_bb (bb);
+       {
+         gimple stmt = gsi_stmt (bsi);
+         if (gimple_code (gsi_stmt (bsi)) != GIMPLE_LABEL
+             && !bitmap_bit_p (partition, x++))
+           {
+             unlink_stmt_vdef (stmt);
+             gsi_remove (&bsi, true);
+             release_defs (stmt);
+           }
+         else
+           gsi_next (&bsi);
+       }
     }
 
   free (bbs);
@@ -226,12 +230,9 @@ build_size_arg_loc (location_t loc, tree nb_iter, tree op,
                    gimple_seq *stmt_list)
 {
   gimple_seq stmts;
-  tree x;
-
-  x = fold_build2_loc (loc, MULT_EXPR, size_type_node,
-                      fold_convert_loc (loc, size_type_node, nb_iter),
-                      fold_convert_loc (loc, size_type_node,
-                                        TYPE_SIZE_UNIT (TREE_TYPE (op))));
+  tree x = size_binop_loc (loc, MULT_EXPR,
+                          fold_convert_loc (loc, sizetype, nb_iter),
+                          TYPE_SIZE_UNIT (TREE_TYPE (op)));
   x = force_gimple_operand (x, &stmts, true, NULL);
   gimple_seq_add_seq (stmt_list, stmts);
 
@@ -249,7 +250,6 @@ generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
   gimple_seq stmt_list = NULL, stmts;
   gimple fn_call;
   tree mem, fn;
-  gimple_stmt_iterator i;
   struct data_reference *dr = XCNEW (struct data_reference);
   location_t loc = gimple_location (stmt);
 
@@ -285,6 +285,8 @@ generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
       addr_base = fold_convert_loc (loc, sizetype, addr_base);
       addr_base = size_binop_loc (loc, MINUS_EXPR, addr_base,
                                  fold_convert_loc (loc, sizetype, nb_bytes));
+      addr_base = size_binop_loc (loc, PLUS_EXPR, addr_base,
+                                 TYPE_SIZE_UNIT (TREE_TYPE (op0)));
       addr_base = fold_build2_loc (loc, POINTER_PLUS_EXPR,
                                   TREE_TYPE (DR_BASE_ADDRESS (dr)),
                                   DR_BASE_ADDRESS (dr), addr_base);
@@ -298,13 +300,6 @@ generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
   fn = build_fold_addr_expr (implicit_built_in_decls [BUILT_IN_MEMSET]);
   fn_call = gimple_build_call (fn, 3, mem, integer_zero_node, nb_bytes);
   gimple_seq_add_stmt (&stmt_list, fn_call);
-
-  for (i = gsi_start (stmt_list); !gsi_end_p (i); gsi_next (&i))
-    {
-      gimple s = gsi_stmt (i);
-      update_stmt_if_modified (s);
-    }
-
   gsi_insert_seq_after (&bsi, stmt_list, GSI_CONTINUE_LINKING);
   res = true;
 
@@ -322,27 +317,20 @@ static void
 prop_phis (basic_block b)
 {
   gimple_stmt_iterator psi;
-  gimple_seq phis = phi_nodes (b);
 
-  for (psi = gsi_start (phis); !gsi_end_p (psi); )
+  for (psi = gsi_start_phis (b); !gsi_end_p (psi); )
     {
       gimple phi = gsi_stmt (psi);
-      tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0);
-
-      gcc_assert (gimple_phi_num_args (phi) == 1);
+      tree def = gimple_phi_result (phi);
 
       if (!is_gimple_reg (def))
+       mark_virtual_phi_result_for_renaming (phi);
+      else
        {
-         imm_use_iterator iter;
-         use_operand_p use_p;
-         gimple stmt;
-
-         FOR_EACH_IMM_USE_STMT (stmt, iter, def)
-           FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
-             SET_USE (use_p, use);
+         tree use = gimple_phi_arg_def (phi, 0);
+         gcc_assert (gimple_phi_num_args (phi) == 1);
+         replace_uses_by (def, use);
        }
-      else
-       replace_uses_by (def, use);
 
       remove_phi_node (&psi, true);
     }
@@ -389,6 +377,8 @@ generate_builtin (struct loop *loop, bitmap partition, bool copy_p)
                goto end;
 
              write = stmt;
+             if (bb == loop->latch)
+               nb_iter = number_of_latch_executions (loop);
            }
        }
     }
@@ -400,7 +390,7 @@ generate_builtin (struct loop *loop, bitmap partition, bool copy_p)
   op1 = gimple_assign_rhs1 (write);
 
   if (!(TREE_CODE (op0) == ARRAY_REF
-       || TREE_CODE (op0) == INDIRECT_REF))
+       || TREE_CODE (op0) == MEM_REF))
     goto end;
 
   /* The new statements will be placed before LOOP.  */
@@ -520,13 +510,11 @@ mark_nodes_having_upstream_mem_writes (struct graph *rdg)
 
        graphds_dfs (rdg, &v, 1, &nodes, false, NULL);
 
-       for (i = 0; VEC_iterate (int, nodes, i, x); i++)
+       FOR_EACH_VEC_ELT (int, nodes, i, x)
          {
-           if (bitmap_bit_p (seen, x))
+           if (!bitmap_set_bit (seen, x))
              continue;
 
-           bitmap_set_bit (seen, x);
-
            if (RDG_MEM_WRITE_STMT (rdg, x)
                || predecessor_has_mem_write (rdg, &(rdg->vertices[x]))
                /* In anti dependences the read should occur before
@@ -647,12 +635,11 @@ rdg_flag_vertex (struct graph *rdg, int v, bitmap partition, bitmap loops,
 {
   struct loop *loop;
 
-  if (bitmap_bit_p (partition, v))
+  if (!bitmap_set_bit (partition, v))
     return;
 
   loop = loop_containing_stmt (RDG_STMT (rdg, v));
   bitmap_set_bit (loops, loop->num);
-  bitmap_set_bit (partition, v);
 
   if (rdg_cannot_recompute_vertex_p (rdg, v))
     {
@@ -678,7 +665,7 @@ rdg_flag_vertex_and_dependent (struct graph *rdg, int v, bitmap partition,
   graphds_dfs (rdg, &v, 1, &nodes, false, remaining_stmts);
   rdg_flag_vertex (rdg, v, partition, loops, part_has_writes);
 
-  for (i = 0; VEC_iterate (int, nodes, i, x); i++)
+  FOR_EACH_VEC_ELT (int, nodes, i, x)
     if (!already_processed_vertex_p (processed, x))
       rdg_flag_vertex_and_dependent (rdg, x, partition, loops, processed,
                                     part_has_writes);
@@ -696,7 +683,7 @@ collect_condition_stmts (struct loop *loop, VEC (gimple, heap) **conds)
   edge e;
   VEC (edge, heap) *exits = get_loop_exit_edges (loop);
 
-  for (i = 0; VEC_iterate (edge, exits, i, e); i++)
+  FOR_EACH_VEC_ELT (edge, exits, i, e)
     {
       gimple cond = last_stmt (e->src);
 
@@ -733,11 +720,8 @@ rdg_flag_loop_exits (struct graph *rdg, bitmap loops, bitmap partition,
                                       part_has_writes);
 
       EXECUTE_IF_SET_IN_BITMAP (new_loops, 0, i, bi)
-       if (!bitmap_bit_p (loops, i))
-         {
-           bitmap_set_bit (loops, i);
-           collect_condition_stmts (get_loop (i), &conds);
-         }
+       if (bitmap_set_bit (loops, i))
+         collect_condition_stmts (get_loop (i), &conds);
 
       BITMAP_FREE (new_loops);
     }
@@ -780,7 +764,7 @@ rdg_flag_similar_memory_accesses (struct graph *rdg, bitmap partition,
 
              /* Remove from OTHER_STORES the vertex that we flagged.  */
              if (RDG_MEM_WRITE_STMT (rdg, j))
-               for (k = 0; VEC_iterate (int, *other_stores, k, kk); k++)
+               FOR_EACH_VEC_ELT (int, *other_stores, k, kk)
                  if (kk == j)
                    {
                      VEC_unordered_remove (int, *other_stores, k);
@@ -811,7 +795,7 @@ build_rdg_partition_for_component (struct graph *rdg, rdgc c,
   bitmap loops = BITMAP_ALLOC (NULL);
   bitmap processed = BITMAP_ALLOC (NULL);
 
-  for (i = 0; VEC_iterate (int, c->vertices, i, v); i++)
+  FOR_EACH_VEC_ELT (int, c->vertices, i, v)
     if (!already_processed_vertex_p (processed, v))
       rdg_flag_vertex_and_dependent (rdg, v, partition, loops, processed,
                                     part_has_writes);
@@ -838,7 +822,7 @@ free_rdg_components (VEC (rdgc, heap) *components)
   int i;
   rdgc x;
 
-  for (i = 0; VEC_iterate (rdgc, components, i, x); i++)
+  FOR_EACH_VEC_ELT (rdgc, components, i, x)
     {
       VEC_free (int, heap, x->vertices);
       free (x);
@@ -863,18 +847,17 @@ rdg_build_components (struct graph *rdg, VEC (int, heap) *starting_vertices,
   for (i = 0; i < rdg->n_vertices; i++)
     VEC_safe_push (int, heap, all_components[rdg->vertices[i].component], i);
 
-  for (i = 0; VEC_iterate (int, starting_vertices, i, v); i++)
+  FOR_EACH_VEC_ELT (int, starting_vertices, i, v)
     {
       int c = rdg->vertices[v].component;
 
-      if (!bitmap_bit_p (saved_components, c))
+      if (bitmap_set_bit (saved_components, c))
        {
          rdgc x = XCNEW (struct rdg_component);
          x->num = c;
          x->vertices = all_components[c];
 
          VEC_safe_push (rdgc, heap, *components, x);
-         bitmap_set_bit (saved_components, c);
        }
     }
 
@@ -899,7 +882,7 @@ rdg_build_partitions (struct graph *rdg, VEC (rdgc, heap) *components,
   rdgc x;
   bitmap partition = BITMAP_ALLOC (NULL);
 
-  for (i = 0; VEC_iterate (rdgc, components, i, x); i++)
+  FOR_EACH_VEC_ELT (rdgc, components, i, x)
     {
       bitmap np;
       bool part_has_writes = false;
@@ -965,14 +948,14 @@ dump_rdg_partitions (FILE *file, VEC (bitmap, heap) *partitions)
   int i;
   bitmap partition;
 
-  for (i = 0; VEC_iterate (bitmap, partitions, i, partition); i++)
+  FOR_EACH_VEC_ELT (bitmap, partitions, i, partition)
     debug_bitmap_file (file, partition);
 }
 
 /* Debug PARTITIONS.  */
 extern void debug_rdg_partitions (VEC (bitmap, heap) *);
 
-void
+DEBUG_FUNCTION void
 debug_rdg_partitions (VEC (bitmap, heap) *partitions)
 {
   dump_rdg_partitions (stderr, partitions);
@@ -1029,7 +1012,7 @@ partition_contains_all_rw (struct graph *rdg, VEC (bitmap, heap) *partitions)
   bitmap partition;
   int nrw = number_of_rw_in_rdg (rdg);
 
-  for (i = 0; VEC_iterate (bitmap, partitions, i, partition); i++)
+  FOR_EACH_VEC_ELT (bitmap, partitions, i, partition)
     if (nrw == number_of_rw_in_partition (rdg, partition))
       return true;
 
@@ -1064,7 +1047,7 @@ ldist_gen (struct loop *loop, struct graph *rdg,
          unsigned j;
          bool found = false;
 
-         for (j = 0; VEC_iterate (int, starting_vertices, j, v); j++)
+         FOR_EACH_VEC_ELT (int, starting_vertices, j, v)
            if (i == v)
              {
                found = true;
@@ -1090,7 +1073,7 @@ ldist_gen (struct loop *loop, struct graph *rdg,
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_rdg_partitions (dump_file, partitions);
 
-  for (i = 0; VEC_iterate (bitmap, partitions, i, partition); i++)
+  FOR_EACH_VEC_ELT (bitmap, partitions, i, partition)
     if (!generate_code_for_partition (loop, partition, i < nbp - 1))
       goto ldist_done;
 
@@ -1102,7 +1085,7 @@ ldist_gen (struct loop *loop, struct graph *rdg,
   BITMAP_FREE (remaining_stmts);
   BITMAP_FREE (upstream_mem_writes);
 
-  for (i = 0; VEC_iterate (bitmap, partitions, i, partition); i++)
+  FOR_EACH_VEC_ELT (bitmap, partitions, i, partition)
     BITMAP_FREE (partition);
 
   VEC_free (int, heap, other_stores);
@@ -1153,7 +1136,7 @@ distribute_loop (struct loop *loop, VEC (gimple, heap) *stmts)
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_rdg (dump_file, rdg);
 
-  for (i = 0; VEC_iterate (gimple, stmts, i, s); i++)
+  FOR_EACH_VEC_ELT (gimple, stmts, i, s)
     {
       int v = rdg_vertex_for_stmt (rdg, s);
 
@@ -1187,18 +1170,36 @@ tree_loop_distribution (void)
     {
       VEC (gimple, heap) *work_list = VEC_alloc (gimple, heap, 3);
 
-      /* With the following working list, we're asking distribute_loop
-        to separate the stores of the loop: when dependences allow,
-        it will end on having one store per loop.  */
-      stores_from_loop (loop, &work_list);
-
-      /* A simple heuristic for cache locality is to not split stores
-        to the same array.  Without this call, an unrolled loop would
-        be split into as many loops as unroll factor, each loop
-        storing in the same array.  */
-      remove_similar_memory_refs (&work_list);
-
-      nb_generated_loops = distribute_loop (loop, work_list);
+      /* If both flag_tree_loop_distribute_patterns and
+        flag_tree_loop_distribution are set, then only
+        distribute_patterns is executed.  */
+      if (flag_tree_loop_distribute_patterns)
+       {
+         /* With the following working list, we're asking
+            distribute_loop to separate from the rest of the loop the
+            stores of the form "A[i] = 0".  */
+         stores_zero_from_loop (loop, &work_list);
+
+         /* Do nothing if there are no patterns to be distributed.  */
+         if (VEC_length (gimple, work_list) > 0)
+           nb_generated_loops = distribute_loop (loop, work_list);
+       }
+      else if (flag_tree_loop_distribution)
+       {
+         /* With the following working list, we're asking
+            distribute_loop to separate the stores of the loop: when
+            dependences allow, it will end on having one store per
+            loop.  */
+         stores_from_loop (loop, &work_list);
+
+         /* A simple heuristic for cache locality is to not split
+            stores to the same array.  Without this call, an unrolled
+            loop would be split into as many loops as unroll factor,
+            each loop storing in the same array.  */
+         remove_similar_memory_refs (&work_list);
+
+         nb_generated_loops = distribute_loop (loop, work_list);
+       }
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -1220,7 +1221,8 @@ tree_loop_distribution (void)
 static bool
 gate_tree_loop_distribution (void)
 {
-  return flag_tree_loop_distribution != 0;
+  return flag_tree_loop_distribution
+    || flag_tree_loop_distribute_patterns;
 }
 
 struct gimple_opt_pass pass_loop_distribution =
@@ -1238,6 +1240,6 @@ struct gimple_opt_pass pass_loop_distribution =
   0,                           /* properties_provided */
   0,                           /* properties_destroyed */
   0,                           /* todo_flags_start */
-  TODO_dump_func | TODO_verify_loops            /* todo_flags_finish */
+  TODO_dump_func                /* todo_flags_finish */
  }
 };