diff mbox

Make ipa-icf to not prevent devirtualization

Message ID 20160115110148.GC77658@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Jan. 15, 2016, 11:01 a.m. UTC
Hi,
this patch avoid ipa-icf to take away body of a virtual function which is a subject
of later devirtualization.

Bootstrapped/regtested x86_64-linux, comitted.

Honza

	PR ipa/68148
	* ipa-icf.c (sem_function::merge): Virtual functions may become
	reachable even if they address is not taken and there are no
	idrect calls.
	* testsuite/g++.dg/ipa/devirt-49.C: New testcase.

Comments

Richard Biener Jan. 15, 2016, 11:32 a.m. UTC | #1
On Fri, Jan 15, 2016 at 12:01 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this patch avoid ipa-icf to take away body of a virtual function which is a subject
> of later devirtualization.

But isn't can_remove_if_no_direct_alls_p () supposed to return false
then?  (depending
on cgraph state)

Richard.

> Bootstrapped/regtested x86_64-linux, comitted.
>
> Honza
>
>         PR ipa/68148
>         * ipa-icf.c (sem_function::merge): Virtual functions may become
>         reachable even if they address is not taken and there are no
>         idrect calls.
>         * testsuite/g++.dg/ipa/devirt-49.C: New testcase.
>
> Index: ipa-icf.c
> ===================================================================
> --- ipa-icf.c   (revision 232407)
> +++ ipa-icf.c   (working copy)
> @@ -1305,6 +1305,7 @@ sem_function::merge (sem_item *alias_ite
>
>        /* If all callers was redirected, do not produce wrapper.  */
>        if (alias->can_remove_if_no_direct_calls_p ()
> +         && !DECL_VIRTUAL_P (alias->decl)
>           && !alias->has_aliases_p ())
>         {
>           create_wrapper = false;
> Index: testsuite/g++.dg/ipa/devirt-49.C
> ===================================================================
> --- testsuite/g++.dg/ipa/devirt-49.C    (revision 0)
> +++ testsuite/g++.dg/ipa/devirt-49.C    (revision 0)
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-ipa-devirt"  } */
> +struct Interface {
> +  virtual ~Interface() {}
> +  virtual void virtualFunc() = 0;
> +  virtual void virtualFunc2() = 0;
> +};
> +
> +struct Concrete : Interface {
> +  int counter_;
> +  Concrete() : counter_(0) {}
> +  void virtualFunc() { counter_++; }
> +  void virtualFunc2() { counter_++; }
> +};
> +
> +void test(Interface &c) {
> +  c.virtualFunc();
> +  c.virtualFunc2();
> +}
> +/* { dg-final { scan-ipa-dump "2 speculatively devirtualized" "devirt"  } } */
Jan Hubicka Jan. 15, 2016, 11:40 a.m. UTC | #2
> On Fri, Jan 15, 2016 at 12:01 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> > Hi,
> > this patch avoid ipa-icf to take away body of a virtual function which is a subject
> > of later devirtualization.
> 
> But isn't can_remove_if_no_direct_alls_p () supposed to return false
> then?  (depending
> on cgraph state)

No, can_remove_if_no_direct_calls_p returns true if you can remove the body after
you eliminate all calls (as the name is supposed to suggest).

For the virtual function in question this is satisfied, but unfortunately in ICF
case makes us to miss optimization for no very good reason.  it is indeed quite bit
more subtle than I would like to.  Changing the predicate itself will however make
inliner to inline those functions less agressively which is not very desired either.

Honza
diff mbox

Patch

Index: ipa-icf.c
===================================================================
--- ipa-icf.c	(revision 232407)
+++ ipa-icf.c	(working copy)
@@ -1305,6 +1305,7 @@  sem_function::merge (sem_item *alias_ite
 
       /* If all callers was redirected, do not produce wrapper.  */
       if (alias->can_remove_if_no_direct_calls_p ()
+	  && !DECL_VIRTUAL_P (alias->decl)
 	  && !alias->has_aliases_p ())
 	{
 	  create_wrapper = false;
Index: testsuite/g++.dg/ipa/devirt-49.C
===================================================================
--- testsuite/g++.dg/ipa/devirt-49.C	(revision 0)
+++ testsuite/g++.dg/ipa/devirt-49.C	(revision 0)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-ipa-devirt"  } */
+struct Interface {
+  virtual ~Interface() {}
+  virtual void virtualFunc() = 0;
+  virtual void virtualFunc2() = 0;
+};
+
+struct Concrete : Interface {
+  int counter_;
+  Concrete() : counter_(0) {}
+  void virtualFunc() { counter_++; }
+  void virtualFunc2() { counter_++; }
+};
+
+void test(Interface &c) {
+  c.virtualFunc();
+  c.virtualFunc2();
+}
+/* { dg-final { scan-ipa-dump "2 speculatively devirtualized" "devirt"  } } */