This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Explicitly defining a copy-constructor may cost a lot: optimizationbug?
- From: Roberto Bagnara <bagnara at cs dot unipr dot it>
- To: gcc at gcc dot gnu dot org
- Cc: Roberto Bagnara <bagnara at cs dot unipr dot it>
- Date: Wed, 11 Aug 2004 16:29:27 +0200
- Subject: Explicitly defining a copy-constructor may cost a lot: optimizationbug?
- Organization: Department of Mathematics, University of Parma, Italy
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