2017-09-27 27 views
6

này được nhiều hơn hoặc ít hơn một đề nghị làm rõ về Casting a function pointer to another type với mã ví dụTối ưu hóa ra chức năng helper

struct my_struct; 
void my_callback_function(struct my_struct* arg); 
void do_stuff(void (*cb)(void*)); 

static void my_callback_helper(void* pv) 
{ 
    my_callback_function(pv); 
} 
int main() 
{ 
    do_stuff(&my_callback_helper); 
} 

Câu trả lời nói rằng một "tốt" trình biên dịch sẽ có thể tối ưu hóa ra các my_callback_helper() chức năng nhưng tôi tìm thấy không có trình biên dịch tại https://gcc.godbolt.org nào đó và chức năng helper được luôn tạo ra ngay cả khi nó just a jump to my_callback_function() (O3):

my_callback_helper: 
     jmp  my_callback_function 
main: 
     subq $8, %rsp 
     movl $my_callback_helper, %edi 
     call do_stuff 
     xorl %eax, %eax 
     addq $8, %rsp 
     ret 

Vì vậy, câu hỏi của tôi là: Có bất cứ điều gì trong tiêu chuẩn ngăn chặn trình biên dịch từ loại bỏ người trợ giúp?

+0

Theo kinh nghiệm của tôi, các trình biên dịch có xu hướng làm một công việc kém tại các cuộc gọi hàm con trỏ nội tuyến ngay cả khi giá trị của con trỏ hàm có thể được xác định tại thời gian biên dịch. Bạn có thể thử quăng vào từ khóa 'inline'. Theo tôi biết, không có gì trong tiêu chuẩn ngăn chặn tối ưu hóa. – Lundin

Trả lời

3

Không có gì trong tiêu chuẩn ngăn chặn trực tiếp tối ưu hóa này. Nhưng trong thực tế, không phải lúc nào cũng có thể cho các trình biên dịch khi chúng không có "bức tranh đầy đủ".

Bạn đã lấy địa chỉ my_callback_helper. Vì vậy, trình biên dịch không thể dễ dàng tối ưu hóa nó ra bởi vì nó không biết những gì do_stuff hiện với nó. Trong một mô-đun riêng biệt, trong đó do_stuff được xác định, trình biên dịch không biết rằng nó chỉ có thể sử dụng/gọi my_callback_function thay cho đối số của nó (my_callback_helper). Để tối ưu hóa hoàn toàn my_callback_helper, trình biên dịch cũng phải biết do_stuff là gì. Nhưng do_stuff là một hàm bên ngoài có định nghĩa không có sẵn cho trình biên dịch. Vì vậy, loại tối ưu hóa này có thể xảy ra nếu bạn cung cấp định nghĩa cho do_stuff và tất cả các cách sử dụng của nó.

+1

Điều này cũng nên được resloved bằng cách sử dụng tối ưu hóa thời gian liên kết (-flto với GCC) trong quá trình biên dịch và "liên kết" bước. – dbrank0

+0

Tôi nghĩ có lẽ nó bị cấm vì so sánh con trỏ khả năng. 'do_stuff()' có thể đang cố gắng so sánh con trỏ đã nhận với 'my_callback_function()'. Khi tối ưu hóa, phép so sánh sẽ nói 'my_callback_function == my_callback_helper' và có thể không hợp pháp đối với hai đối tượng khác nhau để có cùng địa chỉ. Nếu nó là bất hợp pháp, sau đó nó là một chút không may nhảy không thể được loại bỏ. Có lẽ nó sẽ tốt hơn cho fn-phôi được thực hiện xác định chứ không phải là undefined. – PSkocik

Các vấn đề liên quan