+2012-08-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR middle-end/53321
+       PR middle-end/53865
+       * ipa-inline-analysis.c (inline_free_summary): Return if
+       inline_edge_summary_vec is NULL.
+
+       * ipa-split.c (execute_split_functions): Check if a function
+       is inlinable only if inline_edge_summary_vec != NULL.
+
+       * ipa.c (symtab_remove_unreachable_nodes): Restore
+       cgraph_propagate_frequency call when something was changed.
+       (free_inline_summary): New function.
+       (pass_ipa_free_inline_summary): New pass.
+
+       * passes.c (init_optimization_passes): Add
+       pass_ipa_free_inline_summary before pass_ipa_tree_profile.
+
+       * timevar.def (TV_IPA_FREE_INLINE_SUMMARY): New.
+
+       * tree-pass.h (pass_ipa_free_inline_summary): New.
+
 2012-08-02  Richard Earnshaw  <rearnsha@arm.com>
 
        * arm.c (arm_gen_constant): Use UBFX for some AND operations when
 
 inline_free_summary (void)
 {
   struct cgraph_node *node;
+  if (inline_edge_summary_vec == NULL)
+    return;
   FOR_EACH_DEFINED_FUNCTION (node)
     reset_inline_summary (node);
   if (function_insertion_hook_holder)
 
     }
   /* This can be relaxed; function might become inlinable after splitting
      away the uninlinable part.  */
-  if (!inline_summary (node)->inlinable)
+  if (inline_edge_summary_vec && !inline_summary (node)->inlinable)
     {
       if (dump_file)
        fprintf (dump_file, "Not splitting: not inlinable.\n");
 
   verify_symtab ();
 #endif
 
+  /* If we removed something, perhaps profile could be improved.  */
+  if (changed && optimize && inline_edge_summary_vec)
+    FOR_EACH_DEFINED_FUNCTION (node)
+      cgraph_propagate_frequency (node);
+
   return changed;
 }
 
  }
 };
 
+/* Free inline summary.  */
+
+static unsigned
+free_inline_summary (void)
+{
+  inline_free_summary ();
+  return 0;
+}
+
+struct simple_ipa_opt_pass pass_ipa_free_inline_summary =
+{
+ {
+  SIMPLE_IPA_PASS,
+  "*free_inline_summary",              /* name */
+  NULL,                                        /* gate */
+  free_inline_summary,                 /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_IPA_FREE_INLINE_SUMMARY,          /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_ggc_collect                     /* todo_flags_finish */
+ }
+};
+
 /* Do not re-run on ltrans stage.  */
 
 static bool
 
       NEXT_PASS (pass_rebuild_cgraph_edges);
       NEXT_PASS (pass_inline_parameters);
     }
+  NEXT_PASS (pass_ipa_free_inline_summary);
   NEXT_PASS (pass_ipa_tree_profile);
     {
       struct opt_pass **p = &pass_ipa_tree_profile.pass.sub;
 
 DEFTIMEVAR (TV_IPA_PTA               , "ipa points-to")
 DEFTIMEVAR (TV_IPA_SRA               , "ipa SRA")
 DEFTIMEVAR (TV_IPA_FREE_LANG_DATA    , "ipa free lang data")
+DEFTIMEVAR (TV_IPA_FREE_INLINE_SUMMARY, "ipa free inline summary")
 /* Time spent by constructing CFG.  */
 DEFTIMEVAR (TV_CFG                   , "cfg construction")
 /* Time spent by cleaning up CFG.  */
 
 extern struct simple_ipa_opt_pass pass_ipa_matrix_reorg;
 extern struct ipa_opt_pass_d pass_ipa_inline;
 extern struct simple_ipa_opt_pass pass_ipa_free_lang_data;
+extern struct simple_ipa_opt_pass pass_ipa_free_inline_summary;
 extern struct ipa_opt_pass_d pass_ipa_cp;
 extern struct ipa_opt_pass_d pass_ipa_reference;
 extern struct ipa_opt_pass_d pass_ipa_pure_const;