[PATCH] Remove unreachable nodes before IPA profile pass (PR ipa/87706).

Jan Hubicka hubicka@ucw.cz
Tue Nov 20 13:18:00 GMT 2018


> Hi.
> 
> In order to fix the warnings mentioned in the PR, we need
> to run remove_unreachable_nodes after early tree passes. That's
> however possible only within a IPA pass. Thus I'm calling that
> before the profile PASS.
> 
> Patch survives regression tests on ppc64le-linux-gnu and majority
> of warnings are gone in profiledbootstrap.
> 
> Ready for trunk?
> Thanks,
> Martin
> 
> gcc/ChangeLog:
> 
> 2018-11-08  Martin Liska  <mliska@suse.cz>
> 
> 	* tree-profile.c: Run TODO_remove_functions before "profile"
> 	pass in order to remove dead functions that will trigger
> 	-Wmissing-profile.

Hi,
it turns out there are few bugs on the way.  First ipa.c has incomplete
tests on when it needs to keep the functions. Also the function remval
is actually scheduled in fnsummary1 pass that just run bit late because
post-profile function splitting needs it.

This is variant I ended up testing.  My original plan to do it at the
end of the early passes ipa pass did not fly because TODOs are run
before subpasses (as already commented in ipa-fnsummary.c. So I ended up
splitting ipa_fnsummary into two mini-passes.

Bootstrapped/regtested x86_64-linux, plan to commit it shortly.

Honza

	* ipa-fnsummary.c (pass_ipa_fnsummary): Do not remove functions
	* ipa.c (possible_inline_candidate_p): Break out from ..
	(process_references): ... here ; drop before_inlining_p;
	cleanup handling of alises.
	(walk_polymorphic_call_targets): Likewise.
	(symbol_table::remove_unreachable_nodes): Likewise.
	* passes.c (pass_data_ipa_remove_symbols): New structure.
	(pass_ipa_remove_symbols): New pass.
	(make_pass_ipa_remove_symbols): New functoin.
	* passes.def (pass_ipa_remove_symbols): Schedule after early passes.
Index: ipa-fnsummary.c
===================================================================
--- ipa-fnsummary.c	(revision 266288)
+++ ipa-fnsummary.c	(working copy)
@@ -3563,10 +3563,7 @@ public:
   virtual unsigned int execute (function *)
     {
       ipa_free_fn_summary ();
-      /* Early optimizations may make function unreachable.  We can not
-	 remove unreachable functions as part of the early opts pass because
-	 TODOs are run before subpasses.  Do it here.  */
-      return small_p ? TODO_remove_functions | TODO_dump_symtab : 0;
+      return 0;
     }
 
 private:
Index: ipa.c
===================================================================
--- ipa.c	(revision 266288)
+++ ipa.c	(working copy)
@@ -101,12 +101,32 @@ enqueue_node (symtab_node *node, symtab_
   *first = node;
 }
 
+/* Return true if NODE may get inlined later.
+   This is used to keep DECL_EXTERNAL function bodies around long enough
+   so inliner can proces them.  */
+
+static bool
+possible_inline_candidate_p (symtab_node *node)
+{
+  if (symtab->state >= IPA_SSA_AFTER_INLINING)
+    return false;
+  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
+  if (!cnode)
+    return false;
+  if (DECL_UNINLINABLE (cnode->decl))
+    return false;
+  if (opt_for_fn (cnode->decl, optimize))
+    return true;
+  if (symtab->state >= IPA_SSA)
+    return false;
+  return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
+}
+
 /* Process references.  */
 
 static void
 process_references (symtab_node *snode,
 		    symtab_node **first,
-		    bool before_inlining_p,
 		    hash_set<symtab_node *> *reachable)
 {
   int i;
@@ -118,14 +138,7 @@ process_references (symtab_node *snode,
 
       if (node->definition && !node->in_other_partition
 	  && ((!DECL_EXTERNAL (node->decl) || node->alias)
-	      || (((before_inlining_p
-		    && (TREE_CODE (node->decl) != FUNCTION_DECL
-			|| (TREE_CODE (node->decl) == FUNCTION_DECL
-			    && opt_for_fn (body->decl, optimize))
-		        || (symtab->state < IPA_SSA
-		            && lookup_attribute
-				 ("always_inline",
-			          DECL_ATTRIBUTES (body->decl))))))
+	      || (possible_inline_candidate_p (node)
 		  /* We use variable constructors during late compilation for
 		     constant folding.  Keep references alive so partitioning
 		     knows about potential references.  */
@@ -140,7 +153,7 @@ process_references (symtab_node *snode,
 	     body.  */
 	  if (DECL_EXTERNAL (node->decl)
 	      && node->alias
-	      && before_inlining_p)
+	      && symtab->state < IPA_SSA_AFTER_INLINING)
 	    reachable->add (body);
 	  reachable->add (node);
 	}
@@ -160,8 +173,7 @@ static void
 walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
 			       struct cgraph_edge *edge,
 			       symtab_node **first,
-			       hash_set<symtab_node *> *reachable,
-			       bool before_inlining_p)
+			       hash_set<symtab_node *> *reachable)
 {
   unsigned int i;
   void *cache_token;
@@ -190,15 +202,14 @@ walk_polymorphic_call_targets (hash_set<
 	  /* Prior inlining, keep alive bodies of possible targets for
 	     devirtualization.  */
 	  if (n->definition
-	      && (before_inlining_p
-		  && opt_for_fn (body->decl, optimize)
+	      && (possible_inline_candidate_p (body)
 		  && opt_for_fn (body->decl, flag_devirtualize)))
 	     {
 		/* Be sure that we will not optimize out alias target
 		   body.  */
 		if (DECL_EXTERNAL (n->decl)
 		    && n->alias
-		    && before_inlining_p)
+		    && symtab->state < IPA_SSA_AFTER_INLINING)
 		  reachable->add (body);
 	       reachable->add (n);
 	     }
@@ -303,8 +314,6 @@ symbol_table::remove_unreachable_nodes (
   hash_set<symtab_node *> reachable;
   hash_set<tree> body_needed_for_clonning;
   hash_set<void *> reachable_call_targets;
-  bool before_inlining_p = symtab->state < (!optimize && !in_lto_p ? IPA_SSA
-					    : IPA_SSA_AFTER_INLINING);
 
   timevar_push (TV_IPA_UNREACHABLE);
   build_type_inheritance_graph ();
@@ -396,7 +405,7 @@ symbol_table::remove_unreachable_nodes (
 		  enqueue_node (next, &first, &reachable);
 	    }
 	  /* Mark references as reachable.  */
-	  process_references (node, &first, before_inlining_p, &reachable);
+	  process_references (node, &first, &reachable);
 	}
 
       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
@@ -416,8 +425,7 @@ symbol_table::remove_unreachable_nodes (
 		      next = e->next_callee;
 		      if (e->indirect_info->polymorphic)
 			walk_polymorphic_call_targets (&reachable_call_targets,
-						       e, &first, &reachable,
-						       before_inlining_p);
+						       e, &first, &reachable);
 		    }
 		}
 	      for (e = cnode->callees; e; e = e->next_callee)
@@ -428,18 +436,13 @@ symbol_table::remove_unreachable_nodes (
 		      && (!e->inline_failed
 			  || !DECL_EXTERNAL (e->callee->decl)
 			  || e->callee->alias
-			  || (before_inlining_p
-			      && (opt_for_fn (body->decl, optimize)
-		                  || (symtab->state < IPA_SSA
-		                      && lookup_attribute
-				          ("always_inline",
-				           DECL_ATTRIBUTES (body->decl)))))))
+			  || possible_inline_candidate_p (e->callee)))
 		    {
 		      /* Be sure that we will not optimize out alias target
 			 body.  */
 		      if (DECL_EXTERNAL (e->callee->decl)
 			  && e->callee->alias
-			  && before_inlining_p)
+			  && symtab->state < IPA_SSA_AFTER_INLINING)
 			reachable.add (body);
 		      reachable.add (e->callee);
 		    }
@@ -654,7 +657,7 @@ symbol_table::remove_unreachable_nodes (
 		   of possible later devirtualization.  Do not mark them as
 		   local too early so we won't optimize them out before
 		   we are done with polymorphic call analysis.  */
-		&& (!before_inlining_p
+		&& (symtab->state >= IPA_SSA_AFTER_INLINING
 		    || !node->call_for_symbol_and_aliases
 		       (is_indirect_call_target_p, NULL, true)))
 	      {
Index: passes.c
===================================================================
--- passes.c	(revision 266288)
+++ passes.c	(working copy)
@@ -459,6 +459,35 @@ public:
 
 }; // class pass_local_optimization_passes
 
+const pass_data pass_data_ipa_remove_symbols =
+{
+  SIMPLE_IPA_PASS, /* type */
+  "remove_symbols", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_NONE, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_remove_functions | TODO_dump_symtab, /* todo_flags_finish */
+};
+
+class pass_ipa_remove_symbols : public simple_ipa_opt_pass
+{
+public:
+  pass_ipa_remove_symbols (gcc::context *ctxt)
+    : simple_ipa_opt_pass (pass_data_ipa_remove_symbols, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      /* Don't bother doing anything if the program has errors.  */
+      return (!seen_error () && !in_lto_p);
+    }
+
+}; // class pass_local_optimization_passes
+
 } // anon namespace
 
 simple_ipa_opt_pass *
@@ -473,6 +502,12 @@ make_pass_local_optimization_passes (gcc
   return new pass_local_optimization_passes (ctxt);
 }
 
+simple_ipa_opt_pass *
+make_pass_ipa_remove_symbols (gcc::context *ctxt)
+{
+  return new pass_ipa_remove_symbols (ctxt);
+}
+
 namespace {
 
 const pass_data pass_data_all_early_optimizations =
Index: passes.def
===================================================================
--- passes.def	(revision 266288)
+++ passes.def	(working copy)
@@ -106,6 +106,7 @@ along with GCC; see the file COPYING3.
       NEXT_PASS (pass_local_fn_summary);
   POP_INSERT_PASSES ()
 
+  NEXT_PASS (pass_ipa_remove_symbols);
   NEXT_PASS (pass_ipa_oacc);
   PUSH_INSERT_PASSES_WITHIN (pass_ipa_oacc)
       NEXT_PASS (pass_ipa_pta);
Index: testsuite/gcc.dg/ipa/ctor-empty-1.c
===================================================================
--- testsuite/gcc.dg/ipa/ctor-empty-1.c	(revision 266288)
+++ testsuite/gcc.dg/ipa/ctor-empty-1.c	(working copy)
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
-/* { dg-options "-O3 -c -fdump-ipa-free-fnsummary1"  } */
+/* { dg-options "-O3 -c -fdump-ipa-remove_symbols"  } */
 static __attribute__((constructor))
 void empty_constructor()
 {
 }
-/* { dg-final { scan-ipa-dump "Reclaiming functions: empty_constructor"  "free-fnsummary1"  } } */
+/* { dg-final { scan-ipa-dump "Reclaiming functions: empty_constructor"  "remove_symbols"  } } */



More information about the Gcc-patches mailing list