OSDN Git Service

Fix clearing ZERO_REG
[pf3gnuchains/gcc-fork.git] / gcc / passes.c
index 38b38cd..a786881 100644 (file)
@@ -1,7 +1,7 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011, 2012  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -74,6 +74,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "lto-streamer.h"
 #include "plugin.h"
 #include "ipa-utils.h"
+#include "tree-pretty-print.h"
 
 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
 #include "dwarf2out.h"
@@ -97,6 +98,8 @@ along with GCC; see the file COPYING3.  If not see
    The variable current_pass is also used for statistics and plugins.  */
 struct opt_pass *current_pass;
 
+static void register_pass_name (struct opt_pass *, const char *);
+
 /* Call from anywhere to find out what pass this is.  Useful for
    printing out debugging information deep inside an service
    routine.  */
@@ -153,6 +156,11 @@ rest_of_decl_compilation (tree decl,
       {
        alias = TREE_VALUE (TREE_VALUE (alias));
        alias = get_identifier (TREE_STRING_POINTER (alias));
+       /* A quirk of the initial implementation of aliases required that the
+          user add "extern" to all of them.  Which is silly, but now
+          historical.  Do note that the symbol is in fact locally defined.  */
+       if (!lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+         DECL_EXTERNAL (decl) = 0;
        assemble_alias (decl, alias);
       }
   }
@@ -329,7 +337,7 @@ struct rtl_opt_pass pass_postreload =
 
 /* The root of the compilation pass tree, once constructed.  */
 struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes,
-  *all_regular_ipa_passes, *all_lto_gen_passes;
+  *all_regular_ipa_passes, *all_late_ipa_passes, *all_lto_gen_passes;
 
 /* This is used by plugins, and should also be used in register_pass.  */
 #define DEF_PASS_LIST(LIST) &LIST,
@@ -375,7 +383,7 @@ void
 register_one_dump_file (struct opt_pass *pass)
 {
   char *dot_name, *flag_name, *glob_name;
-  const char *name, *prefix;
+  const char *name, *full_name, *prefix;
   char num[10];
   int flags, id;
 
@@ -404,6 +412,9 @@ register_one_dump_file (struct opt_pass *pass)
   glob_name = concat (prefix, name, NULL);
   id = dump_register (dot_name, flag_name, glob_name, flags);
   set_pass_for_id (id, pass);
+  full_name = concat (prefix, pass->name, num, NULL);
+  register_pass_name (pass, full_name);
+  free (CONST_CAST (char *, full_name));
 }
 
 /* Recursive worker function for register_dump_files.  */
@@ -447,6 +458,451 @@ register_dump_files (struct opt_pass *pass,int properties)
   register_dump_files_1 (pass, properties);
 }
 
