Hi,
this patch sanifies placement of symtab_remove_unreachable_nodes.  First is a
confussion about early local passes.  THe superpass TODO contains
symtab_remove_unreachable_nodes that is intended to run after local passes but
PM executes it before (because subpasses are run after TODOs). This is supposed
to be handled in cgraphunit.c but these days it is too late, because we do have
small IPA passes run after local cleanups (profiling, pass_ipa_tm etc.). This
makes these passes to process about 200K extra functions on firefox.

symtab_remove_unreachable_nodes takes parameter whether it is run before or
after inlining.  This parameter is wrong at couple times, so I fixed it too.
Incrementally I plan to make this part of cgraph_state as theparameter is
clearly confusing and hard to maintain.

Bootstrapped/regtested x86_64-linux.

        * cgraphunit.c (ipa_passes, compile): Reshedule
        symtab_remove_unreachable_nodes passes; update comments.
        * ipa-inline.c (pass_data_ipa_inline): Do not schedule
        TODO_remove_functions before the pass; the functions ought to be
        already removed.
        * ipa.c (pass_data_ipa_free_inline_summary): Enable dump; schedule
        TODO_remove_functions.
        * passes.c (pass_data_early_local_passes): Do not schedule function
        removal.
        (execute_one_pass): Fix call of symtab_remove_unreachable_nodes.

        * lto.c (read_cgraph_and_symbols): Fix symtab_remove_unreachable_nodes
        call.
        (do_whole_program_analysis): Only sanity check that IPA passes cleans 
up.

        * testsuite/g++.dg/ipa/devirt-17.C: Update template.
        * testsuite/g++.dg/ipa/devirt-16.C: Update template.
Index: cgraphunit.c
===================================================================
--- cgraphunit.c        (revision 214193)
+++ cgraphunit.c        (working copy)
@@ -2047,10 +2047,6 @@ ipa_passes (void)
        return;
     }
 
-  /* We never run removal of unreachable nodes after early passes.  This is
-     because TODO is run before the subpasses.  It is important to remove
-     the unreachable functions to save works at IPA level and to get LTO
-     symbol tables right.  */
   symtab_remove_unreachable_nodes (true, cgraph_dump_file);
 
   /* If pass_all_early_optimizations was not scheduled, the state of
@@ -2184,7 +2180,8 @@ compile (void)
     }
 
   /* This pass remove bodies of extern inline functions we never inlined.
-     Do this later so other IPA passes see what is really going on.  */
+     Do this later so other IPA passes see what is really going on.
+     FIXME: THis should be run just after inlining by pasmanager.  */
   symtab_remove_unreachable_nodes (false, dump_file);
   cgraph_global_info_ready = true;
   if (cgraph_dump_file)
@@ -2210,9 +2207,10 @@ compile (void)
   cgraph_materialize_all_clones ();
   bitmap_obstack_initialize (NULL);
   execute_ipa_pass_list (g->get_passes ()->all_late_ipa_passes);
-  symtab_remove_unreachable_nodes (true, dump_file);
 #ifdef ENABLE_CHECKING
   symtab_node::verify_symtab_nodes ();
+  /* Verify late IPA passes cleaned up after themselves.  */
+  gcc_assert (!symtab_remove_unreachable_nodes (false, dump_file));
 #endif
   bitmap_obstack_release (NULL);
   mark_functions_to_output ();
Index: testsuite/g++.dg/ipa/devirt-16.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-16.C    (revision 214193)
+++ testsuite/g++.dg/ipa/devirt-16.C    (working copy)
@@ -32,7 +32,6 @@ main()
   return b->foo();
 }
 
-/* { dg-final { scan-ipa-dump "devirtualizing" "whole-program"} } */
 /* { dg-final { scan-ipa-dump "builtin_unreachable" "whole-program"} } */
 /* { dg-final { scan-ipa-dump-not "A::foo" "whole-program"} } */
 /* { dg-final { scan-ipa-dump-not "A::foo" "whole-program"} } */
