OSDN Git Service

PR testsuite/34168
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-dom.c
index 888c5ee..4d95261 100644 (file)
@@ -7,7 +7,7 @@ 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)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -16,9 +16,8 @@ MERCHANTABILITY or 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/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -275,26 +274,19 @@ tree_ssa_dominator_optimize (void)
   init_walk_dominator_tree (&walk_data);
 
   calculate_dominance_info (CDI_DOMINATORS);
+  cfg_altered = false;
 
-  /* We need to know which edges exit loops so that we can
-     aggressively thread through loop headers to an exit
-     edge.  */
-  loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
-  if (current_loops)
-    {
-      mark_loop_exit_edges ();
-      loop_optimizer_finalize ();
-    }
-
-  /* Clean up the CFG so that any forwarder blocks created by loop
-     canonicalization are removed.  */
-  cleanup_tree_cfg ();
-  calculate_dominance_info (CDI_DOMINATORS);
+  /* We need to know loop structures in order to avoid destroying them
+     in jump threading.  Note that we still can e.g. thread through loop
+     headers to an exit edge, or through loop header to the loop body, assuming
+     that we update the loop info.  */
+  loop_optimizer_init (LOOPS_HAVE_SIMPLE_LATCHES);
 
   /* We need accurate information regarding back edges in the CFG
-     for jump threading.  */
+     for jump threading; this may include back edes that are not part of
+     a single loop.  */
   mark_dfs_back_edges ();
-
+      
   /* Recursively walk the dominator tree optimizing statements.  */
   walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
 
@@ -318,19 +310,19 @@ tree_ssa_dominator_optimize (void)
   free_all_edge_infos ();
 
   /* Thread jumps, creating duplicate blocks as needed.  */
-  cfg_altered |= thread_through_all_blocks ();
+  cfg_altered |= thread_through_all_blocks (first_pass_instance);
+
+  if (cfg_altered)
+    free_dominance_info (CDI_DOMINATORS);
 
   /* Removal of statements may make some EH edges dead.  Purge
      such edges from the CFG as needed.  */
   if (!bitmap_empty_p (need_eh_cleanup))
     {
-      cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup);
+      tree_purge_all_dead_eh_edges (need_eh_cleanup);
       bitmap_zero (need_eh_cleanup);
     }
 
-  if (cfg_altered)
-    free_dominance_info (CDI_DOMINATORS);
-
   /* Finally, remove everything except invariants in SSA_NAME_VALUE.
 
      Long term we will be able to let everything in SSA_NAME_VALUE
@@ -352,6 +344,8 @@ tree_ssa_dominator_optimize (void)
   if (dump_file && (dump_flags & TDF_STATS))
     dump_dominator_optimization_stats (dump_file);
 
+  loop_optimizer_finalize ();
+
   /* Delete our main hashtable.  */
   htab_delete (avail_exprs);
 
@@ -373,8 +367,10 @@ gate_dominator (void)
   return flag_tree_dom != 0;
 }
 
-struct tree_opt_pass pass_dominator = 
+struct gimple_opt_pass pass_dominator = 
 {
+ {
+  GIMPLE_PASS,
   "dom",                               /* name */
   gate_dominator,                      /* gate */
   tree_ssa_dominator_optimize,         /* execute */
@@ -389,9 +385,8 @@ struct tree_opt_pass pass_dominator =
   TODO_dump_func
     | TODO_update_ssa
     | TODO_cleanup_cfg
-    | TODO_verify_ssa  
-    | TODO_update_smt_usage,           /* todo_flags_finish */
-  0                                    /* letter */
+    | TODO_verify_ssa                  /* todo_flags_finish */
+ }
 };
 
 
@@ -554,7 +549,7 @@ restore_vars_to_original_value (void)
 /* A trivial wrapper so that we can present the generic jump
    threading code with a simple API for simplifying statements.  */
 static tree
-simplify_stmt_for_jump_threading (tree stmt)
+simplify_stmt_for_jump_threading (tree stmt, tree within_stmt ATTRIBUTE_UNUSED)
 {
   return lookup_avail_expr (stmt, false);
 }
@@ -575,7 +570,7 @@ dom_thread_across_edge (struct dom_walk_data *walk_data, edge e)
       walk_data->global_data = dummy_cond;
     }
 
-  thread_across_edge (walk_data->global_data, e, false,
+  thread_across_edge ((tree) walk_data->global_data, e, false,
                      &const_and_copies_stack,
                      simplify_stmt_for_jump_threading);
 }
