OSDN Git Service

PR rtl-optimization/27477
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-sink.c
index d1ac56a..4db67c5 100644 (file)
@@ -16,14 +16,13 @@ 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, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "errors.h"
 #include "ggc.h"
 #include "tree.h"
 #include "basic-block.h"
@@ -73,13 +72,13 @@ Boston, MA 02111-1307, USA.  */
 
 static struct
 {  
-  /* The number of statements sunk down the flowgraph by code sinking. */
+  /* The number of statements sunk down the flowgraph by code sinking.  */
   int sunk;
   
 } sink_stats;
 
 
-/* Given a PHI, and one of it's arguments (DEF), find the edge for
+/* Given a PHI, and one of its arguments (DEF), find the edge for
    that argument and return it.  If the argument occurs twice in the PHI node,
    we return NULL.  */
 
@@ -106,24 +105,29 @@ find_bb_for_arg (tree phi, tree def)
    and all the other uses are in phis in the same basic block, but this
    requires some expensive checking later (you have to make sure no def/vdef
    in the statement occurs for multiple edges in the various phi nodes it's
-   used in, so that you only have one place you can sink it to. */
+   used in, so that you only have one place you can sink it to.  */
 
 static bool
-all_immediate_uses_same_place (dataflow_t imm)
+all_immediate_uses_same_place (tree stmt)
 {
-  int i;
-  tree firstuse;
-
-  if (imm == NULL || num_immediate_uses (imm) < 2)
-    return true;
-  firstuse = immediate_use (imm, 0);
+  tree firstuse = NULL_TREE;
+  ssa_op_iter op_iter;
+  imm_use_iterator imm_iter;
+  use_operand_p use_p;
+  tree var;
 
-  for (i = 1; i < num_immediate_uses (imm); i++)
+  FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_ALL_DEFS)
     {
-      tree immuse = immediate_use (imm, i);
-      if (immuse != firstuse)
-       return false;
+      FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
+        {
+         if (firstuse == NULL_TREE)
+           firstuse = USE_STMT (use_p);
+         else
+           if (firstuse != USE_STMT (use_p))
+             return false;
+       }
     }
+
   return true;
 }
 
