OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / tree-predcom.c
index 8745969..6fa80ee 100644 (file)
@@ -1,11 +1,11 @@
 /* Predictive commoning.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007 Free Software Foundation, Inc.
    
 This file is part of GCC.
    
 GCC is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
+Free Software Foundation; either version 3, or (at your option) any
 later version.
    
 GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -14,9 +14,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
    
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This file implements the predictive commoning optimization.  Predictive
    commoning can be viewed as CSE around a loop, and with some improvements,
@@ -628,6 +627,13 @@ determine_offset (struct data_reference *a, struct data_reference *b,
                  double_int *off)
 {
   aff_tree diff, baseb, step;
+  tree typea, typeb;
+
+  /* Check that both the references access the location in the same type.  */
+  typea = TREE_TYPE (DR_REF (a));
+  typeb = TREE_TYPE (DR_REF (b));
+  if (!useless_type_conversion_p (typeb, typea))
+    return false;
 
   /* Check whether the base address and the step of both references is the
      same.  */
@@ -700,7 +706,7 @@ split_data_refs_to_components (struct loop *loop,
             just fail.  */
          goto end;
        }
-      dr->aux = i;
+      dr->aux = (void *) (size_t) i;
       comp_father[i] = i;
       comp_size[i] = 1;
     }
@@ -715,7 +721,7 @@ split_data_refs_to_components (struct loop *loop,
 
       if (!suitable_reference_p (dr, &dummy))
        {
-         ia = dr->aux;
+         ia = (unsigned) (size_t) dr->aux;
          merge_comps (comp_father, comp_size, n, ia);
        }
     }
@@ -729,8 +735,8 @@ split_data_refs_to_components (struct loop *loop,
 
       dra = DDR_A (ddr);
       drb = DDR_B (ddr);
-      ia = component_of (comp_father, dra->aux);
-      ib = component_of (comp_father, drb->aux);
+      ia = component_of (comp_father, (unsigned) (size_t) dra->aux);
+      ib = component_of (comp_father, (unsigned) (size_t) drb->aux);
       if (ia == ib)
        continue;
 
@@ -749,7 +755,7 @@ split_data_refs_to_components (struct loop *loop,
   bad = component_of (comp_father, n);
   for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
     {
-      ia = dr->aux;
+      ia = (unsigned) (size_t) dr->aux;
       ca = component_of (comp_father, ia);
       if (ca == bad)
        continue;
@@ -793,7 +799,7 @@ end:
 }
 
 /* Returns true if the component COMP satisfies the conditions
-   described in 2) at the begining of this file.  LOOP is the current
+   described in 2) at the beginning of this file.  LOOP is the current
    loop.  */
       
 static bool
@@ -850,7 +856,7 @@ suitable_component_p (struct loop *loop, struct component *comp)
 /* Check the conditions on references inside each of components COMPS,
    and remove the unsuitable components from the list.  The new list
    of components is returned.  The conditions are described in 2) at
-   the begining of this file.  LOOP is the current loop.  */
+   the beginning of this file.  LOOP is the current loop.  */
 
 static struct component *
 filter_suitable_components (struct loop *loop, struct component *comps)
@@ -1225,7 +1231,7 @@ replace_ref_with (tree stmt, tree new, bool set, bool in_lhs)
       remove_phi_node (stmt, NULL_TREE, false);
 
       /* Turn the phi node into GIMPLE_MODIFY_STMT.  */
-      new_stmt = build_gimple_modify_stmt_stat (val, new);
+      new_stmt = build_gimple_modify_stmt (val, new);
       SSA_NAME_DEF_STMT (val) = new_stmt;
       bsi_insert_before (&bsi, new_stmt, BSI_NEW_STMT);
       return;
@@ -1271,7 +1277,7 @@ replace_ref_with (tree stmt, tree new, bool set, bool in_lhs)
         NEW = VAL  */
     }
 
-  new_stmt = build_gimple_modify_stmt_stat (new, unshare_expr (val));
+  new_stmt = build_gimple_modify_stmt (new, unshare_expr (val));
   bsi_insert_after (&bsi, new_stmt, BSI_NEW_STMT);
   SSA_NAME_DEF_STMT (new) = new_stmt;
 }
