OSDN Git Service

2010-07-25 Jerry DeLisle <jvdelisle@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-optimize.c
index f71ab4d..5df3fdb 100644 (file)
@@ -1,5 +1,5 @@
 /* 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>
 
@@ -27,14 +27,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm_p.h"
 #include "basic-block.h"
 #include "output.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 "diagnostic-core.h"
 #include "toplev.h"
 #include "flags.h"
 #include "cgraph.h"
@@ -47,7 +46,7 @@ along with GCC; see the file COPYING3.  If not see
 #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.  */
 
@@ -57,7 +56,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 */
-         && (!(errorcount || sorrycount) || gimple_in_ssa_p (cfun)));
+         && (!seen_error () || gimple_in_ssa_p (cfun)));
 }
 
 struct gimple_opt_pass pass_all_optimizations =
@@ -85,7 +84,21 @@ static bool
 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 =
@@ -94,7 +107,7 @@ struct simple_ipa_opt_pass pass_early_local_passes =
   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 */
@@ -107,18 +120,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
@@ -126,7 +127,7 @@ gate_all_early_optimizations (void)
 {
   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 =
@@ -135,7 +136,7 @@ struct gimple_opt_pass pass_all_early_optimizations =
   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 */
@@ -192,6 +193,35 @@ execute_cleanup_cfg_post_optimizing (void)
   cleanup_tree_cfg ();
   cleanup_dead_labels ();
   group_case_labels ();
+  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 0;
 }
 
@@ -231,7 +261,8 @@ execute_free_datastructures (void)
 }
 
 /* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
-   might have changed some properties, such as marked functions nothrow.
+   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
@@ -267,19 +298,23 @@ execute_fixup_cfg (void)
          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_in_ssa_p (cfun))
+                   {
+                     todo |= TODO_update_ssa | TODO_cleanup_cfg;
+                     mark_symbols_for_renaming (stmt);
+                     update_stmt (stmt);
+                   }
                }
-           }
+             
+             if (flags & ECF_NORETURN
+                 && fixup_noreturn_call (stmt))
+               todo |= TODO_cleanup_cfg;
+            }
 
          maybe_clean_eh_stmt (stmt);
        }
@@ -293,6 +328,13 @@ execute_fixup_cfg (void)
   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);