OSDN Git Service

2007-08-04 Andrew Pinski <andrew_pinski@playstation.sony.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
index 75df4cc..b4bd069 100644 (file)
@@ -1,12 +1,12 @@
 /* Top-level control of tree optimizations.
-   Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 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,
@@ -15,9 +15,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"
@@ -101,7 +100,7 @@ struct tree_opt_pass pass_early_local_passes =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  0,                                   /* todo_flags_finish */
+  TODO_remove_functions,               /* todo_flags_finish */
   0                                    /* letter */
 };
 
@@ -208,13 +207,10 @@ struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
 static unsigned int
 execute_free_datastructures (void)
 {
-  /* ??? This isn't the right place for this.  Worse, it got computed
-     more or less at random in various passes.  */
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
 
-  /* Remove the ssa structures.  Do it here since this includes statement
-     annotations that need to be intact during disband_implicit_edges.  */
+  /* Remove the ssa structures.  */
   if (cfun->gimple_df)
     delete_tree_ssa ();
   return 0;
@@ -241,17 +237,9 @@ struct tree_opt_pass pass_free_datastructures =
 static unsigned int
 execute_free_cfg_annotations (void)
 {
-  /* Emit gotos for implicit jumps.  */
-  disband_implicit_edges ();
-
   /* And get rid of annotations we no longer need.  */
   delete_tree_cfg_annotations ();
 
-#ifdef ENABLE_CHECKING
-  /* Once the statement annotations have been removed, we can verify
-     the integrity of statements in the EH throw table.  */
-  verify_eh_throw_table_statements ();
-#endif
   return 0;
 }
 
@@ -272,31 +260,19 @@ struct tree_opt_pass pass_free_cfg_annotations =
   0                                    /* letter */
 };
 
-/* Return true if BB has at least one abnormal outgoing edge.  */
-
-static inline bool
-has_abnormal_outgoing_edge_p (basic_block bb)
-{
-  edge e;
-  edge_iterator ei;
-
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    if (e->flags & EDGE_ABNORMAL)
-      return true;
-
-  return false;
-}
-
 /* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
-   might have changed some properties, such as marked functions nothrow or
-   added calls that can potentially go to non-local labels.  Remove redundant
-   edges and basic blocks, and create new ones if necessary.  */
+   might have changed some properties, such as marked functions nothrow.
+   Remove redundant edges and basic blocks, and create new ones if necessary.
 
-static unsigned int
+   This pass can't be executed as stand alone pass from pass manager, because
+   in between inlining and this fixup the verify_flow_info would fail.  */
+
+unsigned int
 execute_fixup_cfg (void)
 {
   basic_block bb;
   block_stmt_iterator bsi;
+  int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
 
   cfun->after_inlining = true;
 
@@ -312,7 +288,11 @@ execute_fixup_cfg (void)
            if (decl && call_expr_flags (call) & (ECF_CONST | ECF_PURE)
                && TREE_SIDE_EFFECTS (call))
              {
-               update_stmt (stmt);
+               if (gimple_in_ssa_p (cfun))
+                 {
+                   todo |= TODO_update_ssa | TODO_cleanup_cfg;
+                   update_stmt (stmt);
+                 }
                TREE_SIDE_EFFECTS (call) = 0;
              }
            if (decl && TREE_NOTHROW (decl))
@@ -320,85 +300,17 @@ execute_fixup_cfg (void)
            if (!tree_could_throw_p (stmt) && lookup_stmt_eh_region (stmt))
              remove_stmt_from_eh_region (stmt);
          }
-       tree_purge_dead_eh_edges (bb);
+       if (tree_purge_dead_eh_edges (bb))
+          todo |= TODO_cleanup_cfg;
       }
 
