Cleanup call_stmt_cannot_inline_p wrt inline_failed

Jan Hubicka hubicka@ucw.cz
Tue May 3 18:10:00 GMT 2016


Hi,
call_stmt_cannot_inline_p ultimately translated into setting inline_failed
to CIF_MISMATCHED_ARGUMENTS. This is not always accurate because the flag
is set for multiple reasons.  THis patch makes it possible to simply set
inline_failed to any of the CIF_FATAL_ERROR codes and inliner won't try to
inline it.  THis makes call_stmt_cannot_inline_p more or less redundant,
but I kept for for a time being because it is currently used by ipa propagation,
too.  I will try to untangle this incrementally.

With this patch at least the inline_failed reason is correct for thunks
and other cases.

Bootstrapped/regtested x86_64-linux, will commit it after further testing
on Firefox.

Honza

	* cgraph.c (symbol_table::create_edge): Set inline_failed.
	(cgraph_edge::make_direct): Likewise.
	(cgraph_edge::dump_edge_flags): Dump call_stmt_cannot_inline_p.
	* cgraphclones.c (duplicate_thunk_for_node): Set inline_failed.
	* cif-code.def (CIF_LTO_MISMATCHED_DECLARATIONS): New code
	(CIF_THUNK): New code.
	* ipa-inline-analysis.c (initialize_inline_failed): Preserve
	CIF_FINAL_ERROR codes; do not deal with call_stmt_cannot_inline_p.
	(compute_inline_parameters): Set inline_failed for thunks.
	(inline_analyze_function): Cleanup.
	* ipa-inline.c (can_inline_edge_p): Do not deal with
	call_stmt_cannot_inline_p.
	(can_early_inline_edge_p): Likewise.
	(early_inliner): Initialize inline_failed.
	* lto-cgraph.c (lto_output_edge): Sanity check inline_failed.

	* lto-symtab.c (lto_cgraph_replace_node): Initialize inline_failed.
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 235830)
+++ cgraph.c	(working copy)
@@ -859,9 +859,15 @@ symbol_table::create_edge (cgraph_node *
       && callee && callee->decl
       && !gimple_check_call_matching_types (call_stmt, callee->decl,
 					    false))
-    edge->call_stmt_cannot_inline_p = true;
+    {
+      edge->inline_failed = CIF_MISMATCHED_ARGUMENTS;
+      edge->call_stmt_cannot_inline_p = true;
+    }
   else
-    edge->call_stmt_cannot_inline_p = false;
+    {
+      edge->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+      edge->call_stmt_cannot_inline_p = false;
+    }
 
   edge->indirect_info = NULL;
   edge->indirect_inlining_edge = 0;