@@ -1343,9 +1349,18 @@ ref_at_iteration (struct loop *loop, tree ref, int iter)
   else
     {
       type = TREE_TYPE (iv.base);
-      val = fold_build2 (MULT_EXPR, type, iv.step,
-                        build_int_cst_type (type, iter));
-      val = fold_build2 (PLUS_EXPR, type, iv.base, val);
+      if (POINTER_TYPE_P (type))
+       {
+         val = fold_build2 (MULT_EXPR, sizetype, iv.step,
+                            size_int (iter));
+         val = fold_build2 (POINTER_PLUS_EXPR, type, iv.base, val);
+       }
+      else
+       {
+         val = fold_build2 (MULT_EXPR, type, iv.step,
+                            build_int_cst_type (type, iter));
+         val = fold_build2 (PLUS_EXPR, type, iv.base, val);
+       }
       *idx_p = unshare_expr (val);
     }
 
@@ -1371,14 +1386,23 @@ get_init_expr (chain_p chain, unsigned index)
 
 /* Marks all virtual operands of statement STMT for renaming.  */
 
-static void
+void
 mark_virtual_ops_for_renaming (tree stmt)
 {
   ssa_op_iter iter;
   tree var;
 
   if (TREE_CODE (stmt) == PHI_NODE)
-    return;
+    {
+      var = PHI_RESULT (stmt);
+      if (is_gimple_reg (var))
+       return;
+
+      if (TREE_CODE (var) == SSA_NAME)
+       var = SSA_NAME_VAR (var);
+      mark_sym_for_renaming (var);
+      return;
+    }
 
   update_stmt (stmt);
 
@@ -1401,6 +1425,26 @@ mark_virtual_ops_for_renaming_list (tree list)
     mark_virtual_ops_for_renaming (tsi_stmt (tsi));
 }
 
