OSDN Git Service

2010-04-20 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
index 35feaa1..76918f1 100644 (file)
@@ -1,5 +1,6 @@
 /* Top-level control of tree optimizations.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -23,12 +24,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
-#include "expr.h"
 #include "diagnostic.h"
 #include "basic-block.h"
 #include "flags.h"
@@ -48,7 +46,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "graph.h"
 #include "cfgloop.h"
 #include "except.h"
-
+#include "plugin.h"
+#include "regset.h"    /* FIXME: For reg_obstack.  */
 
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
 
@@ -56,7 +55,7 @@ static bool
 gate_all_optimizations (void)
 {
   return (optimize >= 1
-         /* Don't bother doing anything if the program has errors. 
+         /* Don't bother doing anything if the program has errors.
             We have to pass down the queue if we already went into SSA */
          && (!(errorcount || sorrycount) || gimple_in_ssa_p (cfun)));
 }
@@ -65,13 +64,13 @@ struct gimple_opt_pass pass_all_optimizations =
 {
  {
   GIMPLE_PASS,
-  NULL,                                        /* name */
+  "*all_optimizations",                        /* name */
   gate_all_optimizations,              /* gate */
   NULL,                                        /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   0,                                   /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -86,7 +85,7 @@ static bool
 gate_all_early_local_passes (void)
 {
          /* Don't bother doing anything if the program has errors.  */
-  return (!errorcount && !sorrycount);
+  return (!errorcount && !sorrycount && !in_lto_p);
 }
 
 struct simple_ipa_opt_pass pass_early_local_passes =
@@ -99,7 +98,7 @@ struct simple_ipa_opt_pass pass_early_local_passes =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   0,                                   /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -115,7 +114,7 @@ execute_early_local_optimizations (void)
      cgraph state so newly inserted functions are also early optimized.
      However we execute early local optimizations for lately inserted
      functions, in that case don't reset cgraph state back to IPA_SSA.  */
-  if (flag_unit_at_a_time && cgraph_state < CGRAPH_STATE_IPA_SSA)
+  if (cgraph_state < CGRAPH_STATE_IPA_SSA)
     cgraph_state = CGRAPH_STATE_IPA_SSA;
   return 0;
 }
@@ -140,7 +139,7 @@ struct gimple_opt_pass pass_all_early_optimizations =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   0,                                   /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -171,7 +170,7 @@ struct gimple_opt_pass pass_cleanup_cfg =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -200,84 +199,37 @@ struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
 {
  {
   GIMPLE_PASS,
-  "final_cleanup",                     /* name */
+  "optimized",                         /* name */
   NULL,                                        /* gate */
   execute_cleanup_cfg_post_optimizing, /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   TODO_dump_func                       /* todo_flags_finish */
+    | TODO_remove_unused_locals
  }
 };
 
 /* Pass: do the actions required to finish with tree-ssa optimization
    passes.  */
 
-static unsigned int
+unsigned int
 execute_free_datastructures (void)
 {
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
 
-  /* Remove the ssa structures.  */
-  if (cfun->gimple_df)
-    delete_tree_ssa ();
-  return 0;
-}
-
-struct gimple_opt_pass pass_free_datastructures =
-{
- {
-  GIMPLE_PASS,
-  NULL,                                        /* name */
-  NULL,                                        /* gate */
-  execute_free_datastructures,                 /* 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 */
- }
-};
-/* Pass: free cfg annotations.  */
-
-static unsigned int
-execute_free_cfg_annotations (void)
-{
   /* And get rid of annotations we no longer need.  */
   delete_tree_cfg_annotations ();
 
   return 0;
 }
 
-struct gimple_opt_pass pass_free_cfg_annotations =
-{
- {
-  GIMPLE_PASS,
-  NULL,                                        /* name */
-  NULL,                                        /* gate */
-  execute_free_cfg_annotations,                /* 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 */
- }
-};
-
 /* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
    might have changed some properties, such as marked functions nothrow.
    Remove redundant edges and basic blocks, and create new ones if necessary.
@@ -289,47 +241,84 @@ unsigned int
 execute_fixup_cfg (void)
 {
   basic_block bb;
-  block_stmt_iterator bsi;
+  gimple_stmt_iterator gsi;
   int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
+  gcov_type count_scale;
+  edge e;
+  edge_iterator ei;
+
+  if (ENTRY_BLOCK_PTR->count)
+    count_scale = (cgraph_node (current_function_decl)->count * REG_BR_PROB_BASE
+                  + ENTRY_BLOCK_PTR->count / 2) / ENTRY_BLOCK_PTR->count;
+  else
+    count_scale = REG_BR_PROB_BASE;
 
-  cfun->after_inlining = true;
-
-  if (cfun->eh)
-    FOR_EACH_BB (bb)
-      {
-       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
-         {
-           tree stmt = bsi_stmt (bsi);
-           tree call = get_call_expr_in (stmt);
-           tree decl = call ? get_callee_fndecl (call) : NULL;
-
-           if (decl && call_expr_flags (call) & (ECF_CONST | ECF_PURE 
-                                                 | ECF_LOOPING_CONST_OR_PURE)
-               && TREE_SIDE_EFFECTS (call))
-             {
-               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))
-             TREE_NOTHROW (call) = 1;
-           if (!tree_could_throw_p (stmt) && lookup_stmt_eh_region (stmt))
-             remove_stmt_from_eh_region (stmt);
-         }
-       if (tree_purge_dead_eh_edges (bb))
-          todo |= TODO_cleanup_cfg;
-      }
+  ENTRY_BLOCK_PTR->count = cgraph_node (current_function_decl)->count;
+  EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
+                          + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
+
+  FOR_EACH_BB (bb)
+    {
+      bb->count = (bb->count * count_scale
+                  + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
+      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+         tree decl = is_gimple_call (stmt)
+                     ? gimple_call_fndecl (stmt)
+                     : NULL;
+
+         if (decl
+             && gimple_call_flags (stmt) & (ECF_CONST
+                                            | ECF_PURE
+                                            | ECF_LOOPING_CONST_OR_PURE))
+           {
+             if (gimple_in_ssa_p (cfun))
+               {
+                 todo |= TODO_update_ssa | TODO_cleanup_cfg;
+                 mark_symbols_for_renaming (stmt);
+                 update_stmt (stmt);
+               }
+           }
+
+         maybe_clean_eh_stmt (stmt);
+       }
+
+      if (gimple_purge_dead_eh_edges (bb))
+       todo |= TODO_cleanup_cfg;
+      FOR_EACH_EDGE (e, ei, bb->succs)
+        e->count = (e->count * count_scale
+                   + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
+    }
+  if (count_scale != REG_BR_PROB_BASE)
+    compute_function_frequency ();
 
   /* Dump a textual representation of the flowgraph.  */
   if (dump_file)
-    dump_tree_cfg (dump_file, dump_flags);
+    gimple_dump_cfg (dump_file, dump_flags);
 
   return todo;
 }
 