+struct pass_registry
+{
+  const char* unique_name;
+  struct opt_pass *pass;
+};
+
+/* Pass registry hash function.  */
+
+static hashval_t
+passr_hash (const void *p)
+{
+  const struct pass_registry *const s = (const struct pass_registry *const) p;
+  return htab_hash_string (s->unique_name);
+}
+
+/* Hash equal function  */
+
+static int
+passr_eq (const void *p1, const void *p2)
+{
+  const struct pass_registry *const s1 = (const struct pass_registry *const) p1;
+  const struct pass_registry *const s2 = (const struct pass_registry *const) p2;
+
+  return !strcmp (s1->unique_name, s2->unique_name);
+}
+
+static htab_t name_to_pass_map = NULL;
+
+/* Register PASS with NAME.  */
+
+static void
+register_pass_name (struct opt_pass *pass, const char *name)
+{
+  struct pass_registry **slot;
+  struct pass_registry pr;
+
+  if (!name_to_pass_map)
+    name_to_pass_map = htab_create (256, passr_hash, passr_eq, NULL);
+
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (name_to_pass_map, &pr, INSERT);
+  if (!*slot)
+    {
+      struct pass_registry *new_pr;
+
+      new_pr = XCNEW (struct pass_registry);
+      new_pr->unique_name = xstrdup (name);
+      new_pr->pass = pass;
+      *slot = new_pr;
+    }
+  else
+    return; /* Ignore plugin passes.  */
+}
+
+/* Map from pass id to canonicalized pass name.  */
+
+typedef const char *char_ptr;
+DEF_VEC_P(char_ptr);
+DEF_VEC_ALLOC_P(char_ptr, heap);
+static VEC(char_ptr, heap) *pass_tab = NULL;
+
+/* Callback function for traversing NAME_TO_PASS_MAP.  */
+
+static int
+pass_traverse (void **slot, void *data ATTRIBUTE_UNUSED)
+{
+  struct pass_registry **p = (struct pass_registry **)slot;
+  struct opt_pass *pass = (*p)->pass;
+
+  gcc_assert (pass->static_pass_number > 0);
+  gcc_assert (pass_tab);
+
+  VEC_replace (char_ptr, pass_tab, pass->static_pass_number,
+               (*p)->unique_name);
+
+  return 1;
+}
+
+/* The function traverses NAME_TO_PASS_MAP and creates a pass info
+   table for dumping purpose.  */
+
+static void
+create_pass_tab (void)
+{
+  if (!flag_dump_passes)
+    return;
+
+  VEC_safe_grow_cleared (char_ptr, heap,
+                         pass_tab, passes_by_id_size + 1);
+  htab_traverse (name_to_pass_map, pass_traverse, NULL);
+}
+
+static bool override_gate_status (struct opt_pass *, tree, bool);
+
+/* Dump the instantiated name for PASS. IS_ON indicates if PASS
+   is turned on or not.  */
+
+static void
+dump_one_pass (struct opt_pass *pass, int pass_indent)
+{
+  int indent = 3 * pass_indent;
+  const char *pn;
+  bool is_on, is_really_on;
+
+  is_on = (pass->gate == NULL) ? true : pass->gate();
+  is_really_on = override_gate_status (pass, current_function_decl, is_on);
+
+  if (pass->static_pass_number <= 0)
+    pn = pass->name;
+  else
+    pn = VEC_index (char_ptr, pass_tab, pass->static_pass_number);
+
+  fprintf (stderr, "%*s%-40s%*s:%s%s\n", indent, " ", pn,
+           (15 - indent < 0 ? 0 : 15 - indent), " ",
+           is_on ? "  ON" : "  OFF",
+           ((!is_on) == (!is_really_on) ? ""
+            : (is_really_on ? " (FORCED_ON)" : " (FORCED_OFF)")));
+}
+
+/* Dump pass list PASS with indentation INDENT.  */
+
+static void
+dump_pass_list (struct opt_pass *pass, int indent)
+{
+  do
+    {
+      dump_one_pass (pass, indent);
+      if (pass->sub)
+        dump_pass_list (pass->sub, indent + 1);
+      pass = pass->next;
+    }
+  while (pass);
+}
+
+/* Dump all optimization passes.  */
+
+void
+dump_passes (void)
+{
+  struct cgraph_node *n, *node = NULL;
+  tree save_fndecl = current_function_decl;
+
+  create_pass_tab();
+
+  n = cgraph_nodes;
+  while (n)
+    {
+      if (DECL_STRUCT_FUNCTION (n->decl))
+        {
+          node = n;
+          break;
+        }
+      n = n->next;
+    }
+
+  if (!node)
+    return;
+
+  push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+  current_function_decl = node->decl;
+
+  dump_pass_list (all_lowering_passes, 1);
+  dump_pass_list (all_small_ipa_passes, 1);
+  dump_pass_list (all_regular_ipa_passes, 1);
+  dump_pass_list (all_lto_gen_passes, 1);
+  dump_pass_list (all_late_ipa_passes, 1);
+  dump_pass_list (all_passes, 1);
+
+  pop_cfun ();
+  current_function_decl = save_fndecl;
+}
+
+
+/* Returns the pass with NAME.  */
+
+static struct opt_pass *
+get_pass_by_name (const char *name)
+{
+  struct pass_registry **slot, pr;
+
+  pr.unique_name = name;
+  slot = (struct pass_registry **) htab_find_slot (name_to_pass_map,
+                                                   &pr, NO_INSERT);
+
+  if (!slot || !*slot)
+    return NULL;
+
+  return (*slot)->pass;
+}
+
+
+/* Range [start, last].  */
+
+struct uid_range
+{
+  unsigned int start;
+  unsigned int last;
+  const char *assem_name;
+  struct uid_range *next;
+};
+
+typedef struct uid_range *uid_range_p;
+
+DEF_VEC_P(uid_range_p);
+DEF_VEC_ALLOC_P(uid_range_p, heap);
+
+static VEC(uid_range_p, heap) *enabled_pass_uid_range_tab = NULL;
+static VEC(uid_range_p, heap) *disabled_pass_uid_range_tab = NULL;
+
+
+/* Parse option string for -fdisable- and -fenable-
+   The syntax of the options:
+
+   -fenable-<pass_name>
+   -fdisable-<pass_name>
+
+   -fenable-<pass_name>=s1:e1,s2:e2,...
+   -fdisable-<pass_name>=s1:e1,s2:e2,...
+*/
+
+static void
+enable_disable_pass (const char *arg, bool is_enable)
+{
+  struct opt_pass *pass;
+  char *range_str, *phase_name;
+  char *argstr = xstrdup (arg);
+  VEC(uid_range_p, heap) **tab = 0;
+
+  range_str = strchr (argstr,'=');
+  if (range_str)
+    {
+      *range_str = '\0';
+      range_str++;
+    }
+
+  phase_name = argstr;
+  if (!*phase_name)
+    {
+      if (is_enable)
+        error ("unrecognized option -fenable");
+      else
+        error ("unrecognized option -fdisable");
+      free (argstr);
+      return;
+    }
+  pass = get_pass_by_name (phase_name);
+  if (!pass || pass->static_pass_number == -1)
+    {
+      if (is_enable)
+        error ("unknown pass %s specified in -fenable", phase_name);
+      else
+        error ("unknown pass %s specified in -fdisble", phase_name);
+      free (argstr);
+      return;
+    }
+
+  if (is_enable)
+    tab = &enabled_pass_uid_range_tab;
+  else
+    tab = &disabled_pass_uid_range_tab;
+
+  if ((unsigned) pass->static_pass_number >= VEC_length (uid_range_p, *tab))
+    VEC_safe_grow_cleared (uid_range_p, heap,
+                           *tab, pass->static_pass_number + 1);
+
+  if (!range_str)
+    {
+      uid_range_p slot;
+      uid_range_p new_range = XCNEW (struct uid_range);
+
+      new_range->start = 0;
+      new_range->last = (unsigned)-1;
+
+      slot = VEC_index (uid_range_p, *tab, pass->static_pass_number);
+      new_range->next = slot;
+      VEC_replace (uid_range_p, *tab, pass->static_pass_number,
+                   new_range);
+      if (is_enable)
+        inform (UNKNOWN_LOCATION, "enable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+      else
+        inform (UNKNOWN_LOCATION, "disable pass %s for functions in the range "
+                "of [%u, %u]", phase_name, new_range->start, new_range->last);
+    }
+  else
+    {
+      char *next_range = NULL;
+      char *one_range = range_str;
+      char *end_val = NULL;
+
+      do
+       {
+         uid_range_p slot;
+         uid_range_p new_range;
+         char *invalid = NULL;
+         long start;
+         char *func_name = NULL;
+
+         next_range = strchr (one_range, ',');
+         if (next_range)
+           {
+             *next_range = '\0';
+             next_range++;
+           }
+
+         end_val = strchr (one_range, ':');
+         if (end_val)
+           {
+             *end_val = '\0';
+             end_val++;
+           }
+         start = strtol (one_range, &invalid, 10);
+         if (*invalid || start < 0)
+           {
+              if (end_val || (one_range[0] >= '0'
+                             && one_range[0] <= '9'))
+                {
+                  error ("Invalid range %s in option %s",
+                         one_range,
+                         is_enable ? "-fenable" : "-fdisable");
+                  free (argstr);
+                  return;
+                }
+             func_name = one_range;
+           }
+         if (!end_val)
+           {
+             new_range = XCNEW (struct uid_range);
+              if (!func_name)
+                {
+                  new_range->start = (unsigned) start;
+                  new_range->last = (unsigned) start;
+                }
+              else
+                {
+                  new_range->start = (unsigned) -1;
+                  new_range->last = (unsigned) -1;
+                  new_range->assem_name = xstrdup (func_name);
+                }
+           }
+         else
+           {
+             long last = strtol (end_val, &invalid, 10);
+             if (*invalid || last < start)
+               {
+                 error ("Invalid range %s in option %s",
+                        end_val,
+                        is_enable ? "-fenable" : "-fdisable");
+                 free (argstr);
+                 return;
+               }
+             new_range = XCNEW (struct uid_range);
+             new_range->start = (unsigned) start;
+             new_range->last = (unsigned) last;
+           }
+
+          slot = VEC_index (uid_range_p, *tab, pass->static_pass_number);
+          new_range->next = slot;
+          VEC_replace (uid_range_p, *tab, pass->static_pass_number,
+                       new_range);
+          if (is_enable)
+            {
+              if (new_range->assem_name)
+                inform (UNKNOWN_LOCATION,
+                        "enable pass %s for function %s",
+                        phase_name, new_range->assem_name);
+              else
+                inform (UNKNOWN_LOCATION,
+                        "enable pass %s for functions in the range of [%u, %u]",
+                        phase_name, new_range->start, new_range->last);
+            }
+          else
+            {
+              if (new_range->assem_name)
+                inform (UNKNOWN_LOCATION,
+                        "disable pass %s for function %s",
+                        phase_name, new_range->assem_name);
+              else
+                inform (UNKNOWN_LOCATION,
+                        "disable pass %s for functions in the range of [%u, %u]",
+                        phase_name, new_range->start, new_range->last);
+            }
+
+         one_range = next_range;
+       } while (next_range);
+    }
+
+  free (argstr);
+}
+
+/* Enable pass specified by ARG.  */
+
+void
+enable_pass (const char *arg)
+{
+  enable_disable_pass (arg, true);
+}
+
+/* Disable pass specified by ARG.  */
+
+void
+disable_pass (const char *arg)
+{
+  enable_disable_pass (arg, false);
+}
+
+/* Returns true if PASS is explicitly enabled/disabled for FUNC.  */
+
+static bool
+is_pass_explicitly_enabled_or_disabled (struct opt_pass *pass,
+                                       tree func,
+                                       VEC(uid_range_p, heap) *tab)
+{
+  uid_range_p slot, range;
+  int cgraph_uid;
+  const char *aname = NULL;
+
+  if (!tab
+      || (unsigned) pass->static_pass_number >= VEC_length (uid_range_p, tab)
+      || pass->static_pass_number == -1)
+    return false;
+
+  slot = VEC_index (uid_range_p, tab, pass->static_pass_number);
+  if (!slot)
+    return false;
+
+  cgraph_uid = func ? cgraph_get_node (func)->uid : 0;
+  if (func && DECL_ASSEMBLER_NAME_SET_P (func))
+    aname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func));
+
+  range = slot;
+  while (range)
+    {
+      if ((unsigned) cgraph_uid >= range->start
+         && (unsigned) cgraph_uid <= range->last)
+       return true;
+      if (range->assem_name && aname
+          && !strcmp (range->assem_name, aname))
+        return true;
+      range = range->next;
+    }
+
+  return false;
+}
+
 /* Look at the static_pass_number and duplicate the pass
    if it is already added to a list. */
 
