This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

NRV vs Constructor elison.


Hello,

I have been revisiting the so-called return value optimizations, and I
found some things which I cannot fully grasp.

Basically, the issue is about the difference between return value
optimization and constructor elison; and how they are controlled
within GCC.

-----------------------------
---- Test program ----
-----------------------------

Take main.cc as

////
#include <iostream>
class A {
public:
  A(const A&)            { std::cout << "-\n";               }
  A()                    { std::cout << "*\n";               }
  A& operator=(const A&) { std::cout << "=\n"; return *this; }
};
A f() { A a; return a; }
int main() { A a = f(); }
////


------------------------------
---- GCC's version ----
------------------------------

r$ g++ --version
g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

----------------------
---- CASES  ----
----------------------

In order to see what's happening I ran

1)
r$ g++ main.cc
r$ ./a.out
*
2)
r$ g++ -fno-elide-constructors main.cc
r$ ./a.out
*
-
-
3)
r$ g++ -fdump-tree-nrv main.cc
r$ ls
a.out  main.cc
r$ ./a.out
*
4)
r$ g++ -O1 -fdump-tree-nrv main.cc
r$ ls
a.out  main.cc  main.cc.127t.nrv
r$ ./a.out
*
5)
r$ g++ -O1 -fdump-tree-nrv -fno-elide-constructors main.cc
r$ ls
a.out  main.cc  main.cc.127t.nrv
r$ ./a.out
*
-
-
r$ mv main.cc.127t.nrv main.cc.127t.nrv.no-elide
r$ g++ -O1 -fdump-tree-nrv  main.cc
r$ ./a.out
*
r$ ls
a.out  main.cc  main.cc.127t.nrv  main.cc.127t.nrv.no-elide
r$ diff main.cc.127t.nrv main.cc.127t.nrv.no-elide
20a21
>   __ostream_insert (&cout, &"-\n"[0], 2);
32a34
>   __ostream_insert (&cout, &"-\n"[0], 2);
6)
r$ g++ -Q --help=c++ | grep elide
  -felide-constructors
r$ g++ --help=c++ | grep elide
  -felide-constructors        This switch lacks documentation
7)
man g++
...
       -fno-elide-constructors
           The C++ standard allows an implementation to omit creating
a temporary which is only used to
           initialize another object of the same type.  Specifying
this option disables that optimization,
           and forces G++ to call the copy constructor in all cases.
...
       Not all optimizations are controlled directly by a flag.  Only
optimizations that have a flag are
       listed.
8)
r$ g++ -fdump-tree-optimized -fdump-tree-original
-fno-elide-constructors main.cc
r$ ls
a.out  main.cc  main.cc.003t.original
9)
r$ g++ -fdump-tree-original -fno-elide-constructors main.cc
r$ mv main.cc.003t.original main.cc.003t.original.no-elide
r$ g++ -fdump-tree-original  main.cc
r$ gvimdiff main.cc.003t.original main.cc.003t.original.no-elide
2 files to edit
(omit the contents for brevity)
------------------------------------
---- OBSERVATIONS ----
------------------------------------

- Given 3 & 4: NRV is not enabled with -O0 (the default optimization
level) but it's with -O1. There's no individual flag for NRV (as the
man allows in the 2nd paragraph in 7).

- Given 1: Construction elison is taking place even at -O0; but the
first command of 6 doesn't show an [enabled] tag for it.

- Given 5: The constructors are being inlined in the no-elided
version, so more than the call (as the man says in 7) when
"no-elide-constructors" you force the execution of the body (of
course, if no call, no execution).

- Given 8: Constructor elison is not a tree based optimization.

- Given 9: Constructor elison is performed before tree based optimization.

- In the file generated by 4 called "main.cc.127t.nrv" I see a "return
slot optimization" label.

-----------------------------

So, we have:

- Named return value optimization.
- Return slot optimization.
- Construction elison optimization.

What's the relation between them?
Which are the differences and similarities?

On one hand, construction elison seems to be a more general thing than
nrv (from previous knowledge I understand nrv to be an optimization
avoiding calls to constructors in return statements). But we saw that
elison is applied without nrv taking place, but that may be an
artifact of how certain cases are handled in GCC (tree based
optimization or another technique).

Cheers, thanks a lot, and have a happy new year.

--
Rodolfo Federico Gamarra


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]