devirtualize final virtual function calls

Submitted by Roberto Agostino Vitillo on Sept. 20, 2011, 4:43 p.m.

Details

Message ID CEFC5DBC-8421-4578-A04B-97FABD7A2214@lbl.gov
State New
Headers show

Commit Message

Roberto Agostino Vitillo Sept. 20, 2011, 4:43 p.m.
When calling a final virtual function or a virtual function that belongs to a final class there is no need for a virtual lookup. E.g.:

struct A final
{
  virtual void foo ()
  {
  }
};

struct B
{
  virtual void foo () final
  {
  }
};

void fun(A* a, B* b)
{
  a->foo();
  b->foo();
}

with this patch translates to:

(__TEXT,__text) section
__Z3funP1AP1B:
0000000000000000	pushq	%rbp
0000000000000001	movq	%rsp,%rbp
0000000000000004	subq	$0x10,%rsp
0000000000000008	movq	%rdi,0xf8(%rbp)
000000000000000c	movq	%rsi,0xf0(%rbp)
0000000000000010	movq	0xf8(%rbp),%rax
0000000000000014	movq	%rax,%rdi
0000000000000017	callq	__ZN1A3fooEv
000000000000001c	movq	0xf0(%rbp),%rax
0000000000000020	movq	%rax,%rdi
0000000000000023	callq	__ZN1B3fooEv
0000000000000028	leave
0000000000000029	ret

Tested on macosx x86_64.
r


2011-09-20 Roberto Agostino Vitillo <ravitillo@lbl.gov>

	* gcc/testsuite/g++.dg/other/final1.C: new test
	* gcc/cp/call.c (build_new_method_call_1): use non virtual lookup for final virtual functions

Comments

Jason Merrill Sept. 20, 2011, 6:46 p.m.
On 09/20/2011 12:43 PM, Roberto Agostino Vitillo wrote:
> -	      if (DECL_VINDEX (fn)&&  ! (flags&  LOOKUP_NONVIRTUAL)
> -		&&  resolves_to_fixed_type_p (instance, 0))
> +	      if (DECL_VINDEX (fn)&&  ((! (flags&  LOOKUP_NONVIRTUAL)
> +		&&  resolves_to_fixed_type_p (instance, 0))
> +		  || DECL_FINAL_P (fn) || CLASSTYPE_FINAL (basetype)))
>  		flags |= LOOKUP_NONVIRTUAL;

I think we don't need the extra parentheses on the flags test here; if 
LOOKUP_NONVIRTUAL is already set, we can stop right there rather than 
look for reasons to set it.

I'll go ahead and change that and check in the patch.

This patch is small enough not to need a copyright assignment, but it 
would be good to get one on file now so that we don't need to wait on 
that for future patches.  You can get more information about copyright 
assignment from copyright-clerk@fsf.org

Thanks,
Jason

Patch hide | download patch | download mbox

Index: gcc/testsuite/g++.dg/other/final1.C
===================================================================
--- gcc/testsuite/g++.dg/other/final1.C	(revision 0)
+++ gcc/testsuite/g++.dg/other/final1.C	(revision 0)
@@ -0,0 +1,26 @@ 
+/* Verify that final methods are devirtualized */
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-original -std=c++0x"  } */
+
+struct A final
+{
+  virtual void foo ()
+  {
+  }
+};
+
+struct B
+{
+  virtual void foo () final
+  {
+  }
+};
+
+void fun(A* a, B* b)
+{
+  a->foo();
+  b->foo();
+}
+
+/* { dg-final { scan-tree-dump-times "A::foo" 2 "original"  } } */
+/* { dg-final { scan-tree-dump-times "B::foo" 2 "original"  } } */
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 178911)
+++ gcc/cp/call.c	(working copy)
@@ -7277,8 +7277,9 @@ 
 	    }
 	  else
 	    {
-	      if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
-		  && resolves_to_fixed_type_p (instance, 0))
+	      if (DECL_VINDEX (fn) && ((! (flags & LOOKUP_NONVIRTUAL)
+		  && resolves_to_fixed_type_p (instance, 0)) 
+		  || DECL_FINAL_P (fn) || CLASSTYPE_FINAL (basetype)))
 		flags |= LOOKUP_NONVIRTUAL;
               if (explicit_targs)
                 flags |= LOOKUP_EXPLICIT_TMPL_ARGS;