OSDN Git Service

Fix numerous IA-64 C++ failures, IA-64 bootstrap trouble.
[pf3gnuchains/gcc-fork.git] / gcc / tree-outof-ssa.c
index a5fc993..ecbee58 100644 (file)
@@ -1,5 +1,5 @@
 /* Convert a program in SSA form into Normal form.
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
    Contributed by Andrew Macleod <amacleod@redhat.com>
 
 This file is part of GCC.
@@ -51,9 +51,7 @@ Boston, MA 02111-1307, USA.  */
 
 #define SSANORM_PERFORM_TER            0x1
 #define SSANORM_COMBINE_TEMPS          0x2
-#define SSANORM_REMOVE_ALL_PHIS                0x4
-#define SSANORM_COALESCE_PARTITIONS    0x8
-#define SSANORM_USE_COALESCE_LIST      0x10
+#define SSANORM_COALESCE_PARTITIONS    0x4
 
 /* Used to hold all the components required to do SSA PHI elimination.
    The node and pred/succ list is a simple linear list of nodes and
@@ -157,11 +155,18 @@ create_temp (tree t)
     name = "temp";
   tmp = create_tmp_var (type, name);
 
-  if (DECL_DEBUG_ALIAS_OF (t))
-    DECL_DEBUG_ALIAS_OF (tmp) = DECL_DEBUG_ALIAS_OF (t);  
+  if (DECL_DEBUG_EXPR (t) && DECL_DEBUG_EXPR_IS_FROM (t))
+    {
+      DECL_DEBUG_EXPR (tmp) = DECL_DEBUG_EXPR (t);  
+      DECL_DEBUG_EXPR_IS_FROM (tmp) = 1;
+    }
   else if (!DECL_IGNORED_P (t))
-    DECL_DEBUG_ALIAS_OF (tmp) = t;
+    {
+      DECL_DEBUG_EXPR (tmp) = t;
+      DECL_DEBUG_EXPR_IS_FROM (tmp) = 1;
+    }
   DECL_ARTIFICIAL (tmp) = DECL_ARTIFICIAL (t);
+  DECL_IGNORED_P (tmp) = DECL_IGNORED_P (t);
   add_referenced_tmp_var (tmp);
 
   /* add_referenced_tmp_var will create the annotation and set up some
@@ -483,7 +488,6 @@ elim_create (elim_graph g, int T)
 static void
 eliminate_phi (edge e, elim_graph g)
 {
-  int num_nodes = 0;
   int x;
   basic_block B = e->dest;
 
@@ -494,7 +498,6 @@ eliminate_phi (edge e, elim_graph g)
   if (e->flags & EDGE_ABNORMAL)
     return;
 
-  num_nodes = num_var_partitions (g->map);
   g->e = e;
 
   eliminate_build (g, B);
@@ -690,10 +693,6 @@ coalesce_ssa_name (var_map map, int flags)
   if (num_var_partitions (map) <= 1)
     return NULL;
 
-  /* If no preference given, use cheap coalescing of all partitions.  */
-  if ((flags & (SSANORM_COALESCE_PARTITIONS | SSANORM_USE_COALESCE_LIST)) == 0)
-    flags |= SSANORM_COALESCE_PARTITIONS;
-  
   liveinfo = calculate_live_on_entry (map);
   calculate_live_on_exit (liveinfo);
   rv = root_var_init (map);
@@ -701,51 +700,48 @@ coalesce_ssa_name (var_map map, int flags)
   /* Remove single element variable from the list.  */
   root_var_compact (rv);
 
-  if (flags & SSANORM_USE_COALESCE_LIST)
+  cl = create_coalesce_list (map);
+
+  /* Add all potential copies via PHI arguments to the list.  */
+  FOR_EACH_BB (bb)
     {
-      cl = create_coalesce_list (map);
-      
-      /* Add all potential copies via PHI arguments to the list.  */
-      FOR_EACH_BB (bb)
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
        {
-         for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+         tree res = PHI_RESULT (phi);
+         int p = var_to_partition (map, res);
+         if (p == NO_PARTITION)
+           continue;
+         for (x = 0; x < (unsigned)PHI_NUM_ARGS (phi); x++)
            {
-             tree res = PHI_RESULT (phi);
-             int p = var_to_partition (map, res);
-             if (p == NO_PARTITION)
+             tree arg = PHI_ARG_DEF (phi, x);
+             int p2;
+
+             if (TREE_CODE (arg) != SSA_NAME)
                continue;
-             for (x = 0; x < (unsigned)PHI_NUM_ARGS (phi); x++)
-               {
-                 tree arg = PHI_ARG_DEF (phi, x);
-                 int p2;
-
-                 if (TREE_CODE (arg) != SSA_NAME)
-                   continue;
-                 if (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg))
-                   continue;
-                 p2 = var_to_partition (map, PHI_ARG_DEF (phi, x));
-                 if (p2 != NO_PARTITION)
-                   add_coalesce (cl, p, p2, 1);
-               }
+             if (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg))
+               continue;
+             p2 = var_to_partition (map, PHI_ARG_DEF (phi, x));
+             if (p2 != NO_PARTITION)
+               add_coalesce (cl, p, p2, 1);
            }
        }