+struct gimple_opt_pass pass_fixup_cfg =
+{
+ {
+  GIMPLE_PASS,
+  "*free_cfg_annotations",             /* name */
+  NULL,                                        /* gate */
+  execute_fixup_cfg,                   /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_NONE,                             /* tv_id */
+  PROP_cfg,                            /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  0                                    /* todo_flags_finish */
+ }
+};
+
 /* Do the actions required to initialize internal data structures used
    in tree-ssa optimization passes.  */
 
@@ -341,25 +330,17 @@ execute_init_datastructures (void)
   return 0;
 }
 
-/* Gate: initialize or not the SSA datastructures.  */
-
-static bool
-gate_init_datastructures (void)
-{
-  return (optimize >= 1);
-}
-
 struct gimple_opt_pass pass_init_datastructures =
 {
  {
   GIMPLE_PASS,
-  NULL,                                        /* name */
-  gate_init_datastructures,            /* gate */
+  "*init_datastructures",              /* name */
+  NULL,                                        /* gate */
   execute_init_datastructures,         /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -375,7 +356,7 @@ tree_lowering_passes (tree fn)
 
   current_function_decl = fn;
   push_cfun (DECL_STRUCT_FUNCTION (fn));
-  tree_register_cfg_hooks ();
+  gimple_register_cfg_hooks ();
   bitmap_obstack_initialize (NULL);
   execute_pass_list (all_lowering_passes);
   if (optimize && cgraph_global_info_ready)
@@ -395,13 +376,10 @@ void
 tree_rest_of_compilation (tree fndecl)
 {
   location_t saved_loc;
-  struct cgraph_node *node;
 
   timevar_push (TV_EXPAND);
 
-  gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
-
-  node = cgraph_node (fndecl);
+  gcc_assert (cgraph_global_info_ready);
 
   /* Initialize the default bitmap obstack.  */
   bitmap_obstack_initialize (NULL);
@@ -417,19 +395,28 @@ tree_rest_of_compilation (tree fndecl)
      We haven't necessarily assigned RTL to all variables yet, so it's
      not safe to try to expand expressions involving them.  */
   cfun->dont_save_pending_sizes_p = 1;
-  
-  tree_register_cfg_hooks ();
+
+  gimple_register_cfg_hooks ();
 
   bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
+
+  execute_all_ipa_transforms ();
+
   /* Perform all tree transforms and optimizations.  */
+
+  /* Signal the start of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
+
   execute_pass_list (all_passes);
-  
+
+  /* Signal the end of passes.  */
+  invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
+
   bitmap_obstack_release (&reg_obstack);
 
   /* Release the default bitmap obstack.  */
   bitmap_obstack_release (NULL);
-  
-  DECL_SAVED_TREE (fndecl) = NULL;
+
   set_cfun (NULL);
 
   /* If requested, warn about function definitions where the function will
@@ -456,20 +443,17 @@ tree_rest_of_compilation (tree fndecl)
        }
     }
 
-  if (!flag_inline_trees)
+  gimple_set_body (fndecl, NULL);
+  if (DECL_STRUCT_FUNCTION (fndecl) == 0
+      && !cgraph_node (fndecl)->origin)
     {
-      DECL_SAVED_TREE (fndecl) = NULL;
-      if (DECL_STRUCT_FUNCTION (fndecl) == 0
-         && !cgraph_node (fndecl)->origin)
-       {
-         /* Stop pointing to the local nodes about to be freed.
-            But DECL_INITIAL must remain nonzero so we know this
-            was an actual function definition.
-            For a nested function, this is done in c_pop_function_context.
-            If rest_of_compilation set this to 0, leave it 0.  */
-         if (DECL_INITIAL (fndecl) != 0)
-           DECL_INITIAL (fndecl) = error_mark_node;
-       }
+      /* Stop pointing to the local nodes about to be freed.
+        But DECL_INITIAL must remain nonzero so we know this
+        was an actual function definition.
+        For a nested function, this is done in c_pop_function_context.
+        If rest_of_compilation set this to 0, leave it 0.  */
+      if (DECL_INITIAL (fndecl) != 0)
+       DECL_INITIAL (fndecl) = error_mark_node;
     }
 
   input_location = saved_loc;