p0889: ultimate copy elisions and p0878r0: subobjects copy ... elisions v2.pdf · problems that...
TRANSCRIPT
![Page 1: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/1.jpg)
P0889: Ultimate copy elisionsand
P0878R0: Subobjects copy elision
Antony Polukhin
![Page 2: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/2.jpg)
Copy/Move elision
![Page 3: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/3.jpg)
Copy/Move elision
Simplified description:
Copy elision allows to not call copy/move constructors when returning a value of function return type from a function
3 / 50
![Page 4: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/4.jpg)
Copy/Move elision
Simplified description:
Copy elision allows to not call copy/move constructors when returning a value of function return type from a function
Precise description available at [class.copy.elision]
4 / 50
![Page 5: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/5.jpg)
Some codestruct T {
T() noexcept; T(T&&) noexcept; ~T() noexcept;
void do_something() noexcept;
};
static T produce() { T a; a.do_something(); return a; }
static T update(T b) { b.do_something(); return b; }
static T shrink(T c) { c.do_something(); return c; }
int caller() {
T d = shrink(update(produce()));
} 5 / 50
![Page 6: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/6.jpg)
Current result of compilationcaller():
sub rsp, 24
lea rdi, [rsp+14]
call T::T()
lea rdi, [rsp+14]
call T::do_something()
lea rdi, [rsp+14]
call T::do_something()
lea rsi, [rsp+14]
lea rdi, [rsp+15]
call T::T(T&&)
lea rdi, [rsp+15] 6 / 50
call T::do_something()
lea rsi, [rsp+15]
lea rdi, [rsp+13]
call T::T(T&&)
lea rdi, [rsp+15]
call T::~T()
lea rdi, [rsp+14]
call T::~T()
lea rdi, [rsp+13]
call T::~T()
![Page 7: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/7.jpg)
Current result of compilationcaller():
call T::T() // T a
call T::do_something() // a.do_something();
// T& b = a; // copy elision worked well
call T::do_something() // b.do_something();
call T::T(T&&) // T c{std::move(b)};
call T::do_something() // c.do_something();
call T::T(T&&) // T d{std::move(c)};
call T::~T() // ~d();
call T::~T() // ~c();
call T::~T() // ~a(); /*~b()*/
7 / 50
![Page 8: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/8.jpg)
Current result of compilationcaller():
call T::T() // T a
call T::do_something() // a.do_something();
// T& b = a; // copy elision worked well
call T::do_something() // b.do_something();
call T::T(T&&) // T c{std::move(b)};
call T::do_something() // c.do_something();
call T::T(T&&) // T d{std::move(c)};
call T::~T() // ~d();
call T::~T() // ~c(); `c` isn't accessed after move construction of `d`←
call T::~T() // ~a(); `a` isn't accessed after move construction of `c`←
8 / 50
![Page 9: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/9.jpg)
There's something strange
In assembly there is a following pattern:
Variable X is copy constructed from variable Y
Variable Y is not accessed any more
Variable Y is destroyed
9 / 50
![Page 10: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/10.jpg)
There's something strange
In assembly there is a following pattern:
Variable X is copy constructed from variable Y
Variable Y is not accessed any more
Variable Y is destroyed
Instead if copying and using the copy compiler could reuse the old object as if it was a new one (do the copy elision) [*]
10 / 50
![Page 11: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/11.jpg)
Better result is possible:caller():
call T::T() // T a
call T::do_something() // a.do_something();
call T::do_something() // ba.do_something();
call T::T(T&&) // T c{std::move(b)};
call T::do_something() // ca.do_something();
call T::T(T&&) // T d{std::move(c)};
call T::~T() // ~d();
call T::~T() // ~c();
call T::~T() // ~a();
11 / 50
![Page 12: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/12.jpg)
Better result is almost 2 times shorter:caller():
call T::T() // T a
call T::do_something() // a.do_something();
call T::do_something() // a.do_something();
call T::do_something() // a.do_something();
call T::~T() // ~a();
12 / 50
![Page 13: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/13.jpg)
The idea: Relaxed rules for CE
Allow to reuse the old object as if it was a new one if the old object is not accessed between a copy/move construction of it and its destruction.
Allow modern compilers to mix copy elision optimization with results of other optimizations.
13 / 50
![Page 14: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/14.jpg)
Problems that P0889 addresses
![Page 15: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/15.jpg)
Problems that P0889 addresses
Compilers are forced to inline constructors+destructors and optimize a lot of IR
15 / 50
![Page 16: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/16.jpg)
Problems that P0889 addresses
Compilers are forced to inline constructors+destructors and optimize a lot of IR
Affects compile times
16 / 50
![Page 17: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/17.jpg)
Problems that P0889 addresses
Compilers are forced to inline constructors+destructors and optimize a lot of IR
Affects compile times
Compilers fail to inline the copy/move constructors and optimize the whole code to the same point as the relaxed copy elision rules may allow
17 / 50
![Page 18: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/18.jpg)
Problems that P0889 addresses
Compilers are forced to inline constructors+destructors and optimize a lot of IR
Affects compile times
Compilers fail to inline the copy/move constructors and optimize the whole code to the same point as the relaxed copy elision rules may allow:
Affects runtime performance
Affects binary sizes
18 / 50
![Page 19: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/19.jpg)
Problems that P0889 addresses
Compilers are forced to inline constructors+destructors and optimize a lot of IR
Affects compile times
Compilers fail to inline the copy/move constructors and optimize the whole code to the same point as the relaxed copy elision rules may allow:
Affects runtime performance
Affects binary sizes
Because compilers do not elide copy constructors users are forced to write std::move
19 / 50
![Page 20: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/20.jpg)
Problems that P0889 addresses
Compilers are forced to inline constructors+destructors and optimize a lot of IR
Affects compile times
Compilers fail to inline the copy/move constructors and optimize the whole code to the same point as the relaxed copy elision rules may allow:
Affects runtime performance
Affects binary sizes
Because compilers do not elide copy constructors users are forced to write std::move
Rules for writing (or not writing) std::move are tricky
20 / 50
![Page 21: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/21.jpg)
Problems that P0889 addresses
Compilers are forced to inline constructors+destructors and optimize a lot of IR
Affects compile times
Compilers fail to inline the copy/move constructors and optimize the whole code to the same point as the relaxed copy elision rules may allow:
Affects runtime performance
Affects binary sizes
Because compilers do not elide copy constructors users are forced to write std::move
Rules for writing (or not writing) std::move are tricky
Affects language usage simplicity and teach-ability
21 / 50
![Page 22: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/22.jpg)
How far we should go and what could be improved?
![Page 23: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/23.jpg)
Copy elisions through references
return std::move(local_variable);
auto& v = local_variable; return v;
return path(__lhs) /= __rhs; // libstdc++/85671
???
23 / 50
![Page 24: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/24.jpg)
Decompose default destructible types
return pair.second;
return get<0>(tuple); // requires CE through references
auto [a,b] = foo(); return a; // requires CE through references
return local_aggregate_variable.name;
24 / 50
![Page 25: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/25.jpg)
Decompose any type
return stringstream.str(); // requires CE through references
return get<int>(variant); // requires CE through references
return path.string();
25 / 50
![Page 26: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/26.jpg)
Not only for function returns
{ T v; takes_by_copy(v); }
{ T v; takes_by_reference_and_copies_internally(v); }
struct B { T a; B(const T& a): a(a) {} }; B b{T{}}; // CWG #1049
26 / 50
![Page 27: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/27.jpg)
All together (P0889)
[class.copy.elision]
...
Additionally, copy elision is allowed for any non-volatile object with automatic storage duration and it's non-volatile nested objects if source is not accessed between a copy/move construction of it and its destruction.
27 / 50
![Page 28: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/28.jpg)
How far we should go?
Allow to do copy elisions through references?
Allow to decompose default destructible types and do copy elisions for subobjects? (P0878R0 “V. Proposed wording 1”)
Allow to decompose and do copy elisions for subobjects? (P0878R0 “V. Proposed wording 2”)
Allow elisions to work not only for functions' returns?
Allow all of the above? (P0889R0 “VI. Proposed wording”)
28 / 50
![Page 29: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/29.jpg)
FAQ
![Page 30: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/30.jpg)
[*] Does it break user code?
![Page 31: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/31.jpg)
[*] Does it break user code?
Yes
31 / 50
![Page 32: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/32.jpg)
[*] Does it break user code?
Yes, I'm 100% sure
32 / 50
![Page 33: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/33.jpg)
[*] Does it break user code?
Yes, I'm 100% sure
Good news: it breaks only unportable code
Code where generally-accepted constraint for a copy constructor is not satisfied: "After the definition T u = v;, u is equal to v".
33 / 50
![Page 34: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/34.jpg)
Why the code is unportable?
Language and Library heavily rely on “After the definition T u = v;, u is equal to v”
Ranges TS force that requirement
Library implicitly requires objects after copy/assignment/move to be equal in [container.requirements.general]
Algorithms do not work well if that constraint is not satisfied
Complexities are described as "At most [...] swaps" or "Approximately [...] swaps"
Algorithms sometimes do not specify the order of copying/swapping
[class.copy.elision] implicitly relies on that constraint
[class.copy.elision] is not mandatory!
Guaranteed copy elision implicitly relied on that constraint34 / 50
![Page 35: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/35.jpg)
Why the code is unportable?
C++ Language and Library heavily rely on “After the definition T u = v;, u is equal to v”
WG21 has been relying on that constraint for a long time and classes that violate that constraint are already unportable across platforms/Standard versions.
35 / 50
![Page 36: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/36.jpg)
Is it important?
![Page 37: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/37.jpg)
Are those problems important for users?
Runtime performance
Binary sizes
Compile times
Language usage simplicity and teach-ability
37 / 50
![Page 38: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/38.jpg)
Those problems are important for users!
Runtime performance
Binary sizes
Compile times
Language usage simplicity and teach-ability
Here are only some EWG papers from 2018 mailings that are related to those problems:
[[move_relocates]], [[likely]], trivial virtual destructors, zero-overhead exceptions, [[no_unique_address]], Modules, down with typename …
There's even more papers for LEWG that try to improve some of those
38 / 50
![Page 39: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/39.jpg)
Is it possible to implement right now?
![Page 40: P0889: Ultimate copy elisions and P0878R0: Subobjects copy ... elisions v2.pdf · Problems that P0889 addresses Compilers are forced to inline constructors+destructors and optimize](https://reader030.vdocuments.net/reader030/viewer/2022040414/5f20b8ca3d033a4ea70d0b57/html5/thumbnails/40.jpg)
Is it possible to implement right now?
Yes, but it would be hard.
Anyway, this proposal does not require any of the optimizations from examples. The proposal simply attempts to relax copy elision rules to allow those optimizations someday.
40 / 50