-  if (current_function_has_nonlocal_label)
-    {
-      FOR_EACH_BB (bb)
-       {
-         for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-           {
-             tree stmt = bsi_stmt (bsi);
-             if (tree_can_make_abnormal_goto (stmt))
-               {
-                 if (stmt == bsi_stmt (bsi_last (bb)))
-                   {
-                     if (!has_abnormal_outgoing_edge_p (bb))
-                       make_abnormal_goto_edges (bb, true);
-                   }
-                 else
-                   {
-                     edge e = split_block (bb, stmt);
-                     bb = e->src;
-                     make_abnormal_goto_edges (bb, true);
-                   }
-                 break;
-               }
-
-             /* Update PHIs on nonlocal goto receivers we (possibly)
-                just created new edges into.  */
-             if (TREE_CODE (stmt) == LABEL_EXPR
-                 && gimple_in_ssa_p (cfun))
-               {
-                 tree target = LABEL_EXPR_LABEL (stmt);
-                 if (DECL_NONLOCAL (target))
-                   {
-                     tree phi;
-                     for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
-                       {
-                         gcc_assert (SSA_NAME_OCCURS_IN_ABNORMAL_PHI
-                                     (PHI_RESULT (phi)));
-                         mark_sym_for_renaming
-                           (SSA_NAME_VAR (PHI_RESULT (phi)));
-                       }
-                   }
-               }
-           }
-       }
-    }
-
-  if (gimple_in_ssa_p (cfun))
-    {
-      delete_unreachable_blocks ();
-      update_ssa (TODO_update_ssa);
-    }
-  cleanup_tree_cfg ();
-
   /* Dump a textual representation of the flowgraph.  */
   if (dump_file)
     dump_tree_cfg (dump_file, dump_flags);
 
-  return 0;
+  return todo;
 }
 
-struct tree_opt_pass pass_fixup_cfg =
-{
-  "fixupcfg",                          /* name */
-  NULL,                                        /* gate */
-  execute_fixup_cfg,                   /* execute */
-  NULL,                                        /* sub */
-  NULL,                                        /* next */
-  0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
-  PROP_cfg,                            /* properties_required */
-  0,                                   /* properties_provided */
-  0,                                   /* properties_destroyed */
-  0,                                   /* todo_flags_start */
-  0,                                   /* todo_flags_finish */
-  0                                    /* letter */
-};
-
 /* Do the actions required to initialize internal data structures used
    in tree-ssa optimization passes.  */
 
@@ -454,24 +366,6 @@ tree_lowering_passes (tree fn)
   bitmap_obstack_release (NULL);
   pop_cfun ();
 }
-
-/* Update recursively all inlined_to pointers of functions
-   inlined into NODE to INLINED_TO.  */
-static void
-update_inlined_to_pointers (struct cgraph_node *node,
-                           struct cgraph_node *inlined_to)
-{
-  struct cgraph_edge *e;
-  for (e = node->callees; e; e = e->next_callee)
-    {
-      if (e->callee->global.inlined_to)
-       {
-         e->callee->global.inlined_to = inlined_to;
-         update_inlined_to_pointers (e->callee, inlined_to);
-       }
-    }
-}
-
 \f
 /* For functions-as-trees languages, this performs all optimization and
    compilation for FNDECL.  */
@@ -491,13 +385,9 @@ tree_rest_of_compilation (tree fndecl)
   /* Initialize the default bitmap obstack.  */
   bitmap_obstack_initialize (NULL);
 
-  /* We might need the body of this function so that we can expand
-     it inline somewhere else.  */
-  if (cgraph_preserve_function_body_p (fndecl))
-    save_inline_function_body (node);
-
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
+  cfun = DECL_STRUCT_FUNCTION (fndecl);
   saved_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (fndecl);
   init_function_start (fndecl);
@@ -510,33 +400,6 @@ tree_rest_of_compilation (tree fndecl)
   
   tree_register_cfg_hooks ();
 
-  if (flag_inline_trees)
-    {
-      struct cgraph_edge *e;
-      for (e = node->callees; e; e = e->next_callee)
-       if (!e->inline_failed || warn_inline)
-         break;
-      if (e)
-       {
-         timevar_push (TV_INTEGRATION);
-         optimize_inline_calls (fndecl);
-         timevar_pop (TV_INTEGRATION);
-       }
-    }
-  /* In non-unit-at-a-time we must mark all referenced functions as needed.
-     */
-  if (!flag_unit_at_a_time)
-    {
-      struct cgraph_edge *e;
-      for (e = node->callees; e; e = e->next_callee)
-       if (e->callee->analyzed)
-          cgraph_mark_needed_node (e->callee);
-    }
-
-  /* We are not going to maintain the cgraph edges up to date.
-     Kill it so it won't confuse us.  */
-  cgraph_node_remove_callees (node);
-
   bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
   /* Perform all tree transforms and optimizations.  */
   execute_pass_list (all_passes);