OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
index 23b7046..3d18d20 100644 (file)
@@ -1,5 +1,5 @@
 /* Top-level control of tree optimizations.
 /* Top-level control of tree optimizations.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -24,32 +24,28 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tm_p.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
 #include "basic-block.h"
 #include "output.h"
-#include "expr.h"
-#include "diagnostic.h"
-#include "basic-block.h"
 #include "flags.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "timevar.h"
 #include "function.h"
 #include "langhooks.h"
 #include "flags.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "timevar.h"
 #include "function.h"
 #include "langhooks.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "flags.h"
 #include "cgraph.h"
 #include "tree-inline.h"
 #include "toplev.h"
 #include "flags.h"
 #include "cgraph.h"
 #include "tree-inline.h"
-#include "tree-mudflap.h"
 #include "tree-pass.h"
 #include "ggc.h"
 #include "cgraph.h"
 #include "graph.h"
 #include "cfgloop.h"
 #include "except.h"
 #include "tree-pass.h"
 #include "ggc.h"
 #include "cgraph.h"
 #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.  */
 
 
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
 
@@ -59,7 +55,7 @@ gate_all_optimizations (void)
   return (optimize >= 1
          /* Don't bother doing anything if the program has errors.
             We have to pass down the queue if we already went into SSA */
   return (optimize >= 1
          /* 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)));
+         && (!seen_error () || gimple_in_ssa_p (cfun)));
 }
 
 struct gimple_opt_pass pass_all_optimizations =
 }
 
 struct gimple_opt_pass pass_all_optimizations =
@@ -72,7 +68,7 @@ struct gimple_opt_pass pass_all_optimizations =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  TV_NONE,                             /* tv_id */
+  TV_OPTIMIZE,                         /* tv_id */
   0,                                   /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -87,7 +83,21 @@ static bool
 gate_all_early_local_passes (void)
 {
          /* Don't bother doing anything if the program has errors.  */
 gate_all_early_local_passes (void)
 {
          /* Don't bother doing anything if the program has errors.  */
-  return (!errorcount && !sorrycount && !in_lto_p);
+  return (!seen_error () && !in_lto_p);
+}
+
+static unsigned int
+execute_all_early_local_passes (void)
+{
+  /* Once this pass (and its sub-passes) are complete, all functions
+     will be in SSA form.  Technically this state change is happening
+     a tad early, since the sub-passes have not yet run, but since
+     none of the sub-passes are IPA passes and do not create new
+     functions, this is ok.  We're setting this value for the benefit
+     of IPA passes that follow.  */
+  if (cgraph_state < CGRAPH_STATE_IPA_SSA)
+    cgraph_state = CGRAPH_STATE_IPA_SSA;
+  return 0;
 }
 
 struct simple_ipa_opt_pass pass_early_local_passes =
 }
 
 struct simple_ipa_opt_pass pass_early_local_passes =
@@ -96,11 +106,11 @@ struct simple_ipa_opt_pass pass_early_local_passes =
   SIMPLE_IPA_PASS,
   "early_local_cleanups",              /* name */
   gate_all_early_local_passes,         /* gate */
   SIMPLE_IPA_PASS,
   "early_local_cleanups",              /* name */
   gate_all_early_local_passes,         /* gate */
-  NULL,                                        /* execute */
+  execute_all_early_local_passes,      /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  TV_NONE,                             /* tv_id */
+  TV_EARLY_LOCAL,                      /* tv_id */
   0,                                   /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -109,18 +119,6 @@ struct simple_ipa_opt_pass pass_early_local_passes =
  }
 };
 
  }
 };
 
-static unsigned int
-execute_early_local_optimizations (void)
-{
-  /* First time we start with early optimization we need to advance
-     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 (cgraph_state < CGRAPH_STATE_IPA_SSA)
-    cgraph_state = CGRAPH_STATE_IPA_SSA;
-  return 0;
-}
-
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
 
 static bool
 /* Gate: execute, or not, all of the non-trivial optimizations.  */
 
 static bool
@@ -128,7 +126,7 @@ gate_all_early_optimizations (void)
 {
   return (optimize >= 1
          /* Don't bother doing anything if the program has errors.  */
 {
   return (optimize >= 1
          /* Don't bother doing anything if the program has errors.  */
-         && !(errorcount || sorrycount));
+         && !seen_error ());
 }
 
 struct gimple_opt_pass pass_all_early_optimizations =
 }
 
 struct gimple_opt_pass pass_all_early_optimizations =
@@ -137,7 +135,7 @@ struct gimple_opt_pass pass_all_early_optimizations =
   GIMPLE_PASS,
   "early_optimizations",               /* name */
   gate_all_early_optimizations,                /* gate */
   GIMPLE_PASS,
   "early_optimizations",               /* name */
   gate_all_early_optimizations,                /* gate */
-  execute_early_local_optimizations,   /* execute */
+  NULL,                                        /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
@@ -150,37 +148,6 @@ struct gimple_opt_pass pass_all_early_optimizations =
  }
 };
 
  }
 };
 