@@ -654,6 +1110,8 @@ register_pass (struct register_pass_info *pass_info)
   if (!success || all_instances)
     success |= position_pass (pass_info, &all_lto_gen_passes);
   if (!success || all_instances)
+    success |= position_pass (pass_info, &all_late_ipa_passes);
+  if (!success || all_instances)
     success |= position_pass (pass_info, &all_passes);
   if (!success)
     fatal_error
@@ -722,9 +1180,11 @@ init_optimization_passes (void)
   p = &all_lowering_passes;
   NEXT_PASS (pass_warn_unused_result);
   NEXT_PASS (pass_diagnose_omp_blocks);
+  NEXT_PASS (pass_diagnose_tm_blocks);
   NEXT_PASS (pass_mudflap_1);
   NEXT_PASS (pass_lower_omp);
   NEXT_PASS (pass_lower_cf);
+  NEXT_PASS (pass_lower_tm);
   NEXT_PASS (pass_refactor_eh);
   NEXT_PASS (pass_lower_eh);
   NEXT_PASS (pass_build_cfg);
@@ -789,6 +1249,7 @@ init_optimization_passes (void)
     }
   NEXT_PASS (pass_ipa_increase_alignment);
   NEXT_PASS (pass_ipa_matrix_reorg);
+  NEXT_PASS (pass_ipa_tm);
   NEXT_PASS (pass_ipa_lower_emutls);
   *p = NULL;
 
