This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++ PATCH: improve performance of vbase initialization



[ Jeff & Richard -- there's an x86/gcse question buried in here so
  y'all might want to take a look, even though this is a C++ thing.]

I noticed that our vbase initialization code was somewhat suboptimal.

In C++, virtual bases are initialized from the most derived class.
Therefore, we know the offsets of virtual bases at compile-time.  (In
general, the offset of a virtual base must be determined at run-time.)

So, when we're constructing a virtual base, we don't need to look up
its address dynamically.

I've attached a test program and before-and-after x86 assembly to show
how this makes an improvement.  Look for how the arguments to __1Ai
are constructed.

BTW, I'm surprised that GCSE isn't able to eliminate the redundant
test of edx.  Any ideas?

This is not an ABI change, but it will improve code generated by both
the old and new ABIs.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

==== test2.C ====
struct A
{
  A (int);
};

struct B : virtual public A
{
  B ();
};

B::B ()
  : A (3)
{
}
==== test2.s ==== [old version]
__1Bi:
.LFB1:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	subl	$20, %esp
.LCFI2:
	movl	12(%ebp), %edx
	pushl	%ebx
.LCFI3:
	movl	8(%ebp), %ebx
	testl	%edx, %edx
	je	.L3
	leal	4(%ebx), %eax
	movl	%eax, (%ebx)
.L3:
	testl	%edx, %edx
	je	.L4
	subl	$8, %esp
	pushl	$3
	movl	(%ebx), %edx
	pushl	%edx
.LCFI4:
	call	__1Ai
.L4:
	movl	%ebx, %eax
	movl	-24(%ebp), %ebx
	movl	%ebp, %esp
	popl	%ebp
	ret
==== test2.s ==== [new version]
__1Bi:
.LFB1:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	subl	$20, %esp
.LCFI2:
	movl	12(%ebp), %edx
	pushl	%ebx
.LCFI3:
	movl	8(%ebp), %ebx
	testl	%edx, %edx
	je	.L3
	leal	4(%ebx), %eax
	movl	%eax, (%ebx)
.L3:
	testl	%edx, %edx
	je	.L4
	subl	$8, %esp
	leal	4(%ebx), %eax
	pushl	$3
	pushl	%eax
.LCFI4:
	call	__1Ai
.L4:
	movl	%ebx, %eax
	movl	-24(%ebp), %ebx
	movl	%ebp, %esp
	popl	%ebp
	ret

2000-01-16  Mark Mitchell  <mark@codesourcery.com>

	* init.c (construct_virtual_bases): Don't look up the addresses of
	virtual bases at run-time.

Index: init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.160
diff -c -p -r1.160 init.c
*** init.c	2000/01/16 16:59:44	1.160
--- init.c	2000/01/16 20:13:31
*************** construct_virtual_bases (type, this_ref,
*** 751,759 ****
    for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
         vbases = TREE_CHAIN (vbases))
      {
-       tree tmp = purpose_member (vbases, result);
        tree inner_if_stmt;
        tree compound_stmt;
  
        /* If there are virtual base classes with destructors, we need to
  	 emit cleanups to destroy them if an exception is thrown during
--- 751,759 ----
    for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
         vbases = TREE_CHAIN (vbases))
      {
        tree inner_if_stmt;
        tree compound_stmt;
+       tree exp;
  
        /* If there are virtual base classes with destructors, we need to
  	 emit cleanups to destroy them if an exception is thrown during
*************** construct_virtual_bases (type, this_ref,
*** 772,780 ****
        inner_if_stmt = begin_if_stmt ();
        finish_if_stmt_cond (flag, inner_if_stmt);
        compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
!       expand_aggr_vbase_init_1 (vbases, this_ref,
! 				TREE_OPERAND (TREE_VALUE (tmp), 0),
! 				init_list);
        finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
        finish_then_clause (inner_if_stmt);
        finish_if_stmt ();
--- 772,791 ----
        inner_if_stmt = begin_if_stmt ();
        finish_if_stmt_cond (flag, inner_if_stmt);
        compound_stmt = begin_compound_stmt (/*has_no_scope=*/1);
! 
!       /* Compute the location of the virtual base.  If we're
! 	 constructing virtual bases, then we must be the most derived
! 	 class.  Therefore, we don't have to look up the virtual base;
! 	 we already know where it is.  */
!       exp = build (PLUS_EXPR,
! 		   TREE_TYPE (this_ptr),
! 		   this_ptr,
! 		   BINFO_OFFSET (vbases));
!       exp = build1 (NOP_EXPR, 
! 		    build_pointer_type (BINFO_TYPE (vbases)), 
! 		    exp);
! 
!       expand_aggr_vbase_init_1 (vbases, this_ref, exp, init_list);
        finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
        finish_then_clause (inner_if_stmt);
        finish_if_stmt ();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]