OSDN Git Service

In libobjc/:
[pf3gnuchains/gcc-fork.git] / gcc / tree-parloops.c
index 56b88a8..4fc67a3 100644 (file)
@@ -1,5 +1,6 @@
 /* Loop autoparallelization.
-   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
    Contributed by Sebastian Pop <pop@cri.ensmp.fr> and
    Zdenek Dvorak <dvorakz@suse.cz>.
 
@@ -24,12 +25,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tree-flow.h"
 #include "cfgloop.h"
-#include "ggc.h"
 #include "tree-data-ref.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
 #include "tree-pass.h"
 #include "tree-scalar-evolution.h"
 #include "hashtab.h"
@@ -63,7 +63,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /*
   Reduction handling:
-  currently we use vect_is_simple_reduction() to detect reduction patterns.
+  currently we use vect_force_simple_reduction() to detect reduction patterns.
   The code transformation will be introduced by an example.
 
 
@@ -247,7 +247,7 @@ name_to_copy_elt_hash (const void *aa)
    in parallel).  */
 
 static bool
-loop_parallel_p (struct loop *loop)
+loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack)
 {
   VEC (ddr_p, heap) * dependence_relations;
   VEC (data_reference_p, heap) *datarefs;
@@ -272,7 +272,7 @@ loop_parallel_p (struct loop *loop)
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_data_dependence_relations (dump_file, dependence_relations);
 
-  trans = lambda_trans_matrix_new (1, 1);
+  trans = lambda_trans_matrix_new (1, 1, parloop_obstack);
   LTM_MATRIX (trans)[0][0] = -1;
 
   if (lambda_transform_legal_p (trans, 1, dependence_relations))
@@ -357,7 +357,7 @@ take_address_of (tree obj, tree type, edge entry, htab_t decl_address)
 
   if (var_p != &obj)
     {
-      *var_p = build1 (INDIRECT_REF, TREE_TYPE (*var_p), name);
+      *var_p = build_simple_mem_ref (name);
       name = force_gimple_operand (build_addr (obj, current_function_decl),
                                   &stmts, true, NULL_TREE);
       if (!gimple_seq_empty_p (stmts))
@@ -456,7 +456,7 @@ eliminate_local_variables_1 (tree *tp, int *walk_subtrees, void *data)
       type = TREE_TYPE (t);
       addr_type = build_pointer_type (type);
       addr = take_address_of (t, addr_type, dta->entry, dta->decl_address);
-      *tp = build1 (INDIRECT_REF, TREE_TYPE (*tp), addr);
+      *tp = build_simple_mem_ref (addr);
 
       dta->changed = true;
       return NULL_TREE;
@@ -549,7 +549,7 @@ eliminate_local_variables (edge entry, edge exit)
 
   gather_blocks_in_sese_region (entry_bb, exit_bb, &body);
 
-  for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+  FOR_EACH_VEC_ELT (basic_block, body, i, bb)
     if (bb != entry_bb && bb != exit_bb)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        eliminate_local_variables_stmt (entry, gsi_stmt (gsi),
@@ -857,18 +857,16 @@ create_call_for_reduction_1 (void **slot, void *data)
   struct clsn_data *const clsn_data = (struct clsn_data *) data;
   gimple_stmt_iterator gsi;
   tree type = TREE_TYPE (PHI_RESULT (reduc->reduc_phi));
-  tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
   tree load_struct;
   basic_block bb;
   basic_block new_bb;
   edge e;
-  tree t, addr, addr_type, ref, x;
+  tree t, addr, ref, x;
   tree tmp_load, name;
   gimple load;
 
-  load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
+  load_struct = build_simple_mem_ref (clsn_data->load);
   t = build3 (COMPONENT_REF, type, load_struct, reduc->field, NULL_TREE);
-  addr_type = build_pointer_type (type);
 
   addr = build_addr (t, current_function_decl);
 
@@ -926,13 +924,12 @@ create_loads_for_reductions (void **slot, void *data)
   gimple stmt;
   gimple_stmt_iterator gsi;
   tree type = TREE_TYPE (gimple_assign_lhs (red->reduc_stmt));
-  tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
   tree load_struct;
   tree name;
   tree x;
 
   gsi = gsi_after_labels (clsn_data->load_bb);
-  load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
+  load_struct = build_simple_mem_ref (clsn_data->load);
   load_struct = build3 (COMPONENT_REF, type, load_struct, red->field,
                        NULL_TREE);
 
@@ -1013,7 +1010,6 @@ create_loads_and_stores_for_name (void **slot, void *data)
   gimple stmt;
   gimple_stmt_iterator gsi;
   tree type = TREE_TYPE (elt->new_name);
-  tree struct_type = TREE_TYPE (TREE_TYPE (clsn_data->load));
   tree load_struct;
 
   gsi = gsi_last_bb (clsn_data->store_bb);
@@ -1023,7 +1019,7 @@ create_loads_and_stores_for_name (void **slot, void *data)
   gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
 
   gsi = gsi_last_bb (clsn_data->load_bb);
-  load_struct = fold_build1 (INDIRECT_REF, struct_type, clsn_data->load);
+  load_struct = build_simple_mem_ref (clsn_data->load);
   t = build3 (COMPONENT_REF, type, load_struct, elt->field, NULL_TREE);
   stmt = gimple_build_assign (elt->new_name, t);
   SSA_NAME_DEF_STMT (elt->new_name) = stmt;
@@ -1091,7 +1087,7 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
   entry = single_succ_edge (entry_bb);
   gather_blocks_in_sese_region (entry_bb, exit_bb, &body);
 
-  for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+  FOR_EACH_VEC_ELT (basic_block, body, i, bb)
     {
       if (bb != entry_bb && bb != exit_bb)
        {
@@ -1119,7 +1115,7 @@ separate_decls_in_region (edge entry, edge exit, htab_t reduction_list,
      and discard those for which we know there's nothing we can
      do.  */
   if (has_debug_stmt)
-    for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
+    FOR_EACH_VEC_ELT (basic_block, body, i, bb)
       if (bb != entry_bb && bb != exit_bb)
        {
          for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
@@ -1330,7 +1326,6 @@ transform_to_exit_first_loop (struct loop *loop, htab_t reduction_list, tree nit
 
   for (n = 0; bbs[n] != loop->latch; n++)
     continue;
-  n--;
   nbbs = XNEWVEC (basic_block, n);
   ok = gimple_duplicate_sese_tail (single_succ_edge (loop->header), exit,
                                   bbs + 1, n, nbbs);
@@ -1405,7 +1400,7 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
 {
   gimple_stmt_iterator gsi;
   basic_block bb, paral_bb, for_bb, ex_bb;
-  tree t, param, res;
+  tree t, param;
   gimple stmt, for_stmt, phi, cond_stmt;
   tree cvar, cvar_init, initvar, cvar_next, cvar_base, type;
   edge exit, nexit, guard, end, e;
@@ -1474,7 +1469,6 @@ create_parallel_loop (struct loop *loop, tree loop_fn, tree data,
       source_location locus;
       tree def;
       phi = gsi_stmt (gsi);
-      res = PHI_RESULT (phi);
       stmt = SSA_NAME_DEF_STMT (PHI_ARG_DEF_FROM_EDGE (phi, exit));
 
       def = PHI_ARG_DEF_FROM_EDGE (stmt, loop_preheader_edge (loop));
@@ -1531,7 +1525,6 @@ static void
 gen_parallel_loop (struct loop *loop, htab_t reduction_list,
                   unsigned n_threads, struct tree_niter_desc *niter)
 {
-  struct loop *nloop;
   loop_iterator li;
   tree many_iterations_cond, type, nit;
   tree arg_struct, new_arg_struct;
@@ -1624,13 +1617,13 @@ gen_parallel_loop (struct loop *loop, htab_t reduction_list,
 
   /* We assume that the loop usually iterates a lot.  */
   prob = 4 * REG_BR_PROB_BASE / 5;
-  nloop = loop_version (loop, many_iterations_cond, NULL,
-                       prob, prob, REG_BR_PROB_BASE - prob, true);
+  loop_version (loop, many_iterations_cond, NULL,
+               prob, prob, REG_BR_PROB_BASE - prob, true);
   update_ssa (TODO_update_ssa);
   free_original_copy_tables ();
 
   /* Base all the induction variables in LOOP on a single control one.  */
-  canonicalize_loop_ivs (loop, &nit);
+  canonicalize_loop_ivs (loop, &nit, true);
 
   /* Ensure that the exit condition is the first statement in the loop.  */
   transform_to_exit_first_loop (loop, reduction_list, nit);
@@ -1748,7 +1741,9 @@ gather_scalar_reductions (loop_p loop, htab_t reduction_list)
       if (!simple_iv (loop, loop, res, &iv, true)
        && simple_loop_info)
        {
-           gimple reduc_stmt = vect_is_simple_reduction (simple_loop_info, phi, true, &double_reduc);
+           gimple reduc_stmt = vect_force_simple_reduction (simple_loop_info,
+                                                           phi, true,
+                                                           &double_reduc);
           if (reduc_stmt && !double_reduc)
               build_new_reduction (reduction_list, reduc_stmt, phi);
         }
@@ -1887,11 +1882,17 @@ parallelize_loops (void)
   struct tree_niter_desc niter_desc;
   loop_iterator li;
   htab_t reduction_list;
+  struct obstack parloop_obstack;
+  HOST_WIDE_INT estimated;
+  LOC loop_loc;
 
   /* Do not parallelize loops in the functions created by parallelization.  */
   if (parallelized_function_p (cfun->decl))
     return false;
+  if (cfun->has_nonlocal_label)
+    return false;
 
+  gcc_obstack_init (&parloop_obstack);
   reduction_list = htab_create (10, reduction_info_hash,
                                     reduction_info_eq, free);
   init_stmt_vec_info_vec ();
@@ -1929,15 +1930,16 @@ parallelize_loops (void)
       if (/* And of course, the loop must be parallelizable.  */
          !can_duplicate_loop_p (loop)
          || loop_has_blocks_with_irreducible_flag (loop)
+         || (loop_preheader_edge (loop)->src->flags & BB_IRREDUCIBLE_LOOP)
          /* FIXME: the check for vector phi nodes could be removed.  */
          || loop_has_vector_phi_nodes (loop))
        continue;
-
+      estimated = estimated_loop_iterations_int (loop, false);
       /* FIXME: Bypass this check as graphite doesn't update the
       count and frequency correctly now.  */
       if (!flag_loop_parallelize_all
-         && ((estimated_loop_iterations_int (loop, false)
-              <= (HOST_WIDE_INT) n_threads * MIN_PER_THREAD)
+         && ((estimated !=-1 
+            && estimated <= (HOST_WIDE_INT) n_threads * MIN_PER_THREAD)
              /* Do not bother with loops in cold areas.  */
              || optimize_loop_nest_for_size_p (loop)))
        continue;
@@ -1948,37 +1950,39 @@ parallelize_loops (void)
       if (!try_create_reduction_list (loop, reduction_list))
        continue;
 
-      if (!flag_loop_parallelize_all && !loop_parallel_p (loop))
+      if (!flag_loop_parallelize_all
+         && !loop_parallel_p (loop, &parloop_obstack))
        continue;
 
       changed = true;
       if (dump_file && (dump_flags & TDF_DETAILS))
       {
-        fprintf (dump_file, "parallelizing ");
        if (loop->inner)
-         fprintf (dump_file, "outer loop\n");
+         fprintf (dump_file, "parallelizing outer loop %d\n",loop->header->index);
        else
-         fprintf (dump_file, "inner loop\n");
+         fprintf (dump_file, "parallelizing inner loop %d\n",loop->header->index);
+       loop_loc = find_loop_location (loop);
+       if (loop_loc != UNKNOWN_LOC)
+         fprintf (dump_file, "\nloop at %s:%d: ",
+                  LOC_FILE (loop_loc), LOC_LINE (loop_loc));
       }
       gen_parallel_loop (loop, reduction_list,
                         n_threads, &niter_desc);
       verify_flow_info ();
       verify_dominators (CDI_DOMINATORS);
       verify_loop_structure ();
-      verify_loop_closed_ssa ();
+      verify_loop_closed_ssa (true);
     }
 
   free_stmt_vec_info_vec ();
   htab_delete (reduction_list);
+  obstack_free (&parloop_obstack, NULL);
 
   /* Parallelization will cause new function calls to be inserted through
-     which local variables will escape.  Reset the points-to solutions
-     for ESCAPED and CALLUSED.  */
+     which local variables will escape.  Reset the points-to solution
+     for ESCAPED.  */
   if (changed)
-    {
-      pt_solution_reset (&cfun->gimple_df->escaped);
-      pt_solution_reset (&cfun->gimple_df->callused);
-    }
+    pt_solution_reset (&cfun->gimple_df->escaped);
 
   return changed;
 }