@@ -800,7 +1261,6 @@ init_optimization_passes (void)
   NEXT_PASS (pass_ipa_inline);
   NEXT_PASS (pass_ipa_pure_const);
   NEXT_PASS (pass_ipa_reference);
-  NEXT_PASS (pass_ipa_pta);
   *p = NULL;
 
   p = &all_lto_gen_passes;
@@ -808,9 +1268,16 @@ init_optimization_passes (void)
   NEXT_PASS (pass_ipa_lto_finish_out);  /* This must be the last LTO pass.  */
   *p = NULL;
 
+  /* Simple IPA passes executed after the regular passes.  In WHOPR mode the
+     passes are executed after partitioning and thus see just parts of the
+     compiled unit.  */
+  p = &all_late_ipa_passes;
+  NEXT_PASS (pass_ipa_pta);
+  *p = NULL;
   /* These passes are run after IPA passes on every function that is being
      output to the assembler file.  */
   p = &all_passes;
+  NEXT_PASS (pass_fixup_cfg);
   NEXT_PASS (pass_lower_eh_dispatch);
   NEXT_PASS (pass_all_optimizations);
     {
@@ -863,6 +1330,7 @@ init_optimization_passes (void)
       NEXT_PASS (pass_forwprop);
       NEXT_PASS (pass_phiopt);
       NEXT_PASS (pass_object_sizes);
+      NEXT_PASS (pass_strlen);
       NEXT_PASS (pass_ccp);
       NEXT_PASS (pass_copy_prop);
       NEXT_PASS (pass_cse_sincos);
@@ -896,7 +1364,6 @@ init_optimization_passes (void)
          NEXT_PASS (pass_vectorize);
            {
              struct opt_pass **p = &pass_vectorize.pass.sub;
-             NEXT_PASS (pass_lower_vector_ssa);
              NEXT_PASS (pass_dce_loop);
            }
           NEXT_PASS (pass_predcom);
@@ -905,8 +1372,10 @@ init_optimization_passes (void)
          NEXT_PASS (pass_parallelize_loops);
          NEXT_PASS (pass_loop_prefetch);
          NEXT_PASS (pass_iv_optimize);
+         NEXT_PASS (pass_lim);
          NEXT_PASS (pass_tree_loop_done);
        }
