Як запобігти оптимізації gcc деяких висловлювань у C?


107

Для того, щоб зробити сторінку брудною (увімкнувши брудний біт у записі таблиці сторінки), я торкаюся перших байтів сторінки таким чином:

pageptr[0] = pageptr[0];

Але на практиці gcc ігнорує заяву шляхом усунення мертвих магазинів. Щоб запобігти оптимізації gcc, я переписую заяву наступним чином:

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

Здається, фокус працює, але дещо некрасиво. Мені хотілося б знати, чи є якісь директиви чи синтаксис, які мають такий же ефект? І я не хочу використовувати -O0прапор, оскільки він також принесе чудове покарання.


8
@Mark -O0 зупинить оптимізацію, але також сповільнить продуктивність програми. Я просто хочу запобігти оптимізації цього фрагмента коду: P
ZelluX

Я хотів би додати, що в минулому навіть використання -O0не заважало мертвій коді "оптимізації", наприклад, коли GCC виявляє якийсь код не має ефекту, він просто видаляє його. AFAIK це етап ще до -O0... Але це тільки мій досвід
smoothware

Відповіді:


91

Вимкнення оптимізації виправляє проблему, але вона зайва. Більш безпечною альтернативою є забороняти компілятору незаконне оптимізацію магазину за допомогою volatileкласифікатора типу.

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

Класифікатор volatileтипу вказує компілятору бути суворим щодо зберігання пам'яті та навантажень. Одна з цілей volatileполягає в тому, щоб повідомити компілятору про те, що доступ до пам'яті має побічні ефекти, і тому їх потрібно зберігати. У цьому випадку у магазину є побічний ефект спричинення помилок сторінки, і ви хочете, щоб компілятор зберігав помилку сторінки.

Таким чином, оточуючий код все ще можна оптимізувати, а ваш код переноситься для інших компіляторів, які не розуміють GCC #pragmaчи __attribute__синтаксис.


2
Я б сказав, що це краще, ніж вимкнення оптимізацій. Ви можете скористатися іншими оптимізаціями за допомогою цього методу.
Ben S

3
Рішення Dietrich Epp не працює під компілятором ARM4.1 . Навіть рішення ZelluX не працює. Альтернативний спосіб зробити цю роботу для ARM4.1 є у рішенні ZelluX, зробіть ' temp ' глобальною мінливою змінною .
Oculus Dexter

1
Це досить погано для зазначеного компілятора.
Олексій Фрунзе

1
@Shocker: GCC все ще може оптимізувати змінну, не оптимізуючи фактичний доступ до пам'яті. Це різні питання.
Дітріх Епп

2
@jww: це використання відповідає тому, що описано в цій публікації в блозі. volatileозначає, що доступ до пам'яті повинен відбуватися як записаний, саме цього ми хочемо. Іншими словами, ми ретельно продумали це, і це означає, що ми думаємо, що це означає.
Дітріх Епп

184

Можна використовувати

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

your code

#pragma GCC pop_options

відключити оптимізацію, оскільки GCC 4.4.

Дивіться документацію GCC, якщо вам потрібні додаткові деталі.


3
Однак варто зазначити, що це працює лише на цілі функції, а не на конкретні статуси : gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/… "Кожна функція, яка визначається після цієї точки, є як атрибут (( для цієї функції було вказано оптимізувати ("STRING")). "
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

134

Замість використання нових прагм ви також можете використовувати __attribute__((optimize("O0")))для своїх потреб. Це має перевагу лише в застосуванні до однієї функції, а не до всіх функцій, визначених в одному файлі.

Приклад використання:

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

3
Що робити, якщо я не використовую -Olevelваріант, але я використав окремі параметри, які він включається окремо? (У моєму випадку я не можу визначити, який є варіант індивідуальної оптимізації, який порушує код) .
користувач2284570
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.