OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / tree-predcom.c
index 94245a4..0ce35f5 100644 (file)
@@ -1,5 +1,5 @@
 /* Predictive commoning.
-   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
    
 This file is part of GCC.
    
@@ -210,7 +210,7 @@ along with GCC; see the file COPYING3.  If not see
 /* Data references (or phi nodes that carry data reference values across
    loop iterations).  */
 
-typedef struct dref
+typedef struct dref_d
 {
   /* The reference itself.  */
   struct data_reference *ref;
@@ -267,7 +267,7 @@ typedef struct chain
 
   /* For combination chains, the operator and the two chains that are
      combined, and the type of the result.  */
-  enum tree_code operator;
+  enum tree_code op;
   tree rslt_type;
   struct chain *ch1, *ch2;
 
@@ -409,7 +409,7 @@ dump_chain (FILE *file, chain_p chain)
   if (chain->type == CT_COMBINATION)
     {
       fprintf (file, "  equal to %p %s %p in type ",
-              (void *) chain->ch1, op_symbol_code (chain->operator),
+              (void *) chain->ch1, op_symbol_code (chain->op),
               (void *) chain->ch2);
       print_generic_expr (file, chain->rslt_type, TDF_SLIM);
       fprintf (file, "\n");
@@ -775,7 +775,7 @@ split_data_refs_to_components (struct loop *loop,
          comps[ca] = comp;
        }
 
-      dataref = XCNEW (struct dref);
+      dataref = XCNEW (struct dref_d);
       dataref->ref = dr;
       dataref->stmt = DR_STMT (dr);
       dataref->offset = double_int_zero;
@@ -877,7 +877,12 @@ filter_suitable_components (struct loop *loop, struct component *comps)
        comp = &act->next;
       else
        {
+         dref ref;
+         unsigned i;
+
          *comp = act->next;
+         for (i = 0; VEC_iterate (dref, act->refs, i, ref); i++)
+           free (ref);
          release_component (act);
        }
     }
@@ -920,7 +925,10 @@ add_ref_to_chain (chain_p chain, dref ref)
   gcc_assert (double_int_scmp (root->offset, ref->offset) <= 0);
   dist = double_int_add (ref->offset, double_int_neg (root->offset));
   if (double_int_ucmp (uhwi_to_double_int (MAX_DISTANCE), dist) <= 0)
-    return;
+    {
+      free (ref);
+      return;
+    }
   gcc_assert (double_int_fits_in_uhwi_p (dist));
 
   VEC_safe_push (dref, heap, chain->refs, ref);
@@ -1018,9 +1026,6 @@ valid_initializer_p (struct data_reference *ref,
   aff_tree diff, base, step;
   double_int off;
 
-  if (!DR_BASE_ADDRESS (ref))
-    return false;
-
   /* Both REF and ROOT must be accessing the same object.  */
   if (!operand_equal_p (DR_BASE_ADDRESS (ref), DR_BASE_ADDRESS (root), 0))
     return false;
@@ -1107,7 +1112,8 @@ find_looparound_phi (struct loop *loop, dref ref, dref root)
   memset (&init_dr, 0, sizeof (struct data_reference));
   DR_REF (&init_dr) = init_ref;
   DR_STMT (&init_dr) = phi;
-  dr_analyze_innermost (&init_dr);
+  if (!dr_analyze_innermost (&init_dr))
+    return NULL;
 
   if (!valid_initializer_p (&init_dr, ref->distance + 1, root->ref))
     return NULL;
@@ -1120,7 +1126,7 @@ find_looparound_phi (struct loop *loop, dref ref, dref root)
 static void
 insert_looparound_copy (chain_p chain, dref ref, gimple phi)
 {
-  dref nw = XCNEW (struct dref), aref;
+  dref nw = XCNEW (struct dref_d), aref;
   unsigned i;
 
   nw->stmt = phi;
@@ -1224,12 +1230,12 @@ determine_roots (struct loop *loop,
 }
 
 /* Replace the reference in statement STMT with temporary variable
-   NEW.  If SET is true, NEW is instead initialized to the value of
+   NEW_TREE.  If SET is true, NEW_TREE is instead initialized to the value of
    the reference in the statement.  IN_LHS is true if the reference
    is in the lhs of STMT, false if it is in rhs.  */
 
 static void
-replace_ref_with (gimple stmt, tree new, bool set, bool in_lhs)
+replace_ref_with (gimple stmt, tree new_tree, bool set, bool in_lhs)
 {
   tree val;
   gimple new_stmt;
@@ -1245,7 +1251,7 @@ replace_ref_with (gimple stmt, tree new, bool set, bool in_lhs)
       remove_phi_node (&psi, false);
 
       /* Turn the phi node into GIMPLE_ASSIGN.  */
-      new_stmt = gimple_build_assign (val, new);
+      new_stmt = gimple_build_assign (val, new_tree);
       gsi_insert_before (&bsi, new_stmt, GSI_NEW_STMT);
       return;
     }
@@ -1256,11 +1262,11 @@ replace_ref_with (gimple stmt, tree new, bool set, bool in_lhs)
 
   bsi = gsi_for_stmt (stmt);
 
-  /* If we do not need to initialize NEW, just replace the use of OLD.  */
+  /* If we do not need to initialize NEW_TREE, just replace the use of OLD.  */
   if (!set)
     {
       gcc_assert (!in_lhs);
-      gimple_assign_set_rhs_from_tree (&bsi, new);
+      gimple_assign_set_rhs_from_tree (&bsi, new_tree);
       stmt = gsi_stmt (bsi);
       update_stmt (stmt);
       return;
@@ -1306,7 +1312,7 @@ replace_ref_with (gimple stmt, tree new, bool set, bool in_lhs)
       val = gimple_assign_lhs (stmt);
     }
 
-  new_stmt = gimple_build_assign (new, unshare_expr (val));
+  new_stmt = gimple_build_assign (new_tree, unshare_expr (val));
   gsi_insert_after (&bsi, new_stmt, GSI_NEW_STMT);
 }
 
@@ -1368,7 +1374,7 @@ ref_at_iteration (struct loop *loop, tree ref, int iter)
   else
     return NULL_TREE;
 
-  ok = simple_iv (loop, first_stmt (loop->header), idx, &iv, true);
+  ok = simple_iv (loop, loop, idx, &iv, true);
   if (!ok)
     return NULL_TREE;
   iv.base = expand_simple_operations (iv.base);
@@ -1406,7 +1412,7 @@ get_init_expr (chain_p chain, unsigned index)
       tree e1 = get_init_expr (chain->ch1, index);
       tree e2 = get_init_expr (chain->ch2, index);
 
-      return fold_build2 (chain->operator, chain->rslt_type, e1, e2);
+      return fold_build2 (chain->op, chain->rslt_type, e1, e2);
     }
   else
     return VEC_index (tree, chain->inits, index);
@@ -1417,7 +1423,6 @@ get_init_expr (chain_p chain, unsigned index)
 void
 mark_virtual_ops_for_renaming (gimple stmt)
 {
-  ssa_op_iter iter;
   tree var;
 
   if (gimple_code (stmt) == GIMPLE_PHI)
@@ -1433,24 +1438,8 @@ mark_virtual_ops_for_renaming (gimple stmt)
     }
 
   update_stmt (stmt);
-
-  FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
-    {
-      if (TREE_CODE (var) == SSA_NAME)
-       var = SSA_NAME_VAR (var);
-      mark_sym_for_renaming (var);
-    }
-}
-
-/* Calls mark_virtual_ops_for_renaming for all members of LIST.  */
-
-static void
-mark_virtual_ops_for_renaming_list (gimple_seq list)
-{
-  gimple_stmt_iterator gsi;
-
-  for (gsi = gsi_start (list); !gsi_end_p (gsi); gsi_next (&gsi))
-    mark_virtual_ops_for_renaming (gsi_stmt (gsi));
+  if (gimple_vuse (stmt))
+    mark_sym_for_renaming (gimple_vop (cfun));
 }
 
 /* Returns a new temporary variable used for the I-th variable carrying
@@ -1519,15 +1508,12 @@ initialize_root_vars (struct loop *loop, chain_p chain, bitmap tmp_vars)
 
       init = force_gimple_operand (init, &stmts, true, NULL_TREE);
       if (stmts)
-       {
-         mark_virtual_ops_for_renaming_list (stmts);
-         gsi_insert_seq_on_edge_immediate (entry, stmts);
-       }
+       gsi_insert_seq_on_edge_immediate (entry, stmts);
 
       phi = create_phi_node (var, loop->header);
       SSA_NAME_DEF_STMT (var) = phi;
-      add_phi_arg (phi, init, entry);
-      add_phi_arg (phi, next, latch);
+      add_phi_arg (phi, init, entry, UNKNOWN_LOCATION);
+      add_phi_arg (phi, next, latch, UNKNOWN_LOCATION);
     }
 }
 
@@ -1583,18 +1569,15 @@ initialize_root_vars_lm (struct loop *loop, dref root, bool written,
       
   init = force_gimple_operand (init, &stmts, written, NULL_TREE);
   if (stmts)
-    {
-      mark_virtual_ops_for_renaming_list (stmts);
-      gsi_insert_seq_on_edge_immediate (entry, stmts);
-    }
+    gsi_insert_seq_on_edge_immediate (entry, stmts);
 
   if (written)
     {
       next = VEC_index (tree, *vars, 1);
       phi = create_phi_node (var, loop->header);
       SSA_NAME_DEF_STMT (var) = phi;
-      add_phi_arg (phi, init, entry);
-      add_phi_arg (phi, next, latch);
+      add_phi_arg (phi, init, entry, UNKNOWN_LOCATION);
+      add_phi_arg (phi, next, latch, UNKNOWN_LOCATION);
     }
   else
     {
@@ -1887,43 +1870,6 @@ execute_pred_commoning_cbck (struct loop *loop, void *data)
   execute_pred_commoning (loop, dta->chains, dta->tmp_vars);
 }
 
-/* Returns true if we can and should unroll LOOP FACTOR times.  Number
-   of iterations of the loop is returned in NITER.  */
-
-static bool
-should_unroll_loop_p (struct loop *loop, unsigned factor,
-                     struct tree_niter_desc *niter)
-{
-  edge exit;
-
-  if (factor == 1)
-    return false;
-
-  /* Check whether unrolling is possible.  We only want to unroll loops
-     for that we are able to determine number of iterations.  We also
-     want to split the extra iterations of the loop from its end,
-     therefore we require that the loop has precisely one
-     exit.  */
-
-  exit = single_dom_exit (loop);
-  if (!exit)
-    return false;
-
-  if (!number_of_iterations_exit (loop, exit, niter, false))
-    return false;
-
-  /* And of course, we must be able to duplicate the loop.  */
-  if (!can_duplicate_loop_p (loop))
-    return false;
-
-  /* The final loop should be small enough.  */
-  if (tree_num_loop_insns (loop, &eni_size_weights) * factor
-      > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLLED_INSNS))
-    return false;
-
-  return true;
-}
-
 /* Base NAME and all the names in the chain of phi nodes that use it
    on variable VAR.  The phi nodes are recognized by being in the copies of
    the header of the LOOP.  */
