return value aliasing ?

Marc Glisse marc.glisse@inria.fr
Fri Mar 28 09:52:00 GMT 2014


On Thu, 27 Mar 2014, Joachim Schöberl wrote:

> I am experimenting with AVX optimization of a complex code, and discovered
> this simplified test-case already for scalar code:
>
> I compiled this code
>
> class MyDouble
> {
>  double data;
> public:
>  MyDouble (const MyDouble & v2) : data(v2.data) { ; }
>  MyDouble (double d) : data(d) { ; }
>
>  MyDouble & operator+= (MyDouble d)
>  { data += d.data; return *this; }
> };
>
> MyDouble MyFuncBad (int m, MyDouble x)
> {
>  MyDouble sum = 0.0;
>  for (int i = 0; i < m; i++) sum += x;
>  return sum;
> }
>
> MyDouble MyFuncGood (int m, MyDouble x)
> {
>  MyDouble sum = 0.0;
>  for (int i = 0; i < m; i++) sum += x;
>  return MyDouble(sum);
> }
>
> with 'gcc-4.8 -O3 -S testdouble.cpp' and got the assembly code below.
> I would expect that both functions are equivalent.
>
> In MyFuncBad, the intermediate sum is written to memory in every
> iteration, while in MyFuncGood just the final result is brought to
> memory. Is this necessary for correctness ?
> Can the return-value alias the call-by-value argument ?
>
> In the AVX-code the performance difference was about 30 percent.
>
> If I use the default copy-constructor, I also get the faster code.
> Is there something wrong with my (of course here unnecessary) copy-constructor
> ?

Please file a PR in bugzilla for this missed optimization. C++ copy 
elision makes us use the return slot for sum, and we don't manage to avoid 
the memory accesses. Removing the user-defined copy constructor changes 
the ABI to return in a register, and copy elision doesn't apply.

-- 
Marc Glisse



More information about the Gcc-help mailing list