+/* Returns a new temporary variable used for the I-th variable carrying
+   value of REF.  The variable's uid is marked in TMP_VARS.  */
+
+static tree
+predcom_tmp_var (tree ref, unsigned i, bitmap tmp_vars)
+{
+  tree type = TREE_TYPE (ref);
+  tree var = create_tmp_var (type, get_lsm_tmp_name (ref, i));
+
+  /* We never access the components of the temporary variable in predictive
+     commoning.  */
+  if (TREE_CODE (type) == COMPLEX_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (var) = 1;
+
+  add_referenced_var (var);
+  bitmap_set_bit (tmp_vars, DECL_UID (var));
+  return var;
+}
+
 /* Creates the variables for CHAIN, as well as phi nodes for them and
    initialization on entry to LOOP.  Uids of the newly created
    temporary variables are marked in TMP_VARS.  */
@@ -1429,9 +1473,7 @@ initialize_root_vars (struct loop *loop, chain_p chain, bitmap tmp_vars)
 
   for (i = 0; i < n + (reuse_first ? 0 : 1); i++)
     {
-      var = create_tmp_var (TREE_TYPE (ref), get_lsm_tmp_name (ref, i));
-      add_referenced_var (var);
-      bitmap_set_bit (tmp_vars, DECL_UID (var));
+      var = predcom_tmp_var (ref, i, tmp_vars);
       VEC_quick_push (tree, chain->vars, var);
     }
   if (reuse_first)
@@ -1499,9 +1541,7 @@ initialize_root_vars_lm (struct loop *loop, dref root, bool written,
   init = VEC_index (tree, inits, 0);
 
   *vars = VEC_alloc (tree, heap, written ? 2 : 1);
-  var = create_tmp_var (TREE_TYPE (ref), get_lsm_tmp_name (ref, 0));
-  add_referenced_var (var);
-  bitmap_set_bit (tmp_vars, DECL_UID (var));
+  var = predcom_tmp_var (ref, 0, tmp_vars);
   VEC_quick_push (tree, *vars, var);
   if (written)
     VEC_quick_push (tree, *vars, VEC_index (tree, *vars, 0));
@@ -1528,7 +1568,7 @@ initialize_root_vars_lm (struct loop *loop, dref root, bool written,
     }
   else
     {
-      init = build_gimple_modify_stmt_stat (var, init);
+      init = build_gimple_modify_stmt (var, init);
       SSA_NAME_DEF_STMT (var) = init;
       mark_virtual_ops_for_renaming (init);
       bsi_insert_on_edge_immediate (entry, init);
@@ -1752,7 +1792,7 @@ execute_pred_commoning (struct loop *loop, VEC (chain_p, heap) *chains,
   update_ssa (TODO_update_ssa_only_virtuals);
 }
 
-/* For each reference in CHAINS, if its definining statement is
+/* For each reference in CHAINS, if its defining statement is
    ssa name, set it to phi node that defines it.  */
 
 static void
@@ -1771,7 +1811,7 @@ replace_phis_by_defined_names (VEC (chain_p, heap) *chains)
       }
 }
 
-/* For each reference in CHAINS, if its definining statement is
+/* For each reference in CHAINS, if its defining statement is
    phi node, set it to the ssa name that is defined by it.  */
 
 static void
@@ -1909,7 +1949,13 @@ eliminate_temp_copies (struct loop *loop, bitmap tmp_vars)
 
       /* Base all the ssa names in the ud and du chain of NAME on VAR.  */
       stmt = SSA_NAME_DEF_STMT (use);
-      while (TREE_CODE (stmt) == PHI_NODE)
+      while (TREE_CODE (stmt) == PHI_NODE
+            /* In case we could not unroll the loop enough to eliminate
+               all copies, we may reach the loop header before the defining
+               statement (in that case, some register copies will be present
+               in loop latch in the final code, corresponding to the newly
+               created looparound phi nodes).  */
+            && bb_for_stmt (stmt) != loop->header)
        {
          gcc_assert (single_pred_p (bb_for_stmt (stmt)));
          use = PHI_ARG_DEF (stmt, 0);
@@ -2018,7 +2064,7 @@ find_associative_operation_root (tree stmt, unsigned *distance)
 
 /* Returns the common statement in that NAME1 and NAME2 have a use.  If there
    is no such statement, returns NULL_TREE.  In case the operation used on
-   NAME1 and NAME2 is associative and comutative, returns the root of the
+   NAME1 and NAME2 is associative and commutative, returns the root of the
    tree formed by this operation instead of the statement that uses NAME1 or
    NAME2.  */
 
@@ -2169,14 +2215,14 @@ reassociate_to_the_same_stmt (tree name1, tree name2)
   var = create_tmp_var (type, "predreastmp");
   add_referenced_var (var);
   new_name = make_ssa_name (var, NULL_TREE);
-  new_stmt = build_gimple_modify_stmt_stat (new_name,
+  new_stmt = build_gimple_modify_stmt (new_name,
                            fold_build2 (code, type, name1, name2));
   SSA_NAME_DEF_STMT (new_name) = new_stmt;
 
   var = create_tmp_var (type, "predreastmp");
   add_referenced_var (var);
   tmp_name = make_ssa_name (var, NULL_TREE);
-  tmp_stmt = build_gimple_modify_stmt_stat (tmp_name,
+  tmp_stmt = build_gimple_modify_stmt (tmp_name,
                                            GIMPLE_STMT_OPERAND (s1, 1));
   SSA_NAME_DEF_STMT (tmp_name) = tmp_stmt;
 
@@ -2545,12 +2591,13 @@ end: ;
 
 /* Runs predictive commoning.  */
 
-void
+unsigned
 tree_predictive_commoning (void)
 {
   bool unrolled = false;
   struct loop *loop;
   loop_iterator li;
+  unsigned ret = 0;
 
   initialize_original_copy_tables ();
   FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
@@ -2561,7 +2608,9 @@ tree_predictive_commoning (void)
   if (unrolled)
     {
       scev_reset ();
-      cleanup_tree_cfg_loop ();
+      ret = TODO_cleanup_cfg;
     }
   free_original_copy_tables ();
+
+  return ret;
 }