By Z boson


2015-05-04 15:41:05 8 Comments

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.

2 comments

@Jerry Coffin 2015-05-04 15:46:35

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.

@Yakk - Adam Nevraumont 2015-05-04 15:57:13

The address of the variable in the function, and the address of the variable assigned to outside, can be identical as they have non-overlapping lifetimes: the temporary bridge cannot have its address taken, and it sharing the other two variable's address cannot be detected. This, I think, makes it impossible to detect it happened (in theory) under the standard: in practice, if the variable in the function and the variable assigned to outside have the same address, odds are you are witnessing NRVO.

@Peaker 2015-11-17 06:17:56

Testing this out on gcc, g++, clang, clang++, it turns out that everyone does NRVO properly except gcc -xc, which generates superfluous copies when you have: struct s f() { struct s x = g(); return x; }

@Arkanosis 2015-05-04 15:45:59

The reason why it's covered a lot for C++ is because in C++, RVO has side effects (ie. not calling the destructor of the temporary objects nor the copy constructor or assignment operator of the resulting objects).

In C, there's no possible side effect, only potential performance improvements. I see no reason such an optimization couldn't be performed by some compiler. At least, there is nothing that forbids it in the standard.

Anyway, optimization is compiler and optimization level-dependant, so I wouldn't bet on it for critical code paths, unless the compiler used is well defined and not expected to change (which is still often the case).

Related Questions

Sponsored Content

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite?

4 Answered Questions

[SOLVED] How do I achieve the theoretical maximum of 4 FLOPs per cycle?

10 Answered Questions

5 Answered Questions

[SOLVED] Returning unique_ptr from functions

  • 2010-11-30 17:44:37
  • Praetorian
  • 141197 View
  • 328 Score
  • 5 Answer
  • Tags:   c++ c++11 unique-ptr

4 Answered Questions

[SOLVED] What are copy elision and return value optimization?

3 Answered Questions

[SOLVED] Copy Elision for Returned Temporaries

5 Answered Questions

[SOLVED] What is the copy-and-swap idiom?

2 Answered Questions

2 Answered Questions

2 Answered Questions

[SOLVED] Conditions for copy elision?

  • 2011-06-17 09:09:33
  • StackedCrooked
  • 1120 View
  • 10 Score
  • 2 Answer
  • Tags:   c++

Sponsored Content