Tôi đang phát triển một ứng dụng có hiệu suất rất quan trọng. Tôi muốn GCC dịch một số lời gọi cụ thể đến memset() như một lệnh với một tiền tố lặp lại như "rep stos QWORD PTR es: [rdi], rax". GCC thực hiện điều này tự động khi kích thước vừa được biết và nhỏ. Tuy nhiên, GCC ánh xạ các cuộc gọi đến memset() với độ dài ngẫu nhiên thông qua một lời gọi đến memset() thông qua PLT, điều này gây ra sự hiểu sai chi nhánh vì bộ nhớ cache dự đoán nhánh là lạnh.Buộc GCC sử dụng tiền tố lặp lại trong memset() gọi
Có cách nào để buộc GCC phải làm những gì tôi muốn (ngoài lắp ráp nội tuyến) không? Lưu ý rằng tôi không muốn hành vi này cho toàn bộ chương trình, chỉ cho một số cuộc gọi memset cụ thể().
Trên một chủ đề liên quan, tôi cũng quan tâm đến bất cứ hack mà ngăn GCC từ nhánh khi một hướng dẫn cmovcc sẽ thực hiện công việc (Tôi biết về việc sử dụng &, +, vv. Thay vì & &).
Cảm ơn bạn rất nhiều vì đã giúp đỡ.
@FrankH:
Đó là cơ bản những gì tôi đã kết thúc làm. Đây là mã của tôi:
static finline void app_zero(void *dst, uint32_t size, uint32_t count)
{
// Warning: we tell gcc to use 'dst' both as source and destination here.
// This does not cause problems because we don't reuse 'dst'.
#ifdef APP_ARCH_X86
#define STOS(X,Y) do { \
int c = (size/Y)*count; \
__asm__ __volatile__("cld; xor %%eax, %%eax; rep stos"X"\n\n" \
: "+D"(dst), "+c"(c) :: "rax", "flags"); \
} while (0)
if (size % 8 == 0) STOS("q", 8);
else if (size % 4 == 0) STOS("l", 4);
else if (size % 2 == 0) STOS("w", 2);
else STOS("b", 1);
#undef STOS
#else
memset(dst, 0, size*count);
#endif
}
Lưu ý rằng ví dụ của bạn hoạt động trong thiết lập thử nghiệm của bạn, nhưng nó sẽ không làm việc thường. GCC có thể thay đổi cờ hướng, do đó, hướng dẫn cld
là cần thiết. Hơn nữa, bạn phải nói với gcc rằng %rdi
và %rcx
sẽ thay đổi bằng cách hướng dẫn stos
, và vì gcc sẽ không cho phép bạn xác định rằng một thanh ghi là cả một đầu vào và clobbered, bạn phải sử dụng vụng "+"
cú pháp (mà cũng sẽ làm hỏng giá trị đầu vào của bạn).
Điều này không tối ưu do lệnh 'cld', có độ trễ là 4 chu kỳ trên Nehalem. GCC theo dõi trạng thái đăng ký cờ nội bộ (AFAICT) vì vậy nó không cần phải ban hành lệnh đó mỗi lần.
Cách duy nhất tôi có thể nghĩ đến thậm chí cố gắng đạt được điều gì đó chỉ áp dụng cho một số phần nhất định của mã sẽ là thuộc tính của GCC (các thuộc tính của hàm, biến và kiểu). Tuy nhiên, trong nháy mắt, không ai trong số họ đạt được những gì bạn đang tìm kiếm. – zxcdw
Cảm ơn, tôi xác nhận rằng không có thuộc tính/pragma nào như vậy tồn tại. –