This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
NRV vs Constructor elison.
- From: Rodolfo Federico Gamarra <rgamarra at gmail dot com>
- To: GCC-help <gcc-help at gcc dot gnu dot org>
- Date: Thu, 31 Dec 2009 14:04:44 -0200
- Subject: 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