Explicitly defining a copy-constructor may cost a lot: optimization bug?
Roberto Bagnara
bagnara@cs.unipr.it
Wed Aug 11 14:47:00 GMT 2004
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
More information about the Gcc
mailing list