Làm cách nào để ngăn gcc tối ưu hóa một số câu lệnh trong C?


107

Để làm bẩn trang (bật bit bẩn trong mục nhập bảng trang), tôi chạm vào các byte đầu tiên của trang như sau:

pageptr[0] = pageptr[0];

Nhưng trong thực tế, gcc sẽ bỏ qua câu lệnh bằng cách loại bỏ cửa hàng chết. Để ngăn gcc tối ưu hóa nó, tôi viết lại câu lệnh như sau:

volatile int tmp;
tmp = pageptr[0];
pageptr[0] = tmp;

Có vẻ như thủ thuật này hoạt động, nhưng hơi xấu xí. Tôi muốn biết có bất kỳ chỉ thị hoặc cú pháp nào có tác dụng tương tự không? Và tôi không muốn sử dụng một -O0lá cờ, vì nó cũng sẽ mang lại hình phạt hiệu quả cao.


8
@Mark -O0 sẽ ngừng tối ưu hóa, nhưng cũng làm chậm hiệu suất chương trình. Tôi chỉ muốn ngăn chặn việc tối ưu hóa đoạn mã này: P
ZelluX

Tôi muốn nói thêm rằng trong quá khứ, ngay cả việc sử dụng -O0cũng không ngăn chặn được "tối ưu hóa" mã chết, ví dụ: khi GCC phát hiện một số mã không có tác dụng, nó chỉ cần loại bỏ nó. AFAIK đây là một giai đoạn thậm chí trước đó -O0... Nhưng đó chỉ là kinh nghiệm của tôi
Smoothware

Câu trả lời:


91

Tắt tối ưu hóa sẽ khắc phục được sự cố, nhưng không cần thiết. Một giải pháp thay thế an toàn hơn là làm cho trình biên dịch tối ưu hóa lưu trữ bằng cách sử dụng bộ định volatileloại là bất hợp pháp .

// Assuming pageptr is unsigned char * already...
unsigned char *pageptr = ...;
((unsigned char volatile *)pageptr)[0] = pageptr[0];

Bộ định volatileloại kiểu hướng dẫn trình biên dịch nghiêm ngặt về việc lưu trữ và tải bộ nhớ. Một mục đích volatilelà để trình biên dịch biết rằng việc truy cập bộ nhớ có các tác dụng phụ và do đó phải được bảo toàn. Trong trường hợp này, cửa hàng có tác dụng phụ là gây ra lỗi trang và bạn muốn trình biên dịch giữ lại lỗi trang.

Bằng cách này, mã xung quanh vẫn có thể được tối ưu hóa và mã của bạn có thể di động đến các trình biên dịch khác không hiểu cú pháp #pragmahoặc GCC __attribute__.


2
Tôi sẽ nói điều này tốt hơn là tắt tối ưu hóa. Bạn vẫn có thể hưởng lợi từ các tối ưu hóa khác bằng cách sử dụng phương pháp này.
Ben S

3
Giải pháp của Dietrich Epp không hoạt động trong trình biên dịch ARM4.1 . Ngay cả giải pháp của ZelluX cũng không hoạt động. Phương pháp thay thế để làm cho điều này hoạt động cho ARM4.1 nằm trong giải pháp của ZelluX, hãy biến ' temp ' thành một biến dễ bay hơi toàn cầu .
Oculus Dexter

1
Điều đó khá tệ đối với trình biên dịch nói trên.
Alexey Frunze

1
@Shocker: GCC vẫn có thể tối ưu hóa biến mà không cần tối ưu hóa truy cập bộ nhớ thực tế. Đó là những vấn đề khác nhau.
Dietrich Epp

2
@jww: cách sử dụng này phù hợp với những gì được mô tả trong bài đăng blog đó. volatilecó nghĩa là truy cập bộ nhớ phải diễn ra như được viết, đó là chính xác những gì chúng ta muốn. Nói cách khác, chúng tôi đã suy nghĩ kỹ về nó, và nó có nghĩa là những gì chúng tôi nghĩ.
Dietrich Epp

184

Bạn có thể dùng

#pragma GCC push_options
#pragma GCC optimize ("O0")

your code

#pragma GCC pop_options

để tắt tối ưu hóa kể từ GCC 4.4.

Xem tài liệu GCC nếu bạn cần thêm chi tiết.


3
Tuy nhiên, điều đáng chú ý là điều này chỉ hoạt động trên toàn bộ chức năng chứ không phải trên các trạng thái cụ thể: gcc.gnu.org/onlineocs/gcc-4.8.2/gcc/… "Mỗi chức năng được xác định sau thời điểm này giống như thuộc tính if (( tối ưu hóa ("STRING"))) đã được chỉ định cho chức năng đó. ".
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

134

Thay vì sử dụng các pragmas mới, bạn cũng có thể sử dụng __attribute__((optimize("O0")))cho nhu cầu của mình. Điều này có lợi thế là chỉ áp dụng cho một hàm duy nhất và không phải tất cả các hàm được định nghĩa trong cùng một tệp.

Ví dụ sử dụng:

void __attribute__((optimize("O0"))) foo(unsigned char data) {
    // unmodifiable compiler code
}

3
Điều gì sẽ xảy ra nếu tôi không sử dụng một -Oleveltùy chọn nhưng tôi đã sử dụng các tùy chọn cá nhân mà nó bật riêng lẻ? (Trong trường hợp của tôi, tôi không thể xác định đâu là tùy chọn tối ưu hóa riêng lẻ đang phá vỡ mã) .
dùng2284570
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.