This is the mail archive of the gcc@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]
Other format: [Raw text]

Explicitly defining a copy-constructor may cost a lot: optimizationbug?



I always thought that (a) explicitely defining a public, inline copy constructor that performs a memberwise copy of the class' subobjects or (b) leaving it implicitely defined was the same thing, as far as the generated code was concerned.

However, the attached snippet shows that, using GCC 3.4.1
alternative (a) is significantly more expensive than
alternative (b).

--------------------------------- z.cc ---------------------------------
typedef int Type;

void check(int);

template <typename To, typename From>
inline int assign(To& a, From b) {
	a = b;
	return 0;
}

template <typename To, typename From>
inline int add(To& a, From b, From c) {
	a = b + c;
	return 0;
}

template <typename T>
class Template;

template <typename T>
class Template {
private:
	T v;
public:
	Template()
		: v(0) {
	}
#if 1
	Template(const Template& y)
		: v(y.v) {
	}
#endif
	Template(const T y)
		: v(y) {
	}
	template <typename T1>
	Template(const T1 y) {
		check(assign(v, y));
	}
	const T& value() const {
		return v;
	}
};

template <typename T>
inline Template<T>
operator+(const Template<T> x, const Template<T> y) {
	T r;
	check(add(r, x.value(), y.value()));
	return r;
}

template <typename T, typename T1>
inline Template<T>
operator+(const T1 x, const Template<T> y)
{
	return Template<T>(x) + y;
}

Type s(int v)
{
	Template<Type> a = v;
	Template<Type> c = 3 + a;
	return c.value();
}
------------------------------------------------------------------------

Playing with the "#if 1" one can switch from a synthesized to a user-defined
copy constructor.  Compiling with "-O3 -S" one can obtain z.s.gcc_synth_cc
and z.s.gcc_user_cc, respectively.  Then a diff reveals that, in the case
of the user-defined copy constructor, a significant extra-cost has been
incurred.

$ diff z.s.gcc_synth_cc z.s.gcc_user_cc
8c8
< .LFB10:
---
> .LFB11:
15c15
<       subl    $4, %esp
---
>       subl    $100, %esp
17c17,18
<       movl    8(%ebp), %ebx
---
>       movl    8(%ebp), %eax
>       movl    $3, -72(%ebp)
18a20,23
>       leal    3(%eax), %ebx
>       movl    %eax, -24(%ebp)
>       movl    %eax, -56(%ebp)
>       movl    %eax, -88(%ebp)
20,21c25
<       popl    %edx
<       addl    $3, %ebx
---
>       addl    $100, %esp
26c30
< .LFE10:
---
> .LFE11:
52,53c56,57
<       .long   .LFB10
<       .long   .LFE10-.LFB10
---
>       .long   .LFB11
>       .long   .LFE11-.LFB11
56c60
<       .long   .LCFI0-.LFB10
---
>       .long   .LCFI0-.LFB11

I have tried the same program with the Intel C++ compiler and,
compiling with "-O3", changing "#if 1" to "#if 0" makes no
difference in the generated code, which does not write things
to memory the way GCC does in the user-defined case.
Am I missing something?
All the best,

Roberto Bagnara

--
Prof. Roberto Bagnara
Computer Science Group
Department of Mathematics, University of Parma, Italy
http://www.cs.unipr.it/~bagnara/
mailto:bagnara@cs.unipr.it


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