@@ -2347,7 +2293,7 @@ combine_chains (chain_p ch1, chain_p ch2)
 
   new_chain = XCNEW (struct chain);
   new_chain->type = CT_COMBINATION;
-  new_chain->operator = op;
+  new_chain->op = op;
   new_chain->ch1 = ch1;
   new_chain->ch2 = ch2;
   new_chain->rslt_type = rslt_type;
@@ -2356,7 +2302,7 @@ combine_chains (chain_p ch1, chain_p ch2)
   for (i = 0; (VEC_iterate (dref, ch1->refs, i, r1)
               && VEC_iterate (dref, ch2->refs, i, r2)); i++)
     {
-      nw = XCNEW (struct dref);
+      nw = XCNEW (struct dref_d);
       nw->stmt = stmt_combining_refs (r1, r2);
       nw->distance = r1->distance;
 
@@ -2415,31 +2361,6 @@ try_combine_chains (VEC (chain_p, heap) **chains)
     }
 }
 
-/* Sets alias information based on data reference DR for REF,
-   if necessary.  */
-
-static void
-set_alias_info (tree ref, struct data_reference *dr)
-{
-  tree var;
-  tree tag = DR_SYMBOL_TAG (dr);
-
-  gcc_assert (tag != NULL_TREE);
-
-  ref = get_base_address (ref);
-  if (!ref || !INDIRECT_REF_P (ref))
-    return;
-
-  var = SSA_NAME_VAR (TREE_OPERAND (ref, 0));
-  if (var_ann (var)->symbol_mem_tag)
-    return;
-
-  if (!MTAG_P (tag))
-    new_type_alias (var, tag, ref);
-  else
-    var_ann (var)->symbol_mem_tag = tag;
-}
-
 /* Prepare initializers for CHAIN in LOOP.  Returns false if this is
    impossible because one of these initializers may trap, true otherwise.  */
 
