[cfe-dev] Detecting (N)RVO

Kim Gräsman via cfe-dev cfe-dev at lists.llvm.org
Wed Nov 4 02:41:24 PST 2015


Hi Richard,

Thanks, good info!

On Tue, Nov 3, 2015 at 10:51 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> On Tue, Nov 3, 2015 at 1:34 PM, Kim Gräsman <cfe-dev at lists.llvm.org> wrote:
> >
>> > Also, I'm not sure if my terminology is right; I haven't found any
>> > references to RVO-sans-the-N, is that refered to as copy elision? NRVO
>> > only seems to address VarDecls and their lifetime.
>
> RVO is a special case of copy elision, where the elided copy is initializing
> the returned object.

I figured as much, makes sense, thanks!

>> I guess the more direct question is: is there a single place where I
>> can detect if copy elision/NRVO/RVO has happened or will definitely
>> happen for the return value of a function?
>
> Not really, no, our current model marks the places where it's permissible
> then leaves the details up to IR generation.

OK, so IR generation can basically choose to make a copy even if
Sema/CodeGen has marked something as eligible for copy elision? Does
this interact with other optimizations?

> P0135R0 was accepted by C++'s evolution working group in Kona, so RVO is
> likely to be guaranteed by the language semantics in C++17 onwards.

Cool, that's a nice development! This makes it possible to reason more
formally about when elision will happen.

My attribute-guided warning was intended more for user guidance. A
function marked as `requires_rvo` will be able to maintain that
property even if someone changes the code in a way that RVO can't
happen, e.g. from

   [[clang::requires_rvo]]
   std::string f() {
      // copy elision
      return std::string("Hello world");
   }

to

   [[clang::requires_rvo]]
   std::string f(int v) {
      std::string a = "Hello world", b = "Farewell to arms";

      if (v < 20)
        return b;

      return a;
   }

(assuming the latter disables NRVO, maybe it doesn't?)

> For NRVO, I think the best model would be an attribute on the variable:
>
>   std::string f() {
>     [[clang::returned]] std::string x = "Hello world";
>     return x;
>   }
>
> ... which would give an error if we can't apply NRVO to it.

This looks easier to implement, but less useful for the case I
presented above. I'm worried about code that assumes RVO is working,
but where user changes suddenly render the compiler unable to deliver.
I generally trust the compiler to do the right thing.

A per-variable attribute would be more of a guide to the compiler to
make the NRVO analysis user-directed, right?

> (Also of note: clang's NRVO heuristic is currently quite weak, and improving
> it would seem like a good idea. In principle, we should be able to put a
> variable into the return slot in all cases where all return-statements
> within its scope return it.)

I think that's the current behavior, you and Nick Lewycky seem to have
fixed that in:
https://github.com/llvm-mirror/clang/commit/130d63a029bc588cb61a6aaea2db6b9ed4c5cc56

Thanks,
- Kim



More information about the cfe-dev mailing list