+    }
 
-      /* Coalesce all the result decls together.  */
-      var = NULL_TREE;
-      i = 0;
-      for (x = 0; x < num_var_partitions (map); x++)
+  /* Coalesce all the result decls together.  */
+  var = NULL_TREE;
+  i = 0;
+  for (x = 0; x < num_var_partitions (map); x++)
+    {
+      tree p = partition_to_var (map, x);
+      if (TREE_CODE (SSA_NAME_VAR(p)) == RESULT_DECL)
        {
-         tree p = partition_to_var (map, x);
-         if (TREE_CODE (SSA_NAME_VAR(p)) == RESULT_DECL)
+         if (var == NULL_TREE)
            {
-             if (var == NULL_TREE)
-               {
-                 var = p;
-                 i = x;
-               }
-             else
-               add_coalesce (cl, i, x, 1);
+             var = p;
+             i = x;
            }
+         else
+           add_coalesce (cl, i, x, 1);
        }
     }
 
@@ -826,16 +822,14 @@ coalesce_ssa_name (var_map map, int flags)
     dump_var_map (dump_file, map);
 
   /* Coalesce partitions.  */
-  if (flags & SSANORM_USE_COALESCE_LIST)
-    coalesce_tpa_members (rv, graph, map, cl, 
-                         ((dump_flags & TDF_DETAILS) ? dump_file 
-                                                          : NULL));
+  coalesce_tpa_members (rv, graph, map, cl,
+                       ((dump_flags & TDF_DETAILS) ? dump_file
+                        : NULL));
 
-  
   if (flags & SSANORM_COALESCE_PARTITIONS)
-    coalesce_tpa_members (rv, graph, map, NULL, 
-                         ((dump_flags & TDF_DETAILS) ? dump_file 
-                                                          : NULL));
+    coalesce_tpa_members (rv, graph, map, NULL,
+                         ((dump_flags & TDF_DETAILS) ? dump_file
+                          : NULL));
   if (cl)
     delete_coalesce_list (cl);
   root_var_delete (rv);
@@ -1034,7 +1028,7 @@ eliminate_virtual_phis (void)
                    }
                }
 #endif
-             remove_phi_node (phi, NULL_TREE, bb);
+             remove_phi_node (phi, NULL_TREE);
            }
        }
     }
@@ -1253,8 +1247,8 @@ new_temp_expr_table (var_map map)
   t->partition_dep_list = xcalloc (num_var_partitions (map) + 1, 
                                   sizeof (value_expr_p));
 
-  t->replaceable = BITMAP_XMALLOC ();
-  t->partition_in_use = BITMAP_XMALLOC ();
+  t->replaceable = BITMAP_ALLOC (NULL);
+  t->partition_in_use = BITMAP_ALLOC (NULL);
 
   t->saw_replaceable = false;
   t->virtual_partition = num_var_partitions (map);
@@ -1286,8 +1280,8 @@ free_temp_expr_table (temp_expr_table_p t)
       free (p);
     }
 
-  BITMAP_XFREE (t->partition_in_use);
-  BITMAP_XFREE (t->replaceable);
+  BITMAP_FREE (t->partition_in_use);
+  BITMAP_FREE (t->replaceable);
 
   free (t->partition_dep_list);
   if (t->saw_replaceable)
@@ -1459,6 +1453,7 @@ check_replaceable (temp_expr_table_p tab, tree stmt)
   int num_use_ops, version;
   var_map map = tab->map;
   ssa_op_iter iter;
+  tree call_expr;
 
   if (TREE_CODE (stmt) != MODIFY_EXPR)
     return false;
@@ -1485,6 +1480,15 @@ check_replaceable (temp_expr_table_p tab, tree stmt)
   if (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (stmt, 1))))
     return false;
 
+  /* Calls to functions with side-effects cannot be replaced.  */
+  if ((call_expr = get_call_expr_in (stmt)) != NULL_TREE)
+    {
+      int call_flags = call_expr_flags (call_expr);
+      if (TREE_SIDE_EFFECTS (call_expr)
+         && !(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN)))
+       return false;
+    }
+
   uses = USE_OPS (ann);
   num_use_ops = NUM_USES (uses);
   vuseops = VUSE_OPS (ann);