@@ -2485,11 +2406,7 @@ prepare_initializers_chain (struct loop *loop, chain_p chain)
 
       init = force_gimple_operand (init, &stmts, false, NULL_TREE);
       if (stmts)
-       {
-         mark_virtual_ops_for_renaming_list (stmts);
-         gsi_insert_seq_on_edge_immediate (entry, stmts);
-       }
-      set_alias_info (init, dr);
+       gsi_insert_seq_on_edge_immediate (entry, stmts);
 
       VEC_replace (tree, chain->inits, i, init);
     }
@@ -2590,7 +2507,8 @@ tree_predictive_commoning_loop (struct loop *loop)
      that its number of iterations is divisible by the factor.  */
   unroll_factor = determine_unroll_factor (chains);
   scev_reset ();
-  unroll = should_unroll_loop_p (loop, unroll_factor, &desc);
+  unroll = (unroll_factor > 1
+           && can_unroll_loop_p (loop, unroll_factor, &desc));
   exit = single_dom_exit (loop);
 
   /* Execute the predictive commoning transformations, and possibly unroll the
@@ -2650,9 +2568,10 @@ tree_predictive_commoning (void)
 
   initialize_original_copy_tables ();
   FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
-    {
-      unrolled |= tree_predictive_commoning_loop (loop);
-    }
+    if (optimize_loop_for_speed_p (loop))
+      {
+       unrolled |= tree_predictive_commoning_loop (loop);
+      }
 
   if (unrolled)
     {