@@ -1245,26 +1240,26 @@ cprop_into_successor_phis (basic_block bb)
       indx = e->dest_idx;
       for ( ; phi; phi = PHI_CHAIN (phi))
        {
-         tree new;
+         tree new_val;
          use_operand_p orig_p;
-         tree orig;
+         tree orig_val;
 
          /* The alternative may be associated with a constant, so verify
             it is an SSA_NAME before doing anything with it.  */
          orig_p = PHI_ARG_DEF_PTR (phi, indx);
-         orig = USE_FROM_PTR (orig_p);
-         if (TREE_CODE (orig) != SSA_NAME)
+         orig_val = USE_FROM_PTR (orig_p);
+         if (TREE_CODE (orig_val) != SSA_NAME)
            continue;
 
          /* If we have *ORIG_P in our constant/copy table, then replace
             ORIG_P with its value in our constant/copy table.  */
-         new = SSA_NAME_VALUE (orig);
-         if (new
-             && new != orig
-             && (TREE_CODE (new) == SSA_NAME
-                 || is_gimple_min_invariant (new))
-             && may_propagate_copy (orig, new))
-           propagate_value (orig_p, new);
+         new_val = SSA_NAME_VALUE (orig_val);
+         if (new_val
+             && new_val != orig_val
+             && (TREE_CODE (new_val) == SSA_NAME
+                 || is_gimple_min_invariant (new_val))
+             && may_propagate_copy (orig_val, new_val))
+           propagate_value (orig_p, new_val);
        }
     }
 }
@@ -1521,8 +1516,8 @@ eliminate_redundant_computations (tree stmt)
   if (cached_lhs
       && ((TREE_CODE (cached_lhs) != SSA_NAME
           && (modify_expr_p
-              || tree_ssa_useless_type_conversion_1 (TREE_TYPE (*expr_p),
-                                                     TREE_TYPE (cached_lhs))))
+              || useless_type_conversion_p (TREE_TYPE (*expr_p),
+                                           TREE_TYPE (cached_lhs))))
          || may_propagate_copy (*expr_p, cached_lhs)))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1547,8 +1542,8 @@ eliminate_redundant_computations (tree stmt)
        retval = true;
       
       if (modify_expr_p
-         && !tree_ssa_useless_type_conversion_1 (TREE_TYPE (*expr_p),
-                                                 TREE_TYPE (cached_lhs)))
+         && !useless_type_conversion_p (TREE_TYPE (*expr_p),
+                                       TREE_TYPE (cached_lhs)))
        cached_lhs = fold_convert (TREE_TYPE (*expr_p), cached_lhs);
 
       propagate_tree_value (expr_p, cached_lhs);
@@ -1597,7 +1592,7 @@ record_equivalences_from_stmt (tree stmt, int may_optimize_p, stmt_ann_t ann)
       && !is_gimple_reg (lhs))
     {
       tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-      tree new;
+      tree new_stmt;
 
       /* FIXME: If the LHS of the assignment is a bitfield and the RHS
          is a constant, we need to adjust the constant to fit into the
@@ -1623,13 +1618,13 @@ record_equivalences_from_stmt (tree stmt, int may_optimize_p, stmt_ann_t ann)
       if (rhs)
        {
          /* Build a new statement with the RHS and LHS exchanged.  */
-         new = build_gimple_modify_stmt (rhs, lhs);
+         new_stmt = build_gimple_modify_stmt (rhs, lhs);
 
-         create_ssa_artificial_load_stmt (new, stmt);
+         create_ssa_artificial_load_stmt (new_stmt, stmt, true);
 
          /* Finally enter the statement into the available expression
             table.  */
-         lookup_avail_expr (new, true);
+         lookup_avail_expr (new_stmt, true);
        }
     }
 }
