65,186
社区成员




#include <cstdlib>
#include <cstdio>
int test()
{
return rand();
}
int main(int, const char **)
{
int n = 0;
for (size_t i = 0; i < 10000000; i++)
{
n ^= test();
}
printf("%d\n", n);
for (size_t i = 0; i < 10000000; i++)
{
auto f = []()->int {return rand(); };
n ^= f();
}
printf("%d\n", n);
return 0;
}
$ g++ --std=c++11 --pedantic -g -O2 test.cpp
$ g++ --version
g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2
Copyright (C) 2014 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.
00000000004004b0 <main>:
4004b0: 55 push %rbp
4004b1: 53 push %rbx
4004b2: bd 80 96 98 00 mov $0x989680,%ebp
4004b7: 31 db xor %ebx,%ebx
4004b9: 48 83 ec 08 sub $0x8,%rsp
4004bd: 0f 1f 00 nopl (%rax)
4004c0: e8 db ff ff ff callq 4004a0 <rand@plt>
4004c5: 31 c3 xor %eax,%ebx
4004c7: 48 83 ed 01 sub $0x1,%rbp
4004cb: 75 f3 jne 4004c0 <main+0x10>
4004cd: 89 da mov %ebx,%edx
4004cf: be b4 06 40 00 mov $0x4006b4,%esi
4004d4: bf 01 00 00 00 mov $0x1,%edi
4004d9: 31 c0 xor %eax,%eax
4004db: bd 80 96 98 00 mov $0x989680,%ebp
4004e0: e8 ab ff ff ff callq 400490 <__printf_chk@plt>
4004e5: 0f 1f 00 nopl (%rax)
4004e8: e8 b3 ff ff ff callq 4004a0 <rand@plt>
4004ed: 31 c3 xor %eax,%ebx
4004ef: 48 83 ed 01 sub $0x1,%rbp
4004f3: 75 f3 jne 4004e8 <main+0x38>
4004f5: 89 da mov %ebx,%edx
4004f7: be b4 06 40 00 mov $0x4006b4,%esi
4004fc: bf 01 00 00 00 mov $0x1,%edi
400501: 31 c0 xor %eax,%eax
400503: e8 88 ff ff ff callq 400490 <__printf_chk@plt>
400508: 48 83 c4 08 add $0x8,%rsp
40050c: 31 c0 xor %eax,%eax
40050e: 5b pop %rbx
40050f: 5d pop %rbp
400510: c3 retq
两个循环体是一样的 callq (rand), xor, sub, jne 。
4004c0 - 4004cb
4004e8 - 4004f3; Listing generated by Microsoft (R) Optimizing Compiler Version 19.00.23026.0
include listing.inc
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC ?test@@YAMXZ ; test
PUBLIC main
PUBLIC __real@444a4c29
EXTRN _fltused:DWORD
pdata SEGMENT
$pdata$main DD imagerel $LN9
DD imagerel $LN9+128
DD imagerel $unwind$main
pdata ENDS
; COMDAT __real@444a4c29
CONST SEGMENT
__real@444a4c29 DD 0444a4c29r ; 809.19
CONST ENDS
xdata SEGMENT
$unwind$main DD 020e01H
DD 0700a720eH
xdata ENDS
; Function compile flags: /Odtp
; COMDAT ??R<lambda_a063bd16e7642c22fd3d9fd00722fd02>@@QEBAMXZ
_TEXT SEGMENT
this$ = 8
??R<lambda_a063bd16e7642c22fd3d9fd00722fd02>@@QEBAMXZ PROC ; <lambda_a063bd16e7642c22fd3d9fd00722fd02>::operator(), COMDAT
; 15 : auto f = []()->float {return 333 * 2.43; };
mov QWORD PTR [rsp+8], rcx
movss xmm0, DWORD PTR __real@444a4c29
ret 0
??R<lambda_a063bd16e7642c22fd3d9fd00722fd02>@@QEBAMXZ ENDP ; <lambda_a063bd16e7642c22fd3d9fd00722fd02>::operator()
_TEXT ENDS
; Function compile flags: /Odtp
_TEXT SEGMENT
$T1 = 32
f$2 = 33
i$3 = 40
i$4 = 48
__formal$ = 80
__formal$ = 88
main PROC
; 7 : {
$LN9:
mov QWORD PTR [rsp+16], rdx
mov DWORD PTR [rsp+8], ecx
push rdi
sub rsp, 64 ; 00000040H
; 8 : for (size_t i = 0; i < 10000000; i++)
mov QWORD PTR i$3[rsp], 0
jmp SHORT $LN4@main
$LN2@main:
mov rax, QWORD PTR i$3[rsp]
inc rax
mov QWORD PTR i$3[rsp], rax
$LN4@main:
cmp QWORD PTR i$3[rsp], 10000000 ; 00989680H
jae SHORT $LN3@main
; 9 : {
; 10 : test();
call ?test@@YAMXZ ; test
; 11 : }
jmp SHORT $LN2@main
$LN3@main:
; 12 :
; 13 : for (size_t i = 0; i < 10000000; i++)
mov QWORD PTR i$4[rsp], 0
jmp SHORT $LN7@main
$LN5@main:
mov rax, QWORD PTR i$4[rsp]
inc rax
mov QWORD PTR i$4[rsp], rax
$LN7@main:
cmp QWORD PTR i$4[rsp], 10000000 ; 00989680H
jae SHORT $LN6@main
; 14 : {
; 15 : auto f = []()->float {return 333 * 2.43; };
lea rax, QWORD PTR $T1[rsp]
mov rdi, rax
xor eax, eax
mov ecx, 1
rep stosb
; 16 : f();
lea rcx, QWORD PTR f$2[rsp]
call ??R<lambda_a063bd16e7642c22fd3d9fd00722fd02>@@QEBAMXZ ; <lambda_a063bd16e7642c22fd3d9fd00722fd02>::operator()
; 17 : }
jmp SHORT $LN5@main
$LN6@main:
; 18 : return 0;
xor eax, eax
; 19 : }
add rsp, 64 ; 00000040H
pop rdi
ret 0
main ENDP
_TEXT ENDS
; Function compile flags: /Odtp
_TEXT SEGMENT
?test@@YAMXZ PROC ; test
; 4 : return 333 * 2.43;
movss xmm0, DWORD PTR __real@444a4c29
; 5 : }
ret 0
?test@@YAMXZ ENDP ; test
_TEXT ENDS
END
上个没优化的
$ cat test.cpp
#include <cstdlib>
float test()
{
return 333 * 2.43;
}
int main(int, const char **)
{
for (size_t i = 0; i < 10000000; i++)
{
test();
}
for (size_t i = 0; i < 10000000; i++)
{
auto f = []()->float {return 333 * 2.43; };
f();
}
return 0;
}
$ g++ --std=c++11 --pedantic -g -O2 test.cpp
$ g++ --version
g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2
Copyright (C) 2014 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.
$ objdump -d a.out > a.ss
a.ss
0000000000400400 <main>:
400400: 31 c0 xor %eax,%eax
400402: c3 retq
优化之后 main 只剩了一句 return 0;