@@ -1642,8 +1646,23 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
        {
          if (tab->version_info[SSA_NAME_VERSION (def)])
            {
-             /* Mark expression as replaceable unless stmt is volatile.  */
-             if (!ann->has_volatile_ops)
+             bool same_root_var = false;
+             tree def2;
+             ssa_op_iter iter2;
+
+             /* See if the root variables are the same.  If they are, we
+                do not want to do the replacement to avoid problems with
+                code size, see PR tree-optimization/17549.  */
+             FOR_EACH_SSA_TREE_OPERAND (def2, stmt, iter2, SSA_OP_DEF)
+               if (SSA_NAME_VAR (def) == SSA_NAME_VAR (def2))
+                 {
+                   same_root_var = true;
+                   break;
+                 }
+
+             /* Mark expression as replaceable unless stmt is volatile
+                or DEF sets the same root variable as STMT.  */
+             if (!ann->has_volatile_ops && !same_root_var)
                mark_replaceable (tab, def);
              else
                finish_expr (tab, SSA_NAME_VERSION (def), false);
@@ -1909,8 +1928,6 @@ rewrite_trees (var_map map, tree *values)
                      && (DEF_FROM_PTR (def_p) == USE_OP (uses, 0)))
                    remove = 1;
                }
-             if (changed & !remove)
-               modify_stmt (stmt);
            }
 
          /* Remove any stmts marked for removal.  */
@@ -2004,10 +2021,9 @@ identical_stmt_lists_p (edge e1, edge e2)
 
 /* Look at all the incoming edges to block BB, and decide where the best place
    to insert the stmts on each edge are, and perform those insertions.   Output
-   any debug information to DEBUG_FILE.  Return true if anything other than a 
-   standard edge insertion is done.  */
+   any debug information to DEBUG_FILE.  */
 
-static bool 
+static void
 analyze_edges_for_bb (basic_block bb, FILE *debug_file)
 {
   edge e;
@@ -2038,7 +2054,7 @@ analyze_edges_for_bb (basic_block bb, FILE *debug_file)
       FOR_EACH_EDGE (e, ei, bb->preds)
        if (PENDING_STMT (e))
          bsi_commit_one_edge_insert (e, NULL);
-      return false;
+      return;
     }
   /* Find out how many edges there are with interesting pending stmts on them.  
      Commit the stmts on edges we are not interested in.  */
@@ -2075,7 +2091,7 @@ analyze_edges_for_bb (basic_block bb, FILE *debug_file)
     {
       if (single_edge)
         bsi_commit_one_edge_insert (single_edge, NULL);
-      return false;
+      return;
     }
 
   /* Ensure that we have empty worklists.  */
@@ -2083,7 +2099,7 @@ analyze_edges_for_bb (basic_block bb, FILE *debug_file)
     {
       VARRAY_EDGE_INIT (edge_leader, 25, "edge_leader");
       VARRAY_TREE_INIT (stmt_list, 25, "stmt_list");
-      leader_has_match = BITMAP_XMALLOC ();
+      leader_has_match = BITMAP_ALLOC (NULL);
     }
   else
     {
@@ -2137,7 +2153,7 @@ analyze_edges_for_bb (basic_block bb, FILE *debug_file)
       VARRAY_POP_ALL (edge_leader);
       VARRAY_POP_ALL (stmt_list);
       bitmap_clear (leader_has_match);
-      return false;
+      return;
     }
 
 
@@ -2202,8 +2218,6 @@ analyze_edges_for_bb (basic_block bb, FILE *debug_file)
   VARRAY_POP_ALL (edge_leader);
   VARRAY_POP_ALL (stmt_list);
   bitmap_clear (leader_has_match);
-
-  return true;
 }
 
 
@@ -2217,25 +2231,25 @@ static void
 perform_edge_inserts (FILE *dump_file)
 {
   basic_block bb;
-  bool changed = false;
 
   if (dump_file)
     fprintf(dump_file, "Analyzing Edge Insertions.\n");
 
+  /* analyze_edges_for_bb calls make_forwarder_block, which tries to
+     incrementally update the dominator information.  Since we don't
+     need dominator information after this pass, go ahead and free the
+     dominator information.  */
+  free_dominance_info (CDI_DOMINATORS);
+  free_dominance_info (CDI_POST_DOMINATORS);
+
   FOR_EACH_BB (bb)
-    changed |= analyze_edges_for_bb (bb, dump_file);
+    analyze_edges_for_bb (bb, dump_file);
 
-  changed |= analyze_edges_for_bb (EXIT_BLOCK_PTR, dump_file);
+  analyze_edges_for_bb (EXIT_BLOCK_PTR, dump_file);
 
   /* Clear out any tables which were created.  */
   edge_leader = NULL;
-  BITMAP_XFREE (leader_has_match);
-
-  if (changed)
-    {
-      free_dominance_info (CDI_DOMINATORS);
-      free_dominance_info (CDI_POST_DOMINATORS);
-    }
+  BITMAP_FREE (leader_has_match);
 
 #ifdef ENABLE_CHECKING
   {
@@ -2350,18 +2364,107 @@ remove_ssa_form (FILE *dump, var_map map, int flags)
       for (phi = phi_nodes (bb); phi; phi = next)
        {
          next = PHI_CHAIN (phi);
-         if ((flags & SSANORM_REMOVE_ALL_PHIS) 
-             || var_to_partition (map, PHI_RESULT (phi)) != NO_PARTITION)
-           remove_phi_node (phi, NULL_TREE, bb);
+         remove_phi_node (phi, NULL_TREE);
        }
     }
 
+  /* we no longer maintain the SSA operand cache at this point.  */
+  fini_ssa_operands ();
+
   /* If any copies were inserted on edges, analyze and insert them now.  */
   perform_edge_inserts (dump_file);
 
   dump_file = save;
 }
 
