Some people are not aware that it's possible to pass and return structs by value in C. My question is about the compiler making unnecessary copies when returning structs in C. Do C compilers such as GCC use Return value optimization(RVO) optimization or is this a C++ only concept? Everything I have read about RVO and copy elision is in regards to C++.
Let's consider an example. I'm currently implementing a double-double data type in C (or rather float-float to start with because I find it easy to unit test). Consider the following code.
typedef struct { float hi; float lo; } doublefloat; doublefloat quick_two_sum(float a, float b) { float s = a + b; float e = b - (s - a); return (doublefloat){s, e}; }
Will the compiler make a temporary copy of the doublefloat
value I return or can the temporary copy be elided?
What about named return value optimization (NRVO) in C? I have another function
doublefloat df64_add(doublefloat a, doublefloat b) { doublefloat s, t; s = two_sum(a.hi, b.hi); t = two_sum(a.lo, b.lo); s.lo += t.hi; s = quick_two_sum(s.hi, s.lo); s.lo += t.lo; s = quick_two_sum(s.hi, s.lo); return s; }
In this case i'm returning a named struct. Can the temporary copy in this case be elided?
It should be stated that this is a general question for C and that the code examples I have used here are only examples (when I optimize this I will be using SIMD with intrinsics anyway). I'm aware that I could look at the assembly output to see what the compiler does but I think this is an interesting question nevertheless.
> Note also that C doesn't have return-value-optimization, hence all your struct-returning functions will cause a call to memcpy (won't happen when compiled in C++ mode of course).
In the context of the C++ programming language, return value optimization (RVO) is a compiler optimization that involves eliminating the temporary object created to hold a function's return value. RVO is allowed to change the observable behaviour of the resulting program by the C++ standard.
When copy elision occurs, the implementation treats the source and target of the omitted copy/move (since C++11) operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the ...
(Named) Return value optimization is a common form of copy elision. It refers to the situation where an object returned by value from a method has its copy elided. The example set forth in the standard illustrates named return value optimization, since the object is named.
RVO/NRVO are clearly allowed under the "as-if" rule in C.
In C++ you can get observable side-effects because you've overloaded the constructor, destructor, and/or assignment operator to give those side effects (e.g., print something out when one of those operations happens), but in C you don't have any ability to overload those operators, and the built-in ones have no observable side effects.
Without overloading them, you get no observable side-effects from copy elision, and therefore nothing to stop a compiler from doing it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With