diff mbox

Fix cgraph verification (PR middle-end/51929)

Message ID 20120210142507.GA18768@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 10, 2012, 2:25 p.m. UTC
Hi!

As discussed in the PR, this is a verification ICE if a call stmt
calls a same_body_alias (__comp_ctor) and IPA-CP decides to clone the
ctor, it clones the function with the body (__base_ctor), but
before the call stmts are updated, the checking fails because
the clone isn't clone or former clone of the called function,
but its alias.

Fixed by adjusting the verifier, bootstrapped/regtested on x86_64-linux
and i686-linux, ok for trunk?

2012-02-10  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/51929
	* cgraphunit.c (verify_edge_corresponds_to_fndecl): If node is
	a same_body_alias, also test whether e->callee isn't a former
	or current clone of the decl this is a same body alias of.
	(verify_cgraph_node): Fix a typo in error message.

	* g++.dg/ipa/pr51929.C: New test.


	Jakub

Comments

Jason Merrill Feb. 14, 2012, 7:12 p.m. UTC | #1
On 02/10/2012 06:25 AM, Jakub Jelinek wrote:
> 	PR middle-end/51929
> 	* cgraphunit.c (verify_edge_corresponds_to_fndecl): If node is
> 	a same_body_alias, also test whether e->callee isn't a former
> 	or current clone of the decl this is a same body alias of.

Do we want a similar change to the use of former_clone_of in 
cgraph_update_edges_for_call_stmt_node?  Maybe we should wrap the 
former_clone_of checking in a function to make that simpler.

Jason
Jakub Jelinek Feb. 14, 2012, 7:49 p.m. UTC | #2
On Tue, Feb 14, 2012 at 11:12:31AM -0800, Jason Merrill wrote:
> On 02/10/2012 06:25 AM, Jakub Jelinek wrote:
> >	PR middle-end/51929
> >	* cgraphunit.c (verify_edge_corresponds_to_fndecl): If node is
> >	a same_body_alias, also test whether e->callee isn't a former
> >	or current clone of the decl this is a same body alias of.
> 
> Do we want a similar change to the use of former_clone_of in
> cgraph_update_edges_for_call_stmt_node?  Maybe we should wrap the

I don't think so.  new_call in that case is what we are changing the
call to, and we should never change some call into a call to same body alias
function, calls to same body alias functions should be just those that
haven't been changed yet.

> former_clone_of checking in a function to make that simpler.

	Jakub
Jason Merrill Feb. 14, 2012, 8:23 p.m. UTC | #3
On 02/14/2012 11:49 AM, Jakub Jelinek wrote:
>> Do we want a similar change to the use of former_clone_of in
>> cgraph_update_edges_for_call_stmt_node?
>
> I don't think so.

Then let's say the patch is OK tomorrow unless Jan objects today.

Jason
Jan Hubicka Feb. 17, 2012, 2:56 p.m. UTC | #4
> On Tue, Feb 14, 2012 at 11:12:31AM -0800, Jason Merrill wrote:
> > On 02/10/2012 06:25 AM, Jakub Jelinek wrote:
> > >	PR middle-end/51929
> > >	* cgraphunit.c (verify_edge_corresponds_to_fndecl): If node is
> > >	a same_body_alias, also test whether e->callee isn't a former
> > >	or current clone of the decl this is a same body alias of.
> > 
> > Do we want a similar change to the use of former_clone_of in
> > cgraph_update_edges_for_call_stmt_node?  Maybe we should wrap the
> 
> I don't think so.  new_call in that case is what we are changing the
> call to, and we should never change some call into a call to same body alias
> function, calls to same body alias functions should be just those that
> haven't been changed yet.

Yes, I think cgraph_update_edges_for_call_stmt_node is fine here.
I am not sure how long we will be able to maintain the edges sanity check.
It is useful, but as we start doing more and more involved redirections we
may need to disable it eventually.

Honza
> 
> > former_clone_of checking in a function to make that simpler.
> 
> 	Jakub
diff mbox

Patch

--- gcc/cgraphunit.c.jj	2012-02-03 13:31:41.000000000 +0100
+++ gcc/cgraphunit.c	2012-02-10 12:35:44.682099203 +0100
@@ -471,11 +471,17 @@  verify_edge_corresponds_to_fndecl (struc
     return false;
   node = cgraph_function_or_thunk_node (node, NULL);
 
-  if ((e->callee->former_clone_of != node->decl)
+  if ((e->callee->former_clone_of != node->decl
+       && (!node->same_body_alias
+	   || e->callee->former_clone_of != node->thunk.alias))
       /* IPA-CP sometimes redirect edge to clone and then back to the former
-	 function.  This ping-pong has to go, eventaully.  */
+	 function.  This ping-pong has to go, eventually.  */
       && (node != cgraph_function_or_thunk_node (e->callee, NULL))
-      && !clone_of_p (node, e->callee))
+      && !clone_of_p (node, e->callee)
+      /* If decl is a same body alias of some other decl, allow e->callee to be
+	 a clone of a clone of that other decl too.  */
+      && (!node->same_body_alias
+	  || !clone_of_p (cgraph_get_node (node->thunk.alias), e->callee)))
     return true;
   else
     return false;
@@ -667,7 +673,7 @@  verify_cgraph_node (struct cgraph_node *
       for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
 	if (ref->use != IPA_REF_ALIAS)
 	  {
-	    error ("Alias has non-alias refernece");
+	    error ("Alias has non-alias reference");
 	    error_found = true;
 	  }
 	else if (ref_found)
--- gcc/testsuite/g++.dg/ipa/pr51929.C.jj	2012-02-10 12:36:55.792748549 +0100
+++ gcc/testsuite/g++.dg/ipa/pr51929.C	2012-02-09 19:42:10.000000000 +0100
@@ -0,0 +1,32 @@ 
+// PR middle-end/51929
+// { dg-do compile }
+// { dg-options "-O -fno-guess-branch-probability -fipa-cp -fipa-cp-clone --param=max-inline-insns-single=25" }
+
+struct A
+{
+  A (A, unsigned);
+  A (const char *);
+  ~A () { a1 (a4 ()); }
+  void a1 (int);
+  unsigned a2 ();
+  char *a3 ();
+  int a4 ();
+};
+
+template <typename T>
+struct B
+{
+  A b;
+  B (A x, int y = 1) : b (x.a3 (), x.a2 ()) { if (y & 1) b.a2 (); }
+};
+
+extern template struct B <char>;
+A a1 ("foo"), a2 ("bar");
+B<char> b1 (a1), b2 (a2, 8);
+
+void
+foo ()
+{
+  A a3 ("baz");
+  B<char> b3 (a1), b4 (a3);
+}