Patchwork Fix cgraph_redirect_edge_call_stmt_to_callee

login
register
mail settings
Submitter Jan Hubicka
Date Aug. 26, 2013, 3:36 p.m.
Message ID <20130826153640.GC25893@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/269912/
State New
Headers show

Comments

Jan Hubicka - Aug. 26, 2013, 3:36 p.m.
Hi,
this patch fixes interesting problem in cgraph_redirect_edge_call_stmt_to_callee.
Before expanding the speculative call we do type checking ensuring that type of callee
is compatible with a call.  This fails when ipa-cp decides to redirect the call and
change function signature, because the call type is not updated yet.  We need
to compare with type of function we have in reference (that is original function
before ipa-cp change).

This allows us to do 400 more speculative calls on firefox. Still 10 of them fail
for reasons I do not quite understand and will try to debug next.

Bootstrapped/regtested x86_64-linux, comitted.

Honza

Patch

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 201998)
+++ ChangeLog	(working copy)
@@ -1,5 +1,11 @@ 
 2013-08-26  Jan Hubicka  <jh@suse.cz>
 
+	* cgraph.c (cgraph_redirect_edge_call_stmt_to_callee): Fix formatting;
+	fix edge count/frequency when speculation failed; fix type check
+	for the direct call.
+
+2013-08-26  Jan Hubicka  <jh@suse.cz>
+
 	* ipa-prop.c (ipa_print_node_params): Do not ICE during WPA.
 
 2013-08-26  Jan Hubicka  <jh@suse.cz>
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 201996)
+++ cgraph.c	(working copy)
@@ -1306,29 +1306,44 @@  cgraph_redirect_edge_call_stmt_to_callee
       struct ipa_ref *ref;
 
       cgraph_speculative_call_info (e, e, e2, ref);
-      /* If there already is an direct call (i.e. as a result of inliner's substitution),
- 	 forget about speculating.  */
+      /* If there already is an direct call (i.e. as a result of inliner's
+	 substitution), forget about speculating.  */
       if (decl)
 	e = cgraph_resolve_speculation (e, decl);
-      /* If types do not match, speculation was likely wrong.  */
-      else if (!gimple_check_call_matching_types (e->call_stmt, e->callee->symbol.decl,
+      /* If types do not match, speculation was likely wrong. 
+         The direct edge was posisbly redirected to the clone with a different
+	 signature.  We did not update the call statement yet, so compare it 
+	 with the reference that still points to the proper type.  */
+      else if (!gimple_check_call_matching_types (e->call_stmt,
+						  ref->referred->symbol.decl,
 						  true))
 	{
 	  if (dump_file)
 	    fprintf (dump_file, "Not expanding speculative call of %s/%i -> %s/%i\n"
 		     "Type mismatch.\n",
-		     xstrdup (cgraph_node_name (e->caller)), e->caller->symbol.order,
-		     xstrdup (cgraph_node_name (e->callee)), e->callee->symbol.order);
+		     xstrdup (cgraph_node_name (e->caller)),
+		     e->caller->symbol.order,
+		     xstrdup (cgraph_node_name (e->callee)),
+		     e->callee->symbol.order);
 	  e = cgraph_resolve_speculation (e, NULL);
+	  /* We are producing the final function body and will throw away the
+	     callgraph edges really soon.  Reset the counts/frequencies to
+	     keep verifier happy in the case of roundoff errors.  */
+	  e->count = gimple_bb (e->call_stmt)->count;
+	  e->frequency = compute_call_stmt_bb_frequency
+			  (e->caller->symbol.decl, gimple_bb (e->call_stmt));
 	}
       /* Expand speculation into GIMPLE code.  */
       else
 	{
 	  if (dump_file)
-	    fprintf (dump_file, "Expanding speculative call of %s/%i -> %s/%i count:"
+	    fprintf (dump_file,
+		     "Expanding speculative call of %s/%i -> %s/%i count:"
 		     HOST_WIDEST_INT_PRINT_DEC"\n",
-		     xstrdup (cgraph_node_name (e->caller)), e->caller->symbol.order,
-		     xstrdup (cgraph_node_name (e->callee)), e->callee->symbol.order,
+		     xstrdup (cgraph_node_name (e->caller)),
+		     e->caller->symbol.order,
+		     xstrdup (cgraph_node_name (e->callee)),
+		     e->callee->symbol.order,
 		     (HOST_WIDEST_INT)e->count);
 	  gcc_assert (e2->speculative);
 	  push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
@@ -1342,11 +1357,12 @@  cgraph_redirect_edge_call_stmt_to_callee
 				: REG_BR_PROB_BASE / 2,
 				e->count, e->count + e2->count);
 	  e->speculative = false;
-	  cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt, false);
-	  e->frequency = compute_call_stmt_bb_frequency (e->caller->symbol.decl,
-							 gimple_bb (e->call_stmt));
-	  e2->frequency = compute_call_stmt_bb_frequency (e2->caller->symbol.decl,
-							  gimple_bb (e2->call_stmt));
+	  cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt,
+						 new_stmt, false);
+	  e->frequency = compute_call_stmt_bb_frequency
+			   (e->caller->symbol.decl, gimple_bb (e->call_stmt));
+	  e2->frequency = compute_call_stmt_bb_frequency
+			   (e2->caller->symbol.decl, gimple_bb (e2->call_stmt));
 	  e2->speculative = false;
 	  ref->speculative = false;
 	  ref->stmt = NULL;