Patchwork devirtualize final virtual function calls

login
register
mail settings
Submitter Roberto Agostino Vitillo
Date Sept. 20, 2011, 4:43 p.m.
Message ID <CEFC5DBC-8421-4578-A04B-97FABD7A2214@lbl.gov>
Download mbox | patch
Permalink /patch/115601/
State New
Headers show

Comments

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
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

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;