@@ -1240,10 +1246,12 @@ cgraph_edge::make_direct (cgraph_node *c
   /* Insert to callers list of the new callee.  */
   edge->set_callee (callee);
 
-  if (call_stmt)
-    call_stmt_cannot_inline_p
-      = !gimple_check_call_matching_types (call_stmt, callee->decl,
-					   false);
+  if (call_stmt
+      && !gimple_check_call_matching_types (call_stmt, callee->decl, false))
+    {
+      call_stmt_cannot_inline_p = true;
+      inline_failed = CIF_MISMATCHED_ARGUMENTS;
+    }
 
   /* We need to re-determine the inlining status of the edge.  */
   initialize_inline_failed (edge);
@@ -1996,6 +2004,8 @@ cgraph_edge::dump_edge_flags (FILE *f)
     fprintf (f, "(speculative) ");
   if (!inline_failed)
     fprintf (f, "(inlined) ");
+  if (call_stmt_cannot_inline_p)
+    fprintf (f, "(call_stmt_cannot_inline_p) ");
   if (indirect_inlining_edge)
     fprintf (f, "(indirect_inlining) ");
   if (count)
Index: cgraphclones.c
===================================================================
--- cgraphclones.c	(revision 235830)
+++ cgraphclones.c	(working copy)
@@ -338,6 +338,7 @@ duplicate_thunk_for_node (cgraph_node *t
   cgraph_edge *e = new_thunk->create_edge (node, NULL, 0,
 						  CGRAPH_FREQ_BASE);
   e->call_stmt_cannot_inline_p = true;
+  e->inline_failed = CIF_THUNK;
   symtab->call_edge_duplication_hooks (thunk->callees, e);
   symtab->call_cgraph_duplication_hooks (thunk, new_thunk);
   return new_thunk;
Index: cif-code.def
===================================================================
--- cif-code.def	(revision 235830)
+++ cif-code.def	(working copy)
@@ -92,8 +92,12 @@ DEFCIFCODE(MISMATCHED_ARGUMENTS, CIF_FIN
 	   N_("mismatched arguments"))
 
 /* Caller and callee disagree on the arguments.  */
-DEFCIFCODE(THUNK, CIF_FINAL_ERROR,
-	   N_("thunk call"))
+DEFCIFCODE(LTO_MISMATCHED_DECLARATIONS, CIF_FINAL_ERROR,
+	   N_("mismatched declarations during linktime optimization"))
+
+/* Caller is thunk.  */
+DEFCIFCODE(THUNK, CIF_FINAL_ERROR,                                             
+          N_("thunk call"))                                                    
 
 /* Call was originally indirect.  */
 DEFCIFCODE(ORIGINALLY_INDIRECT_CALL, CIF_FINAL_NORMAL,
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c	(revision 235830)
+++ ipa-inline-analysis.c	(working copy)
@@ -1490,19 +1490,23 @@ initialize_inline_failed (struct cgraph_
 {
   struct cgraph_node *callee = e->callee;
 
-  if (e->indirect_unknown_callee)
+  if (e->inline_failed && e->inline_failed != CIF_BODY_NOT_AVAILABLE
+      && cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+    ;
+  else if (e->indirect_unknown_callee)
     e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
   else if (!callee->definition)
     e->inline_failed = CIF_BODY_NOT_AVAILABLE;
   else if (callee->local.redefined_extern_inline)
     e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
-  else if (e->call_stmt_cannot_inline_p)
-    e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
   else if (cfun && fn_contains_cilk_spawn_p (cfun))
     /* We can't inline if the function is spawing a function.  */
-    e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
+    e->inline_failed = CIF_CILK_SPAWN;
   else
     e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+  gcc_checking_assert (!e->call_stmt_cannot_inline_p
+		       || cgraph_inline_failed_type (e->inline_failed)
+			    == CIF_FINAL_ERROR);
 }
 
 /* Callback of walk_aliased_vdefs.  Flags that it has been invoked to the
@@ -2925,7 +2929,7 @@ compute_inline_parameters (struct cgraph
       struct predicate t = true_predicate ();
 
       info->inlinable = 0;
-      node->callees->call_stmt_cannot_inline_p = true;
+      node->callees->inline_failed = CIF_THUNK;
       node->local.can_change_signature = false;
       es->call_stmt_time = 1;
       es->call_stmt_size = 1;
@@ -4107,17 +4111,9 @@ inline_analyze_function (struct cgraph_n
     {
       struct cgraph_edge *e;
       for (e = node->callees; e; e = e->next_callee)
-	{
-	  if (e->inline_failed == CIF_FUNCTION_NOT_CONSIDERED)
-	    e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
-	  e->call_stmt_cannot_inline_p = true;
-	}
+	e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
       for (e = node->indirect_calls; e; e = e->next_callee)
-	{
-	  if (e->inline_failed == CIF_FUNCTION_NOT_CONSIDERED)
-	    e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
-	  e->call_stmt_cannot_inline_p = true;
-	}
+	e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
     }
 
   pop_cfun ();
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 235830)
+++ ipa-inline.c	(working copy)
@@ -335,12 +335,10 @@ can_inline_edge_p (struct cgraph_edge *e
       e->inline_failed = CIF_OVERWRITABLE;
       inlinable = false;
     }
+  /* All edges with call_stmt_cannot_inline_p should have inline_failed
+     initialized to one of FINAL_ERROR reasons.  */
   else if (e->call_stmt_cannot_inline_p)
-    {
-      if (e->inline_failed != CIF_FUNCTION_NOT_OPTIMIZED)
-        e->inline_failed = e->caller->thunk.thunk_p ? CIF_THUNK : CIF_MISMATCHED_ARGUMENTS;
-      inlinable = false;
-    }
+    gcc_unreachable ();
   /* Don't inline if the functions have different EH personalities.  */
   else if (DECL_FUNCTION_PERSONALITY (caller->decl)
 	   && DECL_FUNCTION_PERSONALITY (callee->decl)
@@ -529,6 +527,8 @@ can_early_inline_edge_p (struct cgraph_e
   /* Early inliner might get called at WPA stage when IPA pass adds new
      function.  In this case we can not really do any of early inlining
      because function bodies are missing.  */
+  if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+    return false;
   if (!gimple_has_body_p (callee->decl))
     {
       e->inline_failed = CIF_BODY_NOT_AVAILABLE;
@@ -2741,7 +2741,10 @@ early_inliner (function *fun)
 	      if (edge->callee->decl
 		  && !gimple_check_call_matching_types (
 		      edge->call_stmt, edge->callee->decl, false))
-		edge->call_stmt_cannot_inline_p = true;
+		{
+ 		  edge->inline_failed = CIF_MISMATCHED_ARGUMENTS;
+		  edge->call_stmt_cannot_inline_p = true;
+		}
 	    }
 	  if (iterations < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS) - 1)
 	    inline_update_overall_summary (node);
Index: lto/lto-symtab.c
===================================================================
--- lto/lto-symtab.c	(revision 235830)
+++ lto/lto-symtab.c	(working copy)
@@ -81,7 +81,10 @@ lto_cgraph_replace_node (struct cgraph_n
 	 ???  We really need a way to match function signatures for ABI
 	 compatibility and perform related promotions at inlining time.  */
       if (!compatible_p)
-	e->call_stmt_cannot_inline_p = 1;
+	{
+	  e->inline_failed = CIF_LTO_MISMATCHED_DECLARATIONS;
+	  e->call_stmt_cannot_inline_p = 1;
+	}
     }
   /* Redirect incomming references.  */
   prevailing_node->clone_referring (node);
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 235830)
+++ lto-cgraph.c	(working copy)
@@ -268,6 +268,8 @@ lto_output_edge (struct lto_simple_outpu
   bp_pack_value (&bp, edge->indirect_inlining_edge, 1);
   bp_pack_value (&bp, edge->speculative, 1);
   bp_pack_value (&bp, edge->call_stmt_cannot_inline_p, 1);
+  gcc_assert (!edge->call_stmt_cannot_inline_p
+	      || edge->inline_failed != CIF_BODY_NOT_AVAILABLE);
   bp_pack_value (&bp, edge->can_throw_external, 1);
   bp_pack_value (&bp, edge->in_polymorphic_cdtor, 1);
   if (edge->indirect_unknown_callee)



More information about the Gcc-patches mailing list