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