Index: testsuite/g++.dg/ipa/devirt-17.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-17.C    (revision 214193)
+++ testsuite/g++.dg/ipa/devirt-17.C    (working copy)
@@ -37,7 +37,6 @@ main()
   return b->foo();
 }
 
-/* { dg-final { scan-ipa-dump "devirtualizing" "whole-program"} } */
 /* { dg-final { scan-ipa-dump-not "builtin_unreachable" "whole-program"} } */
 /* { dg-final { scan-ipa-dump "B::foo" "whole-program"} } */
 /* { dg-final { scan-ipa-dump-not "A::foo" "whole-program"} } */
Index: ipa-inline.c
===================================================================
--- ipa-inline.c        (revision 214193)
+++ ipa-inline.c        (working copy)
@@ -2519,7 +2519,7 @@ const pass_data pass_data_ipa_inline =
   0, /* properties_required */
   0, /* properties_provided */
   0, /* properties_destroyed */
-  TODO_remove_functions, /* todo_flags_start */
+  0, /* todo_flags_start */
   ( TODO_dump_symtab ), /* todo_flags_finish */
 };
 
Index: ipa.c
===================================================================
--- ipa.c       (revision 214193)
+++ ipa.c       (working copy)
@@ -727,14 +727,17 @@ namespace {
 const pass_data pass_data_ipa_free_inline_summary =
 {
   SIMPLE_IPA_PASS, /* type */
-  "*free_inline_summary", /* name */
+  "free-inline-summary", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
   TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
-  0, /* todo_flags_finish */
+  /* Early optimizations may make function unreachable.  We can not
+     remove unreachable functions as part of the ealry opts pass because
+     TODOs are run before subpasses.  Do it here.  */
+  ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
 };
 
 class pass_ipa_free_inline_summary : public simple_ipa_opt_pass
Index: lto/lto.c
===================================================================
--- lto/lto.c   (revision 214193)
+++ lto/lto.c   (working copy)
@@ -3084,10 +3084,10 @@ read_cgraph_and_symbols (unsigned nfiles
       symtab_node::dump_table (cgraph_dump_file);
     }
   lto_symtab_merge_symbols ();
-  /* Removal of unreacable symbols is needed to make verify_symtab to pass;
+  /* Removal of unreachable symbols is needed to make verify_symtab to pass;
      we are still having duplicated comdat groups containing local statics.
      We could also just remove them while merging.  */
-  symtab_remove_unreachable_nodes (false, dump_file);
+  symtab_remove_unreachable_nodes (true, dump_file);
   ggc_collect ();
   cgraph_state = CGRAPH_STATE_IPA_SSA;
 
@@ -3244,7 +3244,10 @@ do_whole_program_analysis (void)
   cgraph_state = CGRAPH_STATE_IPA_SSA;
 
   execute_ipa_pass_list (g->get_passes ()->all_regular_ipa_passes);
-  symtab_remove_unreachable_nodes (false, dump_file);
+#ifdef ENABLE_CHECKING
+  /* Verify that IPA passes cleans up after themselves.  */
+  gcc_assert (!symtab_remove_unreachable_nodes (false, dump_file));
+#endif
 
   if (cgraph_dump_file)
     {
Index: passes.c
===================================================================
--- passes.c    (revision 214193)
+++ passes.c    (working copy)
@@ -350,7 +350,9 @@ const pass_data pass_data_early_local_pa
   0, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
-  TODO_remove_functions, /* todo_flags_finish */
+  /* todo_flags_finish is executed before subpases. For this reason
+     it makes no sense to remove unreachable functions here.  */
+  0, /* todo_flags_finish */
 };
 
 class pass_early_local_passes : public simple_ipa_opt_pass
@@ -2119,7 +2121,7 @@ execute_one_pass (opt_pass *pass)
              }
          }
       if (applied)
-        symtab_remove_unreachable_nodes (true, dump_file);
+        symtab_remove_unreachable_nodes (false, dump_file);
       /* Restore current_pass.  */
       current_pass = pass;
     }

Reply via email to