जीसीसी 4.8 इसके साथ क्या करता है यह देखने के लिए विघटित करते हैं
के बिना __builtin_expect
#include "stdio.h"
#include "time.h"
int main() {
/* Use time to prevent it from being optimized away. */
int i = !time(NULL);
if (i)
printf("%d\n", i);
puts("a");
return 0;
}
संकलन और जीसीसी 4.8.2 x86_64 लिनक्स के साथ विघटित:
gcc -c -O3 -std=gnu11 main.c
objdump -dr main.o
आउटपुट:
0000000000000000 <main>:
0: 48 83 ec 08 sub $0x8,%rsp
4: 31 ff xor %edi,%edi
6: e8 00 00 00 00 callq b <main+0xb>
7: R_X86_64_PC32 time-0x4
b: 48 85 c0 test %rax,%rax
e: 75 14 jne 24 <main+0x24>
10: ba 01 00 00 00 mov $0x1,%edx
15: be 00 00 00 00 mov $0x0,%esi
16: R_X86_64_32 .rodata.str1.1
1a: bf 01 00 00 00 mov $0x1,%edi
1f: e8 00 00 00 00 callq 24 <main+0x24>
20: R_X86_64_PC32 __printf_chk-0x4
24: bf 00 00 00 00 mov $0x0,%edi
25: R_X86_64_32 .rodata.str1.1+0x4
29: e8 00 00 00 00 callq 2e <main+0x2e>
2a: R_X86_64_PC32 puts-0x4
2e: 31 c0 xor %eax,%eax
30: 48 83 c4 08 add $0x8,%rsp
34: c3 retq
स्मृति में निर्देश क्रम अपरिवर्तित था: पहले printf
और फिर puts
और retq
वापसी।
साथ में __builtin_expect
अब इसके if (i)
साथ बदलें :
if (__builtin_expect(i, 0))
और हमें मिलता है:
0000000000000000 <main>:
0: 48 83 ec 08 sub $0x8,%rsp
4: 31 ff xor %edi,%edi
6: e8 00 00 00 00 callq b <main+0xb>
7: R_X86_64_PC32 time-0x4
b: 48 85 c0 test %rax,%rax
e: 74 11 je 21 <main+0x21>
10: bf 00 00 00 00 mov $0x0,%edi
11: R_X86_64_32 .rodata.str1.1+0x4
15: e8 00 00 00 00 callq 1a <main+0x1a>
16: R_X86_64_PC32 puts-0x4
1a: 31 c0 xor %eax,%eax
1c: 48 83 c4 08 add $0x8,%rsp
20: c3 retq
21: ba 01 00 00 00 mov $0x1,%edx
26: be 00 00 00 00 mov $0x0,%esi
27: R_X86_64_32 .rodata.str1.1
2b: bf 01 00 00 00 mov $0x1,%edi
30: e8 00 00 00 00 callq 35 <main+0x35>
31: R_X86_64_PC32 __printf_chk-0x4
35: eb d9 jmp 10 <main+0x10>
printf
(संकलित __printf_chk
), समारोह के अंत करने के लिए ले जाया गया था के बाद puts
के रूप में अन्य उत्तर ने उल्लेख किया और बदले शाखा भविष्यवाणी में सुधार होगा।
तो यह मूल रूप से एक ही है:
int main() {
int i = !time(NULL);
if (i)
goto printf;
puts:
puts("a");
return 0;
printf:
printf("%d\n", i);
goto puts;
}
यह अनुकूलन के साथ नहीं किया गया था -O0
।
लेकिन __builtin_expect
बिना किसी उदाहरण के तेजी से चलने वाला उदाहरण लिखने का सौभाग्य , इन दिनों सीपीयू वास्तव में स्मार्ट हैं । मेरी भोली कोशिश यहाँ हैं ।
सी ++ 20 [[likely]]
और[[unlikely]]
C ++ 20 ने उन C ++ बिल्ट-इन को मानकीकृत किया है: यदि C-20 की संभावना / संभावना नहीं है, तो if-else स्टेटमेंट में उनका उपयोग कैसे करें (वे एक वाक्य!) एक ही काम करेंगे।