c++ named return value optimization · void create( buffer< vector >* ret) {vector...

64
C++ Named Return Value Optimization

Upload: others

Post on 26-Jul-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

C++Named Return Value Optimization

Page 3: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,
Page 4: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

auto create() -> T{ T castor /* initialize */; // ... return castor;}

void use(){ T pollux = create(); // ...}

Page 5: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object resource

Page 6: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ Type variable /* initialize */; // ... }// ...

Page 7: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ Type variable /* initialize */; // ... }return stuff;

Page 8: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ Type variable /* initialize */; // ... }throw stuff;

Page 9: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object clean-up scope left destroyed executed

Page 10: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

class Type{ // ...

~Type() { // clean-up code }

};

Page 11: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ Type variable /* init */ ; Type other_var = variable; // ...}

Page 12: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object clean-up different independent independent

Page 13: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ Type variable /* init */ ; { Type other_var = variable; // ... } // ...}

Page 14: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object resource

Page 15: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,
Page 16: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

int

MyInt

array<int, 10>

vector<int>

Page 17: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ int castor = 0; int pollux = castor;

assert(castor == pollux);

castor = 1729; pollux = -1;

assert(castor != pollux);}

Page 18: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ vector<int> castor(1000); vector<int> pollux = castor;

assert(castor == pollux);

castor.at(42) = 1729; pollux.at(42) = -1;

assert(castor != pollux);}

Page 19: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

int

MyInt

array<int, 10>

vector<int> special

Page 20: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

vector<int> memory allocation

object resource

Page 21: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

{ vector<int> castor(1000); vector<int> pollux = castor;

assert(castor == pollux);

castor.at(42) = 1729; pollux.at(42) = -1;

assert(castor != pollux);}

Page 22: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object resource different independent independent

Page 23: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object resource

variable object resource

initialize from copy

copy clone

Page 24: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

auto create() -> vector<int>{ vector<int> castor(1000); // ... return castor;}

void use(){ vector<int> pollux = create(); // ...}

Page 25: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object resource

Page 26: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,
Page 27: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

int_pair p() { int_pair r = {0}; return r;}

int_quadruple q() { int_quadruple r = {0}; return r;}

movl $0, %eaxret

movl $0, %eaxmovl $0, %edxret

Page 28: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

callee(called function)

caller

register 0

register 1

register 2...

calls

sets

reads

Page 29: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

int_pair p() { int_pair r = {0}; return r;}

int_quadruple q() { int_quadruple r = {0}; return r;}

int_octuple o() { int_octuple r = {0}; return r;}

movl $0, %eaxret

movl $0, %eaxmovl $0, %edxret

movq %rdi, %raxmovl $0, (%rdi)movl $0, 4(%rdi)movl $0, 8(%rdi)movl $0, 12(%rdi)movl $0, 16(%rdi)movl $0, 20(%rdi)movl $0, 24(%rdi)movl $0, 28(%rdi)ret

Page 30: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

callee(called function)

caller

register 0

register 1

register 2...space for

return value

sets addressread

s add

ress

writes to address

calls

Page 31: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,
Page 32: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

register 0

register 1

register 2

RAM register

Page 33: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

register 0

register 1

register 2

RAM register

object@ address 2

size 4

Page 34: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

register 0

register 1

register 2

RAM register

object@ address 2

size 4

Page 35: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,
Page 36: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

object object

Page 37: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

trivially copyable

Page 38: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

callee(called function)

caller

register 0

register 1

register 2...space for

return value

sets addressread

s add

ress

writes to address

calls

Page 39: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object resource

indirect returnfor non-trivially-copyable

Page 40: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,
Page 41: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

void use(){

vector<int> pollux = create();

// ...}

auto create() -> vector<int>{ vector<int> castor(1000); // ... return castor;}

Page 42: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

void use(){ buffer< vector<int> > future_pollux; create(&future_pollux); vector<int>& pollux = future_pollux; // ...}

void create(buffer< vector<int> >* ret){ vector<int> castor(1000); // ... new(ret) vector<int>(castor);}

Page 43: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

void create( buffer< vector<int> >* ret){

vector<int> castor(1000);

new(ret) vector<int>(castor);

}

pushq %rbx

subq $32, %rspmovq %rdi, %rbxmovl $1000, %esimovq %rsp, %rdicall vector<int>::vector(int)

movq %rsp, %rsimovq %rbx, %rdicall vector<int> ::vector(vector<int> const&)

movq %rsp, %rdicall vector<int>::~vector()movq %rbx, %raxaddq $32, %rsppopq %rbxret

Page 44: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

void create( buffer< vector<int> >* ret){

new(ret) vector<int>(1000);

}

pushq %rbx

movq %rdi, %rbxmovl $1000, %esi

call vector<int>::vector(int)

movq %rbx, %raxpopq %rbxret

Page 45: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

NRVO=

indirect return- unneccesary operations

Page 46: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

void use(){

vector<int> pollux = create();

// ...}

auto create() -> vector<int>{ vector<int> castor(1000); // ... return castor;}

Page 47: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

castorobject resource

different same same

pollux

Page 48: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

observable behaviour is guaranteedbut not how it is achieved

Page 49: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

int x = 0;

for(int i = 0; i < 100; ++i) x += i;

cout << x; mov edi, offset std::coutmov esi, 4950call ostream::operator<<(int)

Page 50: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

observable behaviour is guaranteedbut not how it is achieved

*except NRVO / copy elision

Page 51: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

resource managementis

potentially observable

Page 52: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

limits of NRVO

● local variable

●same type as return type

Page 53: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

auto no_nrvo() -> vector<int>{ array< vector<int>, 2 > ogre;

return ogre.at(0);}

Page 54: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

limits of NRVO

● local variable

●same type as return type

●complete object

Page 55: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

auto nrvo(bool b) -> vector<int>{ vector<int> thor(500); vector<int> loki(900);

if(b) return thor; else return loki;}

Page 56: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

limits of NRVO

● local variable

●same type as return type

●complete object

●compiler smartness

Page 57: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

auto nrvo() -> vector<int>{ vector<int> thor(500); vector<int> loki(900);

if(read_char() == 'a') return thor; else return loki;}

Page 58: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

limits of NRVO

● local variable

●same type as return type

●complete object

●compiler smartness

●observable behaviour

Page 59: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,
Page 60: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

variable object resource

variable object

Page 61: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

moving is great! but...● for some types it is still slow

● don’t want to write it explicitly

Page 62: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

auto nrvo() -> vector<int>{ vector<int> thor(500); vector<int> loki(900);

if(read_char() == 'a') return thor; else return loki;}

Page 63: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

NRVO > move > copy

Page 64: C++ Named Return Value Optimization · void create( buffer< vector >* ret) {vector castor(1000); new(ret) vector(castor);} pushq %rbx subq $32,

auto no_nrvo() -> vector<int>{ vector<int> thor(500); vector<int> loki(900);

if(read_char() == 'a') return move(thor); else return move(loki);}