-/* Pass: cleanup the CFG just before expanding trees to RTL.
-   This is just a round of label cleanups and case node grouping
-   because after the tree optimizers have run such cleanups may
-   be necessary.  */
-
-static unsigned int
-execute_cleanup_cfg_pre_ipa (void)
-{
-  cleanup_tree_cfg ();
-  return 0;
-}
-
-struct gimple_opt_pass pass_cleanup_cfg =
-{
- {
-  GIMPLE_PASS,
-  "cleanup_cfg",                       /* name */
-  NULL,                                        /* gate */
-  execute_cleanup_cfg_pre_ipa,         /* 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 */
-  TODO_dump_func                       /* todo_flags_finish */
- }
-};
-
 
 /* Pass: cleanup the CFG just before expanding trees to RTL.
    This is just a round of label cleanups and case node grouping
 
 /* Pass: cleanup the CFG just before expanding trees to RTL.
    This is just a round of label cleanups and case node grouping
@@ -190,11 +157,42 @@ struct gimple_opt_pass pass_cleanup_cfg =
 static unsigned int
 execute_cleanup_cfg_post_optimizing (void)
 {
 static unsigned int
 execute_cleanup_cfg_post_optimizing (void)
 {
-  fold_cond_expr_cond ();
-  cleanup_tree_cfg ();
+  unsigned int todo = 0;
+  if (cleanup_tree_cfg ())
+    todo |= TODO_update_ssa;
+  maybe_remove_unreachable_handlers ();
   cleanup_dead_labels ();
   group_case_labels ();
   cleanup_dead_labels ();
   group_case_labels ();
-  return 0;
+  if ((flag_compare_debug_opt || flag_compare_debug)
+      && flag_dump_final_insns)
+    {
+      FILE *final_output = fopen (flag_dump_final_insns, "a");
+
+      if (!final_output)
+       {
+         error ("could not open final insn dump file %qs: %m",
+                flag_dump_final_insns);
+         flag_dump_final_insns = NULL;
+       }
+      else
+       {
+         int save_unnumbered = flag_dump_unnumbered;
+         int save_noaddr = flag_dump_noaddr;
+
+         flag_dump_noaddr = flag_dump_unnumbered = 1;
+         fprintf (final_output, "\n");
+         dump_enumerated_decls (final_output, dump_flags | TDF_NOUID);
+         flag_dump_noaddr = save_noaddr;
+         flag_dump_unnumbered = save_unnumbered;
+         if (fclose (final_output))
+           {
+             error ("could not close final insn dump file %qs: %m",
+                    flag_dump_final_insns);
+             flag_dump_final_insns = NULL;
+           }
+       }
+    }
+  return todo;
 }
 
 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
 }
 
 struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
@@ -207,13 +205,12 @@ struct gimple_opt_pass pass_cleanup_cfg_post_optimizing =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  TV_NONE,                             /* tv_id */
+  TV_TREE_CLEANUP_CFG,                 /* tv_id */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   PROP_cfg,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func                       /* todo_flags_finish */
-    | TODO_remove_unused_locals
+  TODO_remove_unused_locals             /* todo_flags_finish */
  }
 };
 
  }
 };
 
@@ -232,8 +229,9 @@ execute_free_datastructures (void)
   return 0;
 }
 
   return 0;
 }
 