@@ -1686,7 +1681,7 @@ cprop_operand (tree stmt, use_operand_p op_p)
         propagation opportunity.  */
       if (TREE_CODE (val) != SSA_NAME)
        {
-         if (!lang_hooks.types_compatible_p (op_type, val_type))
+         if (!useless_type_conversion_p (op_type, val_type))
            {
              val = fold_convert (TREE_TYPE (op), val);
              if (!is_gimple_min_invariant (val))
@@ -2003,8 +1998,8 @@ lookup_avail_expr (tree stmt, bool insert)
 static hashval_t
 avail_expr_hash (const void *p)
 {
-  tree stmt = ((struct expr_hash_elt *)p)->stmt;
-  tree rhs = ((struct expr_hash_elt *)p)->rhs;
+  tree stmt = ((const struct expr_hash_elt *)p)->stmt;
+  tree rhs = ((const struct expr_hash_elt *)p)->rhs;
   tree vuse;
   ssa_op_iter iter;
   hashval_t val = 0;
@@ -2039,10 +2034,10 @@ real_avail_expr_hash (const void *p)
 static int
 avail_expr_eq (const void *p1, const void *p2)
 {
-  tree stmt1 = ((struct expr_hash_elt *)p1)->stmt;
-  tree rhs1 = ((struct expr_hash_elt *)p1)->rhs;
-  tree stmt2 = ((struct expr_hash_elt *)p2)->stmt;
-  tree rhs2 = ((struct expr_hash_elt *)p2)->rhs;
+  tree stmt1 = ((const struct expr_hash_elt *)p1)->stmt;
+  tree rhs1 = ((const struct expr_hash_elt *)p1)->rhs;
+  tree stmt2 = ((const struct expr_hash_elt *)p2)->stmt;
+  tree rhs2 = ((const struct expr_hash_elt *)p2)->rhs;
 
   /* If they are the same physical expression, return true.  */
   if (rhs1 == rhs2 && stmt1 == stmt2)
@@ -2054,13 +2049,12 @@ avail_expr_eq (const void *p1, const void *p2)
 
   /* In case of a collision, both RHS have to be identical and have the
      same VUSE operands.  */
-  if ((TREE_TYPE (rhs1) == TREE_TYPE (rhs2)
-       || lang_hooks.types_compatible_p (TREE_TYPE (rhs1), TREE_TYPE (rhs2)))
+  if (types_compatible_p (TREE_TYPE (rhs1), TREE_TYPE (rhs2))
       && operand_equal_p (rhs1, rhs2, OEP_PURE_SAME))
     {
       bool ret = compare_ssa_operands_equal (stmt1, stmt2, SSA_OP_VUSE);
-      gcc_assert (!ret || ((struct expr_hash_elt *)p1)->hash
-                 == ((struct expr_hash_elt *)p2)->hash);
+      gcc_assert (!ret || ((const struct expr_hash_elt *)p1)->hash
+                 == ((const struct expr_hash_elt *)p2)->hash);
       return ret;
     }
 
@@ -2337,7 +2331,7 @@ propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
 
                          te->count += e->count;
                          remove_edge (e);
-                         cfg_altered = 1;
+                         cfg_altered = true;
                        }
                      else
                        ei_next (&ei);
@@ -2486,6 +2480,9 @@ eliminate_degenerate_phis (void)
   interesting_names = BITMAP_ALLOC (NULL);
   interesting_names1 = BITMAP_ALLOC (NULL);
 
+  calculate_dominance_info (CDI_DOMINATORS);
+  cfg_altered = false;
+
   /* First phase.  Eliminate degenerate PHIs via a dominator
      walk of the CFG.
 
@@ -2494,7 +2491,6 @@ eliminate_degenerate_phis (void)
      phase in dominator order.  Presumably this is because walking
      in dominator order leaves fewer PHIs for later examination
      by the worklist phase.  */
-  calculate_dominance_info (CDI_DOMINATORS);
   eliminate_degenerate_phis_1 (ENTRY_BLOCK_PTR, interesting_names);
 
   /* Second phase.  Eliminate second order degenerate PHIs as well
@@ -2523,23 +2519,26 @@ eliminate_degenerate_phis (void)
        }
     }
 
+  if (cfg_altered)
+    free_dominance_info (CDI_DOMINATORS);
+
   /* Propagation of const and copies may make some EH edges dead.  Purge
      such edges from the CFG as needed.  */
   if (!bitmap_empty_p (need_eh_cleanup))
     {
-      cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup);
+      tree_purge_all_dead_eh_edges (need_eh_cleanup);
       BITMAP_FREE (need_eh_cleanup);
     }
 
   BITMAP_FREE (interesting_names);
   BITMAP_FREE (interesting_names1);
-  if (cfg_altered)
-    free_dominance_info (CDI_DOMINATORS);
   return 0;
 }
 
-struct tree_opt_pass pass_phi_only_cprop =
+struct gimple_opt_pass pass_phi_only_cprop =
 {
+ {
+  GIMPLE_PASS,
   "phicprop",                           /* name */
   gate_dominator,                       /* gate */
   eliminate_degenerate_phis,            /* execute */
@@ -2551,9 +2550,11 @@ struct tree_opt_pass pass_phi_only_cprop =
   0,                                    /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_cleanup_cfg | TODO_dump_func 
-    | TODO_ggc_collect | TODO_verify_ssa
-    | TODO_verify_stmts | TODO_update_smt_usage
-    | TODO_update_ssa, /* todo_flags_finish */
-  0                                     /* letter */
+  TODO_cleanup_cfg
+    | TODO_dump_func 
+    | TODO_ggc_collect
+    | TODO_verify_ssa
+    | TODO_verify_stmts
+    | TODO_update_ssa                  /* todo_flags_finish */
+ }
 };