+      NEXT_PASS (pass_lower_vector_ssa);
       NEXT_PASS (pass_cse_reciprocals);
       NEXT_PASS (pass_reassoc);
       NEXT_PASS (pass_vrp);
@@ -940,6 +1409,13 @@ init_optimization_passes (void)
       NEXT_PASS (pass_uncprop);
       NEXT_PASS (pass_local_pure_const);
     }
+  NEXT_PASS (pass_tm_init);
+    {
+      struct opt_pass **p = &pass_tm_init.pass.sub;
+      NEXT_PASS (pass_tm_mark);
+      NEXT_PASS (pass_tm_memopt);
+      NEXT_PASS (pass_tm_edges);
+    }
   NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_cleanup_eh);
   NEXT_PASS (pass_lower_resx);
@@ -1009,13 +1485,14 @@ init_optimization_passes (void)
       NEXT_PASS (pass_sms);
       NEXT_PASS (pass_sched);
       NEXT_PASS (pass_ira);
+      NEXT_PASS (pass_reload);
       NEXT_PASS (pass_postreload);
        {
          struct opt_pass **p = &pass_postreload.pass.sub;
          NEXT_PASS (pass_postreload_cse);
          NEXT_PASS (pass_gcse2);
          NEXT_PASS (pass_split_after_reload);
-         NEXT_PASS (pass_implicit_zee);
+         NEXT_PASS (pass_ree);
          NEXT_PASS (pass_compare_elim_after_reload);
          NEXT_PASS (pass_branch_target_load_optimize1);
          NEXT_PASS (pass_thread_prologue_and_epilogue);
@@ -1048,6 +1525,7 @@ init_optimization_passes (void)
          NEXT_PASS (pass_convert_to_eh_region_ranges);
          NEXT_PASS (pass_shorten_branches);
          NEXT_PASS (pass_set_nothrow_function_flags);
+         NEXT_PASS (pass_dwarf2_frame);
          NEXT_PASS (pass_final);
        }
       NEXT_PASS (pass_df_finish);
@@ -1068,6 +1546,9 @@ init_optimization_passes (void)
   register_dump_files (all_lto_gen_passes,
                       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
                       | PROP_cfg);