@@ -133,16 +137,10 @@ all_immediate_uses_same_place (dataflow_t imm)
 bool
 is_hidden_global_store (tree stmt)
 {
-  stmt_ann_t ann = stmt_ann (stmt);
-  v_may_def_optype v_may_defs;
-  v_must_def_optype v_must_defs;
-    
   /* Check virtual definitions.  If we get here, the only virtual
      definitions we should see are those generated by assignment
      statements.  */
-  v_may_defs = V_MAY_DEF_OPS (ann);
-  v_must_defs = V_MUST_DEF_OPS (ann);
-  if (NUM_V_MAY_DEFS (v_may_defs) > 0 || NUM_V_MUST_DEFS (v_must_defs) > 0)
+  if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
     {
       tree lhs;
 
@@ -170,7 +168,7 @@ is_hidden_global_store (tree stmt)
         variable.
 
         Therefore, we check the base address of the LHS.  If the
-        address is a pointer, we check if its name tag or type tag is
+        address is a pointer, we check if its name tag or symbol tag is
         a global variable.  Otherwise, we check if the base variable
         is a global.  */
       lhs = TREE_OPERAND (stmt, 0);
@@ -196,12 +194,12 @@ is_hidden_global_store (tree stmt)
          tree ptr = TREE_OPERAND (lhs, 0);
          struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
          tree nmt = (pi) ? pi->name_mem_tag : NULL_TREE;
-         tree tmt = var_ann (SSA_NAME_VAR (ptr))->type_mem_tag;
+         tree smt = var_ann (SSA_NAME_VAR (ptr))->symbol_mem_tag;
 
-         /* If either the name tag or the type tag for PTR is a
+         /* If either the name tag or the symbol tag for PTR is a
             global variable, then the store is necessary.  */
          if ((nmt && is_global_var (nmt))
-             || (tmt && is_global_var (tmt)))
+             || (smt && is_global_var (smt)))
            {
              return true;
            }
@@ -215,36 +213,35 @@ is_hidden_global_store (tree stmt)
 /* Find the nearest common dominator of all of the immediate uses in IMM.  */
 
 static basic_block
-nearest_common_dominator_of_uses (dataflow_t imm)
+nearest_common_dominator_of_uses (tree stmt)
 {  
   bitmap blocks = BITMAP_ALLOC (NULL);
   basic_block commondom;
-  int i;
   unsigned int j;
   bitmap_iterator bi;
+  ssa_op_iter op_iter;
+  imm_use_iterator imm_iter;
+  use_operand_p use_p;
+  tree var;
+
   bitmap_clear (blocks);
-  for (i = 0; i < num_immediate_uses (imm); i++)
+  FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_ALL_DEFS)
     {
-      tree usestmt = immediate_use (imm, i);
-      basic_block useblock;
-      if (TREE_CODE (usestmt) == PHI_NODE)
-       {
-         int j;
-         for (j = 0; j < PHI_NUM_ARGS (usestmt); j++)
+      FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
+        {
+         tree usestmt = USE_STMT (use_p);
+         basic_block useblock;
+
+         if (TREE_CODE (usestmt) == PHI_NODE)
            {
-             useblock = PHI_ARG_EDGE (usestmt, j)->src;
-             /* Short circuit. Nothing dominates the entry block.  */
-             if (useblock == ENTRY_BLOCK_PTR)
-               {
-                 BITMAP_FREE (blocks);
-                 return NULL;
-               }
-             bitmap_set_bit (blocks, useblock->index);
+             int idx = PHI_ARG_INDEX_FROM_USE (use_p);
+
+             useblock = PHI_ARG_EDGE (usestmt, idx)->src;
+           }
+         else
+           {
+             useblock = bb_for_stmt (usestmt);
            }
-       }
-      else
-       {
-         useblock = bb_for_stmt (usestmt);
 
          /* Short circuit. Nothing dominates the entry block.  */
          if (useblock == ENTRY_BLOCK_PTR)
@@ -266,21 +263,33 @@ nearest_common_dominator_of_uses (dataflow_t imm)
 /* Given a statement (STMT) and the basic block it is currently in (FROMBB), 
    determine the location to sink the statement to, if any.
    Return the basic block to sink it to, or NULL if we should not sink
-   it. */
+   it.  */
 
 static tree
 statement_sink_location (tree stmt, basic_block frombb)
 {
-  dataflow_t imm = get_immediate_uses (stmt);
   tree use, def;
+  use_operand_p one_use = NULL_USE_OPERAND_P;
   basic_block sinkbb;
   use_operand_p use_p;
   def_operand_p def_p;
   ssa_op_iter iter;
   stmt_ann_t ann;
   tree rhs;
+  imm_use_iterator imm_iter;
+
+  FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
+    {
+      FOR_EACH_IMM_USE_FAST (one_use, imm_iter, def)
+       {
+         break;
+       }
+      if (one_use != NULL_USE_OPERAND_P)
+        break;
+    }
 
-  if (imm == NULL)
+  /* Return if there are no immediate uses of this stmt.  */
+  if (one_use == NULL_USE_OPERAND_P)
     return NULL;
 
   if (TREE_CODE (stmt) != MODIFY_EXPR)
@@ -308,14 +317,13 @@ statement_sink_location (tree stmt, basic_block frombb)
 
   */
   ann = stmt_ann (stmt);
-  if (NUM_VUSES (STMT_VUSE_OPS (stmt)) != 0
-      || stmt_ends_bb_p (stmt)
+  if (stmt_ends_bb_p (stmt)
       || TREE_SIDE_EFFECTS (rhs)
       || TREE_CODE (rhs) == EXC_PTR_EXPR
       || TREE_CODE (rhs) == FILTER_EXPR
       || is_hidden_global_store (stmt)
       || ann->has_volatile_ops
-      || num_immediate_uses (imm) == 0)
+      || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
     return NULL;
   
   FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
@@ -337,9 +345,9 @@ statement_sink_location (tree stmt, basic_block frombb)
      common dominator of all the immediate uses.  For PHI nodes, we have to
      find the nearest common dominator of all of the predecessor blocks, since
      that is where insertion would have to take place.  */
-  if (!all_immediate_uses_same_place (imm))
+  if (!all_immediate_uses_same_place (stmt))
     {
-      basic_block commondom = nearest_common_dominator_of_uses (imm);
+      basic_block commondom = nearest_common_dominator_of_uses (stmt);
      
       if (commondom == frombb)
        return NULL;
@@ -371,7 +379,7 @@ statement_sink_location (tree stmt, basic_block frombb)
       return first_stmt (commondom);
     }
 
-  use = immediate_use (imm, 0);
+  use = USE_STMT (one_use);
   if (TREE_CODE (use) != PHI_NODE)
     {
       sinkbb = bb_for_stmt (use);
@@ -382,18 +390,10 @@ statement_sink_location (tree stmt, basic_block frombb)
     }
 
   /* Note that at this point, all uses must be in the same statement, so it
-     doesn't matter which def op we choose.  */
-  if (STMT_DEF_OPS (stmt) == NULL)
-    {
-      if (STMT_V_MAY_DEF_OPS (stmt) != NULL)
-       def = V_MAY_DEF_RESULT (STMT_V_MAY_DEF_OPS (stmt), 0);
-      else if (STMT_V_MUST_DEF_OPS (stmt) != NULL)
-       def = V_MUST_DEF_RESULT (STMT_V_MUST_DEF_OPS (stmt), 0);
-      else
-       gcc_unreachable ();
-    }
-  else
-    def = DEF_OP (STMT_DEF_OPS (stmt), 0);
+     doesn't matter which def op we choose, pick the first one.  */
+  FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
+    break;
+
   
   sinkbb = find_bb_for_arg (use, def);
   if (!sinkbb)
@@ -441,7 +441,6 @@ sink_code_in_bb (basic_block bb)
       tree stmt = bsi_stmt (bsi);      
       block_stmt_iterator tobsi;
       tree sinkstmt;
-      get_stmt_operands (stmt);
       
       sinkstmt = statement_sink_location (stmt, bb);
       if (!sinkstmt)
@@ -523,26 +522,26 @@ sink_code_in_bb (basic_block bb)
 static void
 execute_sink_code (void)
 {
-  struct loops *loops = loop_optimizer_init (dump_file);
+  struct loops *loops = loop_optimizer_init (LOOPS_NORMAL);
+
   connect_infinite_loops_to_exit ();
   memset (&sink_stats, 0, sizeof (sink_stats));
   calculate_dominance_info (CDI_DOMINATORS | CDI_POST_DOMINATORS);
-  compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, NULL);
   sink_code_in_bb (EXIT_BLOCK_PTR); 
   if (dump_file && (dump_flags & TDF_STATS))
     fprintf (dump_file, "Sunk statements:%d\n", sink_stats.sunk);
   free_dominance_info (CDI_POST_DOMINATORS);
   remove_fake_exit_edges ();
-  free_df ();
-  loop_optimizer_finalize (loops, dump_file);
+  loop_optimizer_finalize (loops);
 }
 
 /* Gate and execute functions for PRE.  */
 
-static void
+static unsigned int
 do_sink (void)
 {
   execute_sink_code ();
+  return 0;
 }
 
 static bool
@@ -565,6 +564,9 @@ struct tree_opt_pass pass_sink_code =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_rename_vars | TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */
+  TODO_update_ssa 
+    | TODO_dump_func
+    | TODO_ggc_collect
+    | TODO_verify_ssa,                 /* todo_flags_finish */
   0                                    /* letter */
 };