x

y

Method Name Code Method A { // Limit the scope of t

int t = x;

x = y;

y = t;

} Method B x ^= y;

y ^= x;

x ^= y; Method C x ^= y ^= x ^= y; Method D x = x + y;

y = x - y;

x = x - y; Method E std::swap(x, y);

-Wall

-g

objdump -S

username@computername$cat swap.cc #include <iostream> // Contains std::cout and std::endl #include <algorithm> // Contains std::swap void PrintValues(int x, int y) { std::cout << "x is " << x << std::endl; std::cout << "y is " << y << std::endl; } int main() { int x = 3; int y = 5; PrintValues(x, y); { int t = x; // Method A x = y; y = t; } PrintValues(x, y); x ^= y; // Method B y ^= x; x ^= y; PrintValues(x, y); x ^= y ^= x ^= y; // Method C PrintValues(x, y); x = x + y; // Method D y = x - y; x = x - y; PrintValues(x, y); std::swap(x, y); // Method E PrintValues(x, y); } username@computername$g++ -Wall -g swap.cc swap.cc: In function 'int main()': swap.cc:29: warning: operation on 'x' may be undefined username@computername$

x

x

int x = 3; 80486da: c7 45 f8 03 00 00 00 movl $0x3,-0x8(%ebp) int y = 5; 80486e1: c7 45 f4 05 00 00 00 movl $0x5,-0xc(%ebp) PrintValues(x, y); 80486e8: 8b 45 f4 mov -0xc(%ebp),%eax 80486eb: 8b 55 f8 mov -0x8(%ebp),%edx 80486ee: 89 44 24 04 mov %eax,0x4(%esp) 80486f2: 89 14 24 mov %edx,(%esp) 80486f5: e8 52 ff ff ff call 804864c <_Z11PrintValuesii> { int t = x; // Method A 80486fa: 8b 45 f8 mov -0x8(%ebp),%eax 80486fd: 89 45 fc mov %eax,-0x4(%ebp) x = y; 8048700: 8b 45 f4 mov -0xc(%ebp),%eax 8048703: 89 45 f8 mov %eax,-0x8(%ebp) y = t; 8048706: 8b 45 fc mov -0x4(%ebp),%eax 8048709: 89 45 f4 mov %eax,-0xc(%ebp) } PrintValues(x, y); 804870c: 8b 45 f4 mov -0xc(%ebp),%eax 804870f: 8b 55 f8 mov -0x8(%ebp),%edx 8048712: 89 44 24 04 mov %eax,0x4(%esp) 8048716: 89 14 24 mov %edx,(%esp) 8048719: e8 2e ff ff ff call 804864c <_Z11PrintValuesii> x ^= y; // Method B 804871e: 8b 55 f8 mov -0x8(%ebp),%edx 8048721: 8b 45 f4 mov -0xc(%ebp),%eax 8048724: 31 d0 xor %edx,%eax 8048726: 89 45 f8 mov %eax,-0x8(%ebp) y ^= x; 8048729: 8b 55 f4 mov -0xc(%ebp),%edx 804872c: 8b 45 f8 mov -0x8(%ebp),%eax 804872f: 31 d0 xor %edx,%eax 8048731: 89 45 f4 mov %eax,-0xc(%ebp) x ^= y; 8048734: 8b 55 f8 mov -0x8(%ebp),%edx 8048737: 8b 45 f4 mov -0xc(%ebp),%eax 804873a: 31 d0 xor %edx,%eax 804873c: 89 45 f8 mov %eax,-0x8(%ebp) PrintValues(x, y); 804873f: 8b 45 f4 mov -0xc(%ebp),%eax 8048742: 8b 55 f8 mov -0x8(%ebp),%edx 8048745: 89 44 24 04 mov %eax,0x4(%esp) 8048749: 89 14 24 mov %edx,(%esp) 804874c: e8 fb fe ff ff call 804864c <_Z11PrintValuesii> x = x + y; // Method D 8048751: 8b 55 f8 mov -0x8(%ebp),%edx 8048754: 8b 45 f4 mov -0xc(%ebp),%eax 8048757: 8d 04 02 lea (%edx,%eax,1),%eax 804875a: 89 45 f8 mov %eax,-0x8(%ebp) y = x - y; 804875d: 8b 55 f8 mov -0x8(%ebp),%edx 8048760: 8b 45 f4 mov -0xc(%ebp),%eax 8048763: 89 d1 mov %edx,%ecx 8048765: 29 c1 sub %eax,%ecx 8048767: 89 c8 mov %ecx,%eax 8048769: 89 45 f4 mov %eax,-0xc(%ebp) x = x - y; 804876c: 8b 55 f8 mov -0x8(%ebp),%edx 804876f: 8b 45 f4 mov -0xc(%ebp),%eax 8048772: 89 d1 mov %edx,%ecx 8048774: 29 c1 sub %eax,%ecx 8048776: 89 c8 mov %ecx,%eax 8048778: 89 45 f8 mov %eax,-0x8(%ebp) PrintValues(x, y); 804877b: 8b 45 f4 mov -0xc(%ebp),%eax 804877e: 8b 55 f8 mov -0x8(%ebp),%edx 8048781: 89 44 24 04 mov %eax,0x4(%esp) 8048785: 89 14 24 mov %edx,(%esp) 8048788: e8 bf fe ff ff call 804864c <_Z11PrintValuesii> std::swap(x, y); // Method E 804878d: 8d 45 f4 lea -0xc(%ebp),%eax 8048790: 89 44 24 04 mov %eax,0x4(%esp) 8048794: 8d 45 f8 lea -0x8(%ebp),%eax 8048797: 89 04 24 mov %eax,(%esp) 804879a: e8 8b 00 00 00 call 804882a <_ZSt4swapIiEvRT_S1_> PrintValues(x, y); 804879f: 8b 45 f4 mov -0xc(%ebp),%eax 80487a2: 8b 55 f8 mov -0x8(%ebp),%edx 80487a5: 89 44 24 04 mov %eax,0x4(%esp) 80487a9: 89 14 24 mov %edx,(%esp) 80487ac: e8 9b fe ff ff call 804864c <_Z11PrintValuesii>

mov

movl

call

xor

lea

std::swap

sub

x

%ebp

y

PrintValues

y

x

%eax

%edx

%esp

PrintValues

x

%eax

%ebp

t

y

x

%edx

%eax

%eax

lea

-O2

int x = 3; int y = 5; PrintValues(x, y); 80486dc: c7 44 24 04 05 00 00 movl $0x5,0x4(%esp) 80486e3: 00 80486e4: c7 04 24 03 00 00 00 movl $0x3,(%esp) 80486eb: e8 7c ff ff ff call 804866c { int t = x; // Method A x = y; y = t; } PrintValues(x, y); 80486f0: c7 44 24 04 03 00 00 movl $0x3,0x4(%esp) 80486f7: 00 80486f8: c7 04 24 05 00 00 00 movl $0x5,(%esp) 80486ff: e8 68 ff ff ff call 804866c x ^= y; // Method B y ^= x; x ^= y; PrintValues(x, y); 8048704: c7 44 24 04 05 00 00 movl $0x5,0x4(%esp) 804870b: 00 804870c: c7 04 24 03 00 00 00 movl $0x3,(%esp) 8048713: e8 54 ff ff ff call 804866c x = x + y; // Method D y = x - y; x = x - y; PrintValues(x, y); 8048718: c7 44 24 04 03 00 00 movl $0x3,0x4(%esp) 804871f: 00 8048720: c7 04 24 05 00 00 00 movl $0x5,(%esp) 8048727: e8 40 ff ff ff call 804866c swap(x, y); // Method E PrintValues(x, y); 804872c: c7 44 24 04 05 00 00 movl $0x5,0x4(%esp) 8048733: 00 8048734: c7 04 24 03 00 00 00 movl $0x3,(%esp) 804873b: e8 2c ff ff ff call 804866c

PrintValues

x

y

bool NontrivialFunction(int x, int y, int base) { // I need a way to force x and y to be stored instead of completely optimized // away. So, here's the plan: if either of them are not prime, I will return // true and set them to zero. if (x < base * base && y < base * base) return false; if (x % base == 0) return true; if (y % base == 0) return true; return NontrivialFunction(x, y, base + 1); } ... // and this part is added to main() just after defining x and y if (NontrivialFunction(x, y, 2)) { x = 0; y = 0; }

NontrivialFunction

x

y

-O2

int x = 3; int y = 5; if (NontrivialFunction(x, y, 2)) { 8048739: c7 44 24 08 02 00 00 movl $0x2,0x8(%esp) 8048740: 00 8048741: c7 44 24 04 05 00 00 movl $0x5,0x4(%esp) 8048748: 00 8048749: c7 04 24 03 00 00 00 movl $0x3,(%esp) 8048750: e8 b7 fe ff ff call 804860c <_Z18NontrivialFunctioniii> 8048755: 84 c0 test %al,%al 8048757: 74 52 je 80487ab <main+0x81> 8048759: 31 db xor %ebx,%ebx 804875b: 31 f6 xor %esi,%esi 804875d: 31 ff xor %edi,%edi x = 0; y = 0; } PrintValues(x, y); 804875f: 89 74 24 04 mov %esi,0x4(%esp) 8048763: 89 1c 24 mov %ebx,(%esp) 8048766: e8 5b ff ff ff call 80486c6 <_Z11PrintValuesii> { int t = x; // Method A x = y; y = t; } PrintValues(x, y); 804876b: 89 5c 24 04 mov %ebx,0x4(%esp) 804876f: 89 34 24 mov %esi,(%esp) 8048772: e8 4f ff ff ff call 80486c6 <_Z11PrintValuesii> x ^= y; // Method B y ^= x; 8048777: 31 fb xor %edi,%ebx x ^= y; 8048779: 89 de mov %ebx,%esi 804877b: 31 fe xor %edi,%esi PrintValues(x, y); 804877d: 89 5c 24 04 mov %ebx,0x4(%esp) 8048781: 89 34 24 mov %esi,(%esp) 8048784: e8 3d ff ff ff call 80486c6 <_Z11PrintValuesii> x = x + y; // Method D y = x - y; x = x - y; PrintValues(x, y); 8048789: 89 74 24 04 mov %esi,0x4(%esp) 804878d: 89 1c 24 mov %ebx,(%esp) 8048790: e8 31 ff ff ff call 80486c6 <_Z11PrintValuesii> std::swap(x, y); // Method E PrintValues(x, y); 8048795: 89 5c 24 04 mov %ebx,0x4(%esp) 8048799: 89 34 24 mov %esi,(%esp) 804879c: e8 25 ff ff ff call 80486c6 <_Z11PrintValuesii> } 80487a1: 31 c0 xor %eax,%eax 80487a3: 8d 65 f4 lea -0xc(%ebp),%esp 80487a6: 5b pop %ebx 80487a7: 5e pop %esi 80487a8: 5f pop %edi 80487a9: 5d pop %ebp 80487aa: c3 ret int x = 3; int y = 5; if (NontrivialFunction(x, y, 2)) { 80487ab: bb 03 00 00 00 mov $0x3,%ebx 80487b0: be 05 00 00 00 mov $0x5,%esi 80487b5: bf 06 00 00 00 mov $0x6,%edi 80487ba: eb a3 jmp 804875f <main+0x35>

NontrivialFunction

NontrivialFunction(3, 5, 2)

x

y

%al

test

%al

je

%ebx

%esi

x ^ y

%edi

jmp

PrintValues

xor

pop

ret

main

x

%ebx

y

%esi

PrintValues(x, y)

PrintValues(y, x)

void NontrivialReferenceFunction(int& x, int& y) { // This is really just a fancy no-op, but the compiler doesn't know that. if (NontrivialFunction(x, y, 2)) { NontrivialReferenceFunction(x, y); } } ... // In main replacing the part about NontrivialFunction that we added in last time NontrivialReferenceFunction(x, y);

int x = 3; 8048768: c7 45 fc 03 00 00 00 movl $0x3,-0x4(%ebp) int y = 5; 804876f: c7 45 f8 05 00 00 00 movl $0x5,-0x8(%ebp) NontrivialReferenceFunction(x, y); 8048776: 8d 45 f8 lea -0x8(%ebp),%eax 8048779: 89 44 24 04 mov %eax,0x4(%esp) 804877d: 8d 45 fc lea -0x4(%ebp),%eax 8048780: 89 04 24 mov %eax,(%esp) 8048783: e8 de fe ff ff call 8048666 <_Z27NontrivialReferenceFunctionRiS_> PrintValues(x, y); 8048788: 8b 45 f8 mov -0x8(%ebp),%eax 804878b: 89 44 24 04 mov %eax,0x4(%esp) 804878f: 8b 45 fc mov -0x4(%ebp),%eax 8048792: 89 04 24 mov %eax,(%esp) 8048795: e8 5e ff ff ff call 80486f8 <_Z11PrintValuesii> { int t = x; // Method A 804879a: 8b 45 fc mov -0x4(%ebp),%eax x = y; 804879d: 8b 55 f8 mov -0x8(%ebp),%edx 80487a0: 89 55 fc mov %edx,-0x4(%ebp) y = t; 80487a3: 89 45 f8 mov %eax,-0x8(%ebp) } PrintValues(x, y); 80487a6: 89 44 24 04 mov %eax,0x4(%esp) 80487aa: 89 14 24 mov %edx,(%esp) 80487ad: e8 46 ff ff ff call 80486f8 <_Z11PrintValuesii> x ^= y; // Method B 80487b2: 8b 45 f8 mov -0x8(%ebp),%eax 80487b5: 8b 55 fc mov -0x4(%ebp),%edx 80487b8: 31 c2 xor %eax,%edx y ^= x; 80487ba: 31 d0 xor %edx,%eax 80487bc: 89 45 f8 mov %eax,-0x8(%ebp) x ^= y; 80487bf: 31 c2 xor %eax,%edx 80487c1: 89 55 fc mov %edx,-0x4(%ebp) PrintValues(x, y); 80487c4: 89 44 24 04 mov %eax,0x4(%esp) 80487c8: 89 14 24 mov %edx,(%esp) 80487cb: e8 28 ff ff ff call 80486f8 <_Z11PrintValuesii> x = x + y; // Method D 80487d0: 8b 55 f8 mov -0x8(%ebp),%edx 80487d3: 8b 45 fc mov -0x4(%ebp),%eax 80487d6: 01 d0 add %edx,%eax y = x - y; 80487d8: 89 c1 mov %eax,%ecx 80487da: 29 d1 sub %edx,%ecx 80487dc: 89 4d f8 mov %ecx,-0x8(%ebp) x = x - y; 80487df: 29 c8 sub %ecx,%eax 80487e1: 89 45 fc mov %eax,-0x4(%ebp) PrintValues(x, y); 80487e4: 89 4c 24 04 mov %ecx,0x4(%esp) 80487e8: 89 04 24 mov %eax,(%esp) 80487eb: e8 08 ff ff ff call 80486f8 <_Z11PrintValuesii> swap(_Tp& __a, _Tp& __b) { // concept requirements __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) _Tp __tmp = __a; 80487f0: 8b 45 fc mov -0x4(%ebp),%eax __a = __b; 80487f3: 8b 55 f8 mov -0x8(%ebp),%edx 80487f6: 89 55 fc mov %edx,-0x4(%ebp) __b = __tmp; 80487f9: 89 45 f8 mov %eax,-0x8(%ebp) std::swap(x, y); // Method E PrintValues(x, y); 80487fc: 89 44 24 04 mov %eax,0x4(%esp) 8048800: 89 14 24 mov %edx,(%esp) 8048803: e8 f0 fe ff ff call 80486f8 <_Z11PrintValuesii>

%ebp

std::swap

lea

NontrivialReferenceFunction

add

y

x

mov

xor

mov

%ecx

std::swap

_Tp

_Tp

int

__a

__b

_Tp

__tmp

mov

volatile

NontrivialReferenceFunction

PrintValues(x, y)

PrintValues(y, x)

NontrivialReferenceFunction

volatile

NontrivialFunction

algorithm

std::swap