+/* Search every PHI node for arguments associated with backedges which
+   we can trivially determine will need a copy (the argument is either
+   not an SSA_NAME or the argument has a different underlying variable
+   than the PHI result).
+
+   Insert a copy from the PHI argument to a new destination at the
+   end of the block with the backedge to the top of the loop.  Update
+   the PHI argument to reference this new destination.  */
+
+static void
+insert_backedge_copies (void)
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+    {
+      tree phi;
+
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+       {
+         tree result = PHI_RESULT (phi);
+         tree result_var;
+         int i;
+
+         if (!is_gimple_reg (result))
+           continue;
+
+         result_var = SSA_NAME_VAR (result);
+         for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+           {
+             tree arg = PHI_ARG_DEF (phi, i);
+             edge e = PHI_ARG_EDGE (phi, i);
+
+             /* If the argument is not an SSA_NAME, then we will
+                need a constant initialization.  If the argument is
+                an SSA_NAME with a different underlying variable and
+                we are not combining temporaries, then we will
+                need a copy statement.  */
+             if ((e->flags & EDGE_DFS_BACK)
+                 && (TREE_CODE (arg) != SSA_NAME
+                     || (!flag_tree_combine_temps
+                         && SSA_NAME_VAR (arg) != result_var)))
+               {
+                 tree stmt, name, last = NULL;
+                 block_stmt_iterator bsi;
+
+                 bsi = bsi_last (PHI_ARG_EDGE (phi, i)->src);
+                 if (!bsi_end_p (bsi))
+                   last = bsi_stmt (bsi);
+
+                 /* In theory the only way we ought to get back to the
+                    start of a loop should be with a COND_EXPR or GOTO_EXPR.
+                    However, better safe than sorry. 
+
+                    If the block ends with a control statement or
+                    something that might throw, then we have to
+                    insert this assignment before the last
+                    statement.  Else insert it after the last statement.  */
+                 if (last && stmt_ends_bb_p (last))
+                   {
+                     /* If the last statement in the block is the definition
+                        site of the PHI argument, then we can't insert
+                        anything after it.  */
+                     if (TREE_CODE (arg) == SSA_NAME
+                         && SSA_NAME_DEF_STMT (arg) == last)
+                       continue;
+                   }
+
+                 /* Create a new instance of the underlying
+                    variable of the PHI result.  */
+                 stmt = build (MODIFY_EXPR, TREE_TYPE (result_var),
+                               NULL, PHI_ARG_DEF (phi, i));
+                 name = make_ssa_name (result_var, stmt);
+                 TREE_OPERAND (stmt, 0) = name;
+
+                 /* Insert the new statement into the block and update
+                    the PHI node.  */
+                 if (last && stmt_ends_bb_p (last))
+                   bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+                 else
+                   bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+                 SET_PHI_ARG_DEF (phi, i, name);
+               }
+           }
+       }
+    }
+}
+
 /* Take the current function out of SSA form, as described in
    R. Morgan, ``Building an Optimizing Compiler'',
    Butterworth-Heinemann, Boston, MA, 1998. pp 176-186.  */
@@ -2371,7 +2474,15 @@ rewrite_out_of_ssa (void)
 {
   var_map map;
   int var_flags = 0;
-  int ssa_flags = (SSANORM_REMOVE_ALL_PHIS | SSANORM_USE_COALESCE_LIST);
+  int ssa_flags = 0;
+
+  /* If elimination of a PHI requires inserting a copy on a backedge,
+     then we will have to split the backedge which has numerous
+     undesirable performance effects.
+
+     A significant number of such cases can be handled here by inserting
+     copies into the loop itself.  */
+  insert_backedge_copies ();
 
   if (!flag_tree_live_range_split)
     ssa_flags |= SSANORM_COALESCE_PARTITIONS;