+  register_dump_files (all_late_ipa_passes,
+                      PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
+                      | PROP_cfg);
   register_dump_files (all_passes,
                       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
                       | PROP_cfg);
@@ -1135,7 +1616,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
          /* Allow possibly removed nodes to be garbage collected.  */
          order[i] = NULL;
          node->process = 0;
-         if (node->analyzed)
+         if (cgraph_function_with_gimple_body_p (node))
            {
              push_cfun (DECL_STRUCT_FUNCTION (node->decl));
              current_function_decl = node->decl;
@@ -1153,6 +1634,37 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
   nnodes = 0;
 }
 
+/* Helper function to perform function body dump.  */
+
+static void
+execute_function_dump (void *data ATTRIBUTE_UNUSED)
+{
+  if (dump_file && current_function_decl)
+    {
+      if (cfun->curr_properties & PROP_trees)
+        dump_function_to_file (current_function_decl, dump_file, dump_flags);
+      else
+       {
+         if (dump_flags & TDF_SLIM)
+           print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags);
+         else if ((cfun->curr_properties & PROP_cfg)
+                  && (dump_flags & TDF_BLOCKS))
+           print_rtl_with_bb (dump_file, get_insns ());
+          else
+           print_rtl (dump_file, get_insns ());
+
+         if ((cfun->curr_properties & PROP_cfg)
+             && graph_dump_format != no_graph
+             && (dump_flags & TDF_GRAPH))
+           print_rtl_graph_with_bb (dump_file_name, get_insns ());
+       }
+
+      /* Flush the file.  If verification fails, we won't be able to
+        close the file before aborting.  */
+      fflush (dump_file);
+    }
+}
+
 /* Perform all TODO actions that ought to be done on each function.  */
 
 static void
@@ -1199,31 +1711,6 @@ execute_function_todo (void *data)
   if (flags & TODO_remove_unused_locals)
     remove_unused_locals ();
 
-  if ((flags & TODO_dump_func) && dump_file && current_function_decl)
-    {
-      if (cfun->curr_properties & PROP_trees)
-        dump_function_to_file (current_function_decl, dump_file, dump_flags);
-      else
-       {
-         if (dump_flags & TDF_SLIM)
-           print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags);
-         else if ((cfun->curr_properties & PROP_cfg)
-                  && (dump_flags & TDF_BLOCKS))
-           print_rtl_with_bb (dump_file, get_insns ());
-          else
-           print_rtl (dump_file, get_insns ());
-
-         if ((cfun->curr_properties & PROP_cfg)
-             && graph_dump_format != no_graph
-             && (dump_flags & TDF_GRAPH))
-           print_rtl_graph_with_bb (dump_file_name, get_insns ());
-       }
-
-      /* Flush the file.  If verification fails, we won't be able to
-        close the file before aborting.  */
-      fflush (dump_file);
-    }
-
   if (flags & TODO_rebuild_frequencies)
     rebuild_frequencies ();
 
@@ -1342,21 +1829,7 @@ pass_init_dump_file (struct opt_pass *pass)
       dump_file_name = get_dump_file_name (pass->static_pass_number);
       dump_file = dump_begin (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
-       {
-         const char *dname, *aname;
-         struct cgraph_node *node = cgraph_get_node (current_function_decl);
-         dname = lang_hooks.decl_printable_name (current_function_decl, 2);
-         aname = (IDENTIFIER_POINTER
-                  (DECL_ASSEMBLER_NAME (current_function_decl)));
-         fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname,
-            node->frequency == NODE_FREQUENCY_HOT
-            ? " (hot)"
-            : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
-            ? " (unlikely executed)"
-            : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-            ? " (executed once)"
-            : "");
-       }
+        dump_function_header (dump_file, current_function_decl, dump_flags);
       return initializing_dump;
     }
   else
@@ -1463,6 +1936,7 @@ execute_one_ipa_transform_pass (struct cgraph_node *node,
   execute_todo (todo_after);
   verify_interpass_invariants ();
 
+  do_per_function (execute_function_dump, NULL);
   pass_fini_dump_file (pass);
 
   current_pass = NULL;
@@ -1493,6 +1967,44 @@ execute_all_ipa_transforms (void)
     }
 }
 
+/* Callback for do_per_function to apply all IPA transforms.  */
+
+static void
+apply_ipa_transforms (void *data)
+{
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
+  if (!node->global.inlined_to && node->ipa_transforms_to_apply)
+    {
+      *(bool *)data = true;
+      execute_all_ipa_transforms();
+      rebuild_cgraph_edges ();
+    }
+}
+
+/* Check if PASS is explicitly disabled or enabled and return
+   the gate status.  FUNC is the function to be processed, and
+   GATE_STATUS is the gate status determined by pass manager by
+   default.  */
+
+static bool
+override_gate_status (struct opt_pass *pass, tree func, bool gate_status)
+{
+  bool explicitly_enabled = false;
+  bool explicitly_disabled = false;
+
+  explicitly_enabled
+   = is_pass_explicitly_enabled_or_disabled (pass, func,
+                                             enabled_pass_uid_range_tab);
+  explicitly_disabled
+   = is_pass_explicitly_enabled_or_disabled (pass, func,
+                                             disabled_pass_uid_range_tab);
+
+  gate_status = !explicitly_disabled && (gate_status || explicitly_enabled);
+
+  return gate_status;
+}
+
+
 /* Execute PASS. */
 
 bool
@@ -1515,6 +2027,7 @@ execute_one_pass (struct opt_pass *pass)
   /* Check whether gate check should be avoided.
      User controls the value of the gate through the parameter "gate_status". */
   gate_status = (pass->gate == NULL) ? true : pass->gate();
+  gate_status = override_gate_status (pass, current_function_decl, gate_status);
 
   /* Override gate with plugin.  */
   invoke_plugin_callbacks (PLUGIN_OVERRIDE_GATE, &gate_status);
@@ -1529,6 +2042,18 @@ execute_one_pass (struct opt_pass *pass)
      executed.  */
   invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
 
+  /* SIPLE IPA passes do not handle callgraphs with IPA transforms in it.
+     Apply all trnasforms first.  */
+  if (pass->type == SIMPLE_IPA_PASS)
+    {
+      bool applied = false;
+      do_per_function (apply_ipa_transforms, (void *)&applied);
+      if (applied)
+        cgraph_remove_unreachable_nodes (true, dump_file);
+      /* Restore current_pass.  */
+      current_pass = pass;
+    }
+
   if (!quiet_flag && !cfun)
     fprintf (stderr, " <%s>", pass->name ? pass->name : "");
 
@@ -1578,13 +2103,13 @@ execute_one_pass (struct opt_pass *pass)
   /* Run post-pass cleanup and verification.  */
   execute_todo (todo_after | pass->todo_flags_finish);
   verify_interpass_invariants ();
+  do_per_function (execute_function_dump, NULL);
   if (pass->type == IPA_PASS)
     {
       struct cgraph_node *node;
-      for (node = cgraph_nodes; node; node = node->next)
-        if (node->analyzed)
-          VEC_safe_push (ipa_opt_pass, heap, node->ipa_transforms_to_apply,
-                        (struct ipa_opt_pass_d *)pass);
+      FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
+       VEC_safe_push (ipa_opt_pass, heap, node->ipa_transforms_to_apply,
+                      (struct ipa_opt_pass_d *)pass);
     }
 
   if (!current_function_decl)
@@ -1705,7 +2230,7 @@ ipa_write_summaries (void)
     {
       struct cgraph_node *node = order[i];
 
-      if (node->analyzed)
+      if (cgraph_function_with_gimple_body_p (node))
        {
          /* When streaming out references to statements as part of some IPA
             pass summary, the statements need to have uids assigned and the
@@ -1718,12 +2243,12 @@ ipa_write_summaries (void)
          pop_cfun ();
        }
       if (node->analyzed)
-       cgraph_node_set_add (set, node);
+        cgraph_node_set_add (set, node);
     }
   vset = varpool_node_set_new ();
 
   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
-    if (vnode->needed && !vnode->alias)
+    if (vnode->needed && (!vnode->alias || vnode->alias_of))
       varpool_node_set_add (vset, vnode);
 
   ipa_write_summaries_1 (set, vset);
@@ -2036,7 +2561,7 @@ function_called_by_processed_nodes_p (void)
     {
       if (e->caller->decl == current_function_decl)
         continue;
-      if (!e->caller->analyzed)
+      if (!cgraph_function_with_gimple_body_p (e->caller))
         continue;
       if (TREE_ASM_WRITTEN (e->caller->decl))
         continue;