This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch/RFC] libstdc++/20610
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Cc: Gabriel Dos Reis <gdr at integrable-solutions dot net>
- Date: Thu, 24 Mar 2005 11:31:33 +0100
- Subject: [Patch/RFC] libstdc++/20610
Hi,
Fredrik noticed that the code we produce for complex * real is
suboptimal. The primary template for operator*= is:
template<typename _Tp>
complex<_Tp>&
complex<_Tp>::operator*=(const _Tp& __t)
{
_M_real *= __t;
_M_imag *= __t;
return *this;
}
whereas the specializations read (f.i., for double):
inline complex<double>&
complex<double>::operator*=(double __d)
{
_M_value *= __d;
return *this;
}
A simple fix for this issue is expanding the latter to:
inline complex<double>&
complex<double>::operator*=(double __d)
{
__real__ _M_value *= __d;
__imag__ _M_value *= __d;
return *this;
}
To give you an example, the assembly (for -O3 -march=pentium4
-mfpmath=sse) goes from:
_Z1fv:
.LFB1859:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
movsd b+8, %xmm3
movsd b, %xmm2
movsd c, %xmm4
pxor %xmm5, %xmm5
movapd %xmm2, %xmm0
mulsd %xmm5, %xmm0
movapd %xmm4, %xmm1
mulsd %xmm3, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, a+8
mulsd %xmm4, %xmm2
mulsd %xmm5, %xmm3
subsd %xmm3, %xmm2
movsd %xmm2, a
popl %ebp
ret
to:
_Z1fv:
.LFB1859:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
movsd b, %xmm0
movsd c, %xmm2
movapd %xmm2, %xmm1
mulsd b+8, %xmm1
movsd %xmm1, a+8
mulsd %xmm2, %xmm0
movsd %xmm0, a
popl %ebp
ret
Indeed, we have also a compiler problem here, because in principle,
for builtin complex types, the compiler should be able to expand
efficiently complex * real, still, while making sure that the issue
is investigated by the middle-end maintainers, the above change
probably cannot hurt (would be 4.0 material).
Comments?
In case, probably we should prepare something similar for
operator/= too.
Tested x86-linux.
Paolo.
////////////////
PR libstdc++/20610
* include/std/std_complex.h (operator*=(float), operator*=(double),
operator*=(long double)): Implement consistently with the primary
template, splitting real and imaginary parts of this.
diff -urN libstdc++-v3-orig/include/std/std_complex.h libstdc++-v3/include/std/std_complex.h
--- libstdc++-v3-orig/include/std/std_complex.h 2005-03-16 00:38:54.000000000 +0100
+++ libstdc++-v3/include/std/std_complex.h 2005-03-24 11:03:18.000000000 +0100
@@ -1088,7 +1088,8 @@
inline complex<float>&
complex<float>::operator*=(float __f)
{
- _M_value *= __f;
+ __real__ _M_value *= __f;
+ __imag__ _M_value *= __f;
return *this;
}
@@ -1241,7 +1242,8 @@
inline complex<double>&
complex<double>::operator*=(double __d)
{
- _M_value *= __d;
+ __real__ _M_value *= __d;
+ __imag__ _M_value *= __d;
return *this;
}
@@ -1394,7 +1396,8 @@
inline complex<long double>&
complex<long double>::operator*=(long double __r)
{
- _M_value *= __r;
+ __real__ _M_value *= __r;
+ __imag__ _M_value *= __r;
return *this;
}