Hãy dịch ngược để xem GCC 4.8 làm gì với nó
Blagovest đã đề cập đến việc đảo ngược chi nhánh để cải thiện đường ống, nhưng các trình biên dịch hiện tại có thực sự làm được không? Hãy cùng tìm hiểu!
Không có __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)
puts("a");
return 0;
}
Biên dịch và dịch ngược với GCC 4.8.2 x86_64 Linux:
gcc -c -O3 -std=gnu11 main.c
objdump -dr main.o
Đầu ra:
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 0a jne 1a <main+0x1a>
10: bf 00 00 00 00 mov $0x0,%edi
11: R_X86_64_32 .rodata.str1.1
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
Thứ tự lệnh trong bộ nhớ không thay đổi: đầu tiên puts
và sau đó retq
trả về.
Với __builtin_expect
Bây giờ thay thế if (i)
bằng:
if (__builtin_expect(i, 0))
và chúng tôi nhận được:
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 07 je 17 <main+0x17>
10: 31 c0 xor %eax,%eax
12: 48 83 c4 08 add $0x8,%rsp
16: c3 retq
17: bf 00 00 00 00 mov $0x0,%edi
18: R_X86_64_32 .rodata.str1.1
1c: e8 00 00 00 00 callq 21 <main+0x21>
1d: R_X86_64_PC32 puts-0x4
21: eb ed jmp 10 <main+0x10>
Đã puts
được chuyển đến cuối của chức năng, sự retq
trở lại!
Mã mới về cơ bản giống như:
int i = !time(NULL);
if (i)
goto puts;
ret:
return 0;
puts:
puts("a");
goto ret;
Tối ưu hóa này đã không được thực hiện với -O0
.
Nhưng chúc may mắn khi viết một ví dụ chạy nhanh __builtin_expect
hơn mà không có, CPU thực sự rất thông minh ngày đó . Những nỗ lực ngây thơ của tôi đang ở đây .
C ++ 20 [[likely]]
và[[unlikely]]
C ++ 20 đã tiêu chuẩn hóa các phần tử tích hợp C ++ này: Cách sử dụng thuộc tính có khả năng / không có khả năng của C ++ 20 trong câu lệnh if-other Họ có thể (một cách chơi chữ!) Làm điều tương tự.