-/* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
-   might have changed some properties, such as marked functions nothrow.
+/* IPA passes, compilation of earlier functions or inlining
+   might have changed some properties, such as marked functions nothrow,
+   pure, const or noreturn.
    Remove redundant edges and basic blocks, and create new ones if necessary.
 
    This pass can't be executed as stand alone pass from pass manager, because
    Remove redundant edges and basic blocks, and create new ones if necessary.
 
    This pass can't be executed as stand alone pass from pass manager, because
@@ -250,15 +248,20 @@ execute_fixup_cfg (void)
   edge_iterator ei;
 
   if (ENTRY_BLOCK_PTR->count)
   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;
+    count_scale = ((cgraph_get_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;
 
   else
     count_scale = REG_BR_PROB_BASE;
 
-  ENTRY_BLOCK_PTR->count = cgraph_node (current_function_decl)->count;
+  ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count;
   EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
                           + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
 
   EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale
                           + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
 
+  FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
+    e->count = (e->count * count_scale
+       + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
+
   FOR_EACH_BB (bb)
     {
       bb->count = (bb->count * count_scale
   FOR_EACH_BB (bb)
     {
       bb->count = (bb->count * count_scale
@@ -269,25 +272,31 @@ execute_fixup_cfg (void)
          tree decl = is_gimple_call (stmt)
                      ? gimple_call_fndecl (stmt)
                      : NULL;
          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 (decl)
            {
            {
-             if (gimple_in_ssa_p (cfun))
+             int flags = gimple_call_flags (stmt);
+             if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE))
                {
                {
-                 todo |= TODO_update_ssa | TODO_cleanup_cfg;
-                 mark_symbols_for_renaming (stmt);
-                 update_stmt (stmt);
+                 if (gimple_purge_dead_abnormal_call_edges (bb))
+                   todo |= TODO_cleanup_cfg;
+
+                 if (gimple_in_ssa_p (cfun))
+                   {
+                     todo |= TODO_update_ssa | TODO_cleanup_cfg;
+                     update_stmt (stmt);
+                   }
                }
                }
-           }
 
 
-         maybe_clean_eh_stmt (stmt);
+             if (flags & ECF_NORETURN
+                 && fixup_noreturn_call (stmt))
+               todo |= TODO_cleanup_cfg;
+            }
+
+         if (maybe_clean_eh_stmt (stmt)
+             && gimple_purge_dead_eh_edges (bb))
+           todo |= TODO_cleanup_cfg;
        }
 
        }
 
-      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;
       FOR_EACH_EDGE (e, ei, bb->succs)
         e->count = (e->count * count_scale
                    + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
@@ -295,6 +304,13 @@ execute_fixup_cfg (void)
   if (count_scale != REG_BR_PROB_BASE)
     compute_function_frequency ();
 
   if (count_scale != REG_BR_PROB_BASE)
     compute_function_frequency ();
 
+  /* We just processed all calls.  */
+  if (cfun->gimple_df)
+    {
+      VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun));
+      MODIFIED_NORETURN_CALLS (cfun) = NULL;
+    }
+
   /* Dump a textual representation of the flowgraph.  */
   if (dump_file)
     gimple_dump_cfg (dump_file, dump_flags);
   /* Dump a textual representation of the flowgraph.  */
   if (dump_file)
     gimple_dump_cfg (dump_file, dump_flags);
@@ -379,7 +395,7 @@ tree_rest_of_compilation (tree fndecl)
 {
   location_t saved_loc;
 
 {
   location_t saved_loc;
 
-  timevar_push (TV_EXPAND);
+  timevar_push (TV_REST_OF_COMPILATION);
 
   gcc_assert (cgraph_global_info_ready);
 
 
   gcc_assert (cgraph_global_info_ready);
 
@@ -392,12 +408,6 @@ tree_rest_of_compilation (tree fndecl)
   input_location = DECL_SOURCE_LOCATION (fndecl);
   init_function_start (fndecl);
 
   input_location = DECL_SOURCE_LOCATION (fndecl);
   init_function_start (fndecl);
 
-  /* Even though we're inside a function body, we still don't want to
-     call expand_expr to calculate the size of a variable-sized array.
-     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;
-
   gimple_register_cfg_hooks ();
 
   bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
   gimple_register_cfg_hooks ();
 
   bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
@@ -405,8 +415,15 @@ tree_rest_of_compilation (tree fndecl)
   execute_all_ipa_transforms ();
 
   /* Perform all tree transforms and optimizations.  */
   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);
 
   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 (&reg_obstack);
 
   /* Release the default bitmap obstack.  */
@@ -430,17 +447,17 @@ tree_rest_of_compilation (tree fndecl)
            = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
          if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
            = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
          if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
-           warning (OPT_Wlarger_than_eq, "size of return value of %q+D is %u bytes",
+           warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes",
                      fndecl, size_as_int);
          else
                      fndecl, size_as_int);
          else
-           warning (OPT_Wlarger_than_eq, "size of return value of %q+D is larger than %wd bytes",
+           warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes",
                      fndecl, larger_than_size);
        }
     }
 
   gimple_set_body (fndecl, NULL);
   if (DECL_STRUCT_FUNCTION (fndecl) == 0
                      fndecl, larger_than_size);
        }
     }
 
   gimple_set_body (fndecl, NULL);
   if (DECL_STRUCT_FUNCTION (fndecl) == 0
-      && !cgraph_node (fndecl)->origin)
+      && !cgraph_get_node (fndecl)->origin)
     {
       /* Stop pointing to the local nodes about to be freed.
         But DECL_INITIAL must remain nonzero so we know this
     {
       /* Stop pointing to the local nodes about to be freed.
         But DECL_INITIAL must remain nonzero so we know this
@@ -454,5 +471,5 @@ tree_rest_of_compilation (tree fndecl)
   input_location = saved_loc;
 
   ggc_collect ();
   input_location = saved_loc;
 
   ggc_collect ();
-  timevar_pop (TV_EXPAND);
+  timevar_pop (TV_REST_OF_COMPILATION);
 }
 }