OSDN Git Service

2010-01-17 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-uncprop.c
index f502a2e..96c08d3 100644 (file)
@@ -1,11 +1,11 @@
 /* Routines for discovering and unpropagating edge equivalences.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2007, 2008 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)
+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,
@@ -14,9 +14,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"
@@ -54,7 +53,7 @@ struct edge_equivalency
    in the CFG.
 
    When complete, each edge that creates an equivalency will have an
-   EDGE_EQUIVALENCY structure hanging off the edge's AUX field. 
+   EDGE_EQUIVALENCY structure hanging off the edge's AUX field.
    The caller is responsible for freeing the AUX fields.  */
 
 static void
@@ -66,50 +65,35 @@ associate_equivalences_with_edges (void)
      then it might create a useful equivalence.  */
   FOR_EACH_BB (bb)
     {
-      block_stmt_iterator bsi = bsi_last (bb);
-      tree stmt;
+      gimple_stmt_iterator gsi = gsi_last_bb (bb);
+      gimple stmt;
 
       /* If the block does not end with a COND_EXPR or SWITCH_EXPR
         then there is nothing to do.  */
-      if (bsi_end_p (bsi))
+      if (gsi_end_p (gsi))
        continue;
 
-      stmt = bsi_stmt (bsi);
+      stmt = gsi_stmt (gsi);
 
       if (!stmt)
        continue;
 
       /* A COND_EXPR may create an equivalency in a variety of different
         ways.  */
-      if (TREE_CODE (stmt) == COND_EXPR)
+      if (gimple_code (stmt) == GIMPLE_COND)
        {
-         tree cond = COND_EXPR_COND (stmt);
          edge true_edge;
          edge false_edge;
          struct edge_equivalency *equivalency;
+         enum tree_code code = gimple_cond_code (stmt);
 
          extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
 
-         /* If the conditional is a single variable 'X', record 'X = 1'
-            for the true edge and 'X = 0' on the false edge.  */
-         if (TREE_CODE (cond) == SSA_NAME
-             && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
-           {
-             equivalency = XNEW (struct edge_equivalency);
-             equivalency->rhs = constant_boolean_node (1, TREE_TYPE (cond));
-             equivalency->lhs = cond;
-             true_edge->aux = equivalency;
-
-             equivalency = XNEW (struct edge_equivalency);
-             equivalency->rhs = constant_boolean_node (0, TREE_TYPE (cond));
-             equivalency->lhs = cond;
-             false_edge->aux = equivalency;
-           }
          /* Equality tests may create one or two equivalences.  */
-         else if (TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
+         if (code == EQ_EXPR || code == NE_EXPR)
            {
-             tree op0 = TREE_OPERAND (cond, 0);
-             tree op1 = TREE_OPERAND (cond, 1);
+             tree op0 = gimple_cond_lhs (stmt);
+             tree op1 = gimple_cond_rhs (stmt);
 
              /* Special case comparing booleans against a constant as we
                 know the value of OP0 on both arms of the branch.  i.e., we
@@ -119,7 +103,7 @@ associate_equivalences_with_edges (void)
                  && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
                  && is_gimple_min_invariant (op1))
                {
-                 if (TREE_CODE (cond) == EQ_EXPR)
+                 if (code == EQ_EXPR)
                    {
                      equivalency = XNEW (struct edge_equivalency);
                      equivalency->lhs = op0;
@@ -153,11 +137,11 @@ associate_equivalences_with_edges (void)
                    }
                }
 
-             if (TREE_CODE (op0) == SSA_NAME
-                 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
-                 && (is_gimple_min_invariant (op1)
-                     || (TREE_CODE (op1) == SSA_NAME
-                         && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))))
+             else if (TREE_CODE (op0) == SSA_NAME
+                      && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
+                      && (is_gimple_min_invariant (op1)
+                          || (TREE_CODE (op1) == SSA_NAME
+                              && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))))
                {
                  /* For IEEE, -0.0 == 0.0, so we don't necessarily know
                     the sign of a variable compared against zero.  If
@@ -171,9 +155,9 @@ associate_equivalences_with_edges (void)
                  equivalency = XNEW (struct edge_equivalency);
                  equivalency->lhs = op0;
                  equivalency->rhs = op1;
-                 if (TREE_CODE (cond) == EQ_EXPR)
+                 if (code == EQ_EXPR)
                    true_edge->aux = equivalency;
-                 else 
+                 else
                    false_edge->aux = equivalency;
 
                }
@@ -185,26 +169,24 @@ associate_equivalences_with_edges (void)
       /* For a SWITCH_EXPR, a case label which represents a single
         value and which is the only case label which reaches the
         target block creates an equivalence.  */
-      if (TREE_CODE (stmt) == SWITCH_EXPR)
+      else if (gimple_code (stmt) == GIMPLE_SWITCH)
        {
-         tree cond = SWITCH_COND (stmt);
+         tree cond = gimple_switch_index (stmt);
 
          if (TREE_CODE (cond) == SSA_NAME
              && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
            {
-             tree labels = SWITCH_LABELS (stmt);
-             int i, n_labels = TREE_VEC_LENGTH (labels);
-             tree *info = XCNEWVEC (tree, n_basic_blocks);
+             int i, n_labels = gimple_switch_num_labels (stmt);
+             tree *info = XCNEWVEC (tree, last_basic_block);
 
              /* Walk over the case label vector.  Record blocks
                 which are reached by a single case label which represents
                 a single value.  */
              for (i = 0; i < n_labels; i++)
                {
-                 tree label = TREE_VEC_ELT (labels, i);
+                 tree label = gimple_switch_label (stmt, i);
                  basic_block bb = label_to_block (CASE_LABEL (label));
 
-
                  if (CASE_HIGH (label)
                      || !CASE_LOW (label)
                      || info[bb->index])
@@ -307,9 +289,9 @@ struct equiv_hash_elt
   VEC(tree,heap) *equivalences;
 };
 
-static void uncprop_initialize_block (struct dom_walk_data *, basic_block);
-static void uncprop_finalize_block (struct dom_walk_data *, basic_block);
-static void uncprop_into_successor_phis (struct dom_walk_data *, basic_block);
+static void uncprop_enter_block (struct dom_walk_data *, basic_block);
+static void uncprop_leave_block (struct dom_walk_data *, basic_block);
+static void uncprop_into_successor_phis (basic_block);
 
 /* Hashing and equality routines for the hash table.  */
 
@@ -376,7 +358,7 @@ record_equiv (tree value, tree equivalence)
      free (equiv_hash_elt);
 
   equiv_hash_elt = (struct equiv_hash_elt *) *slot;
-  
+
   VEC_safe_push (tree, heap, equiv_hash_elt->equivalences, equivalence);
 }
 
@@ -399,18 +381,12 @@ tree_ssa_uncprop (void)
   calculate_dominance_info (CDI_DOMINATORS);
 
   /* Setup callbacks for the generic dominator tree walker.  */
-  walk_data.walk_stmts_backward = false;
   walk_data.dom_direction = CDI_DOMINATORS;
   walk_data.initialize_block_local_data = NULL;
-  walk_data.before_dom_children_before_stmts = uncprop_initialize_block;
-  walk_data.before_dom_children_walk_stmts = NULL;
-  walk_data.before_dom_children_after_stmts = uncprop_into_successor_phis;
-  walk_data.after_dom_children_before_stmts = NULL;
-  walk_data.after_dom_children_walk_stmts = NULL;
-  walk_data.after_dom_children_after_stmts = uncprop_finalize_block;
+  walk_data.before_dom_children = uncprop_enter_block;
+  walk_data.after_dom_children = uncprop_leave_block;
   walk_data.global_data = NULL;
   walk_data.block_local_data_size = 0;
-  walk_data.interesting_blocks = NULL;
 
   /* Now initialize the dominator walker.  */
   init_walk_dominator_tree (&walk_data);
@@ -450,8 +426,8 @@ tree_ssa_uncprop (void)
    the dominator tree.  */
 
 static void
-uncprop_finalize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
-                       basic_block bb ATTRIBUTE_UNUSED)
+uncprop_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
+                    basic_block bb ATTRIBUTE_UNUSED)
 {
   /* Pop the topmost value off the equiv stack.  */
   tree value = VEC_pop (tree, equiv_stack);
@@ -465,8 +441,7 @@ uncprop_finalize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
 /* Unpropagate values from PHI nodes in successor blocks of BB.  */
 
 static void
-uncprop_into_successor_phis (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
-                            basic_block bb)
+uncprop_into_successor_phis (basic_block bb)
 {
   edge e;
   edge_iterator ei;
@@ -476,11 +451,12 @@ uncprop_into_successor_phis (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
      destination of the edge.  Then remove the temporary equivalence.  */
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
-      tree phi = phi_nodes (e->dest);
+      gimple_seq phis = phi_nodes (e->dest);
+      gimple_stmt_iterator gsi;
 
       /* If there are no PHI nodes in this destination, then there is
         no sense in recording any equivalences.  */
-      if (!phi)
+      if (gimple_seq_empty_p (phis))
        continue;
 
       /* Record any equivalency associated with E.  */
@@ -491,9 +467,9 @@ uncprop_into_successor_phis (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
        }
 
       /* Walk over the PHI nodes, unpropagating values.  */
-      for ( ; phi; phi = PHI_CHAIN (phi))
+      for (gsi = gsi_start (phis) ; !gsi_end_p (gsi); gsi_next (&gsi))
        {
-         /* Sigh.  We'll have more efficient access to this one day.  */
+         gimple phi = gsi_stmt (gsi);
          tree arg = PHI_ARG_DEF (phi, e->dest_idx);
          struct equiv_hash_elt equiv_hash_elt;
          void **slot;
@@ -572,8 +548,8 @@ single_incoming_edge_ignoring_loop_edges (basic_block bb)
 }
 
 static void
-uncprop_initialize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
-                         basic_block bb)
+uncprop_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
+                    basic_block bb)
 {
   basic_block parent;
   edge e;
@@ -599,6 +575,8 @@ uncprop_initialize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
 
   if (!recorded)
     VEC_safe_push (tree, heap, equiv_stack, NULL_TREE);
+
+  uncprop_into_successor_phis (bb);
 }
 
 static bool
@@ -607,8 +585,10 @@ gate_uncprop (void)
   return flag_tree_dom != 0;
 }
 
-struct tree_opt_pass pass_uncprop = 
+struct gimple_opt_pass pass_uncprop =
 {
+ {
+  GIMPLE_PASS,
   "uncprop",                           /* name */
   gate_uncprop,                                /* gate */
   tree_ssa_uncprop,                    /* execute */
@@ -620,6 +600,7 @@ struct tree_opt_pass pass_uncprop =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa,    /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func | TODO_verify_ssa     /* todo_flags_finish */
+ }
 };
+