Bagaimana cara mencegah gcc mengoptimalkan beberapa pernyataan di C?

107

Untuk membuat halaman kotor (mengaktifkan bit kotor di entri tabel halaman), saya menyentuh byte pertama halaman seperti ini:

pageptr[0] = pageptr[0];

Namun dalam praktiknya, gcc akan mengabaikan pernyataan tersebut dengan eliminasi penyimpanan mati. Untuk mencegah gcc mengoptimalkannya, saya menulis ulang pernyataan sebagai berikut:

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

Tampaknya triknya berhasil, tetapi agak jelek. Saya ingin tahu apakah ada arahan atau sintaksis yang memiliki efek yang sama? Dan saya tidak ingin menggunakan -O0bendera, karena itu akan membawa penalti untuk performa yang bagus juga.

ZelluX
sumber
8
@Mark -O0 akan menghentikan pengoptimalan, tetapi juga memperlambat kinerja program. Saya hanya ingin mencegah pengoptimalan cuplikan kode ini: P
ZelluX
Saya ingin menambahkan bahwa di masa lalu, bahkan menggunakan -O0tidak mencegah kode mati "optimasi", misalnya, ketika GCC mendeteksi beberapa kode tidak berpengaruh, itu hanya menghapusnya. AFAIK ini adalah tahap bahkan sebelumnya -O0... Tapi itu hanya pengalaman saya
smoothware

Jawaban:

91

Mematikan pengoptimalan akan memperbaiki masalah, tetapi itu tidak perlu. Alternatif yang lebih aman adalah membuatnya ilegal bagi kompilator untuk mengoptimalkan penyimpanan dengan menggunakan volatiletipe qualifier.

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

The volatilejenis kualifikasi menginstruksikan compiler untuk menjadi ketat tentang toko memori dan beban. Salah satu tujuannya volatileadalah untuk memberi tahu kompilator bahwa akses memori memiliki efek samping, dan karena itu harus dipertahankan. Dalam kasus ini, penyimpanan memiliki efek samping menyebabkan kesalahan halaman, dan Anda ingin kompilator mempertahankan kesalahan halaman.

Dengan cara ini, kode di sekitarnya masih dapat dioptimalkan, dan kode Anda portabel ke kompiler lain yang tidak memahami GCC #pragma atau __attribute__sintaksis.

Dietrich Epp
sumber
2
Saya akan mengatakan ini lebih baik daripada mematikan pengoptimalan. Anda masih bisa mendapatkan keuntungan dari pengoptimalan lain menggunakan metode ini.
Ben S
3
Solusi Dietrich Epp tidak berfungsi di bawah kompiler ARM4.1 . Bahkan solusi ZelluX tidak berfungsi. Metode alternatif untuk membuat ini berfungsi untuk ARM4.1 ada dalam solusi ZelluX, buat ' temp ' sebagai variabel volatil global .
Oculus Dexter
1
Itu sangat buruk untuk kompiler tersebut.
Alexey Frunze
1
@Shocker: GCC masih dapat mengoptimalkan variabel tanpa mengoptimalkan akses memori yang sebenarnya. Itu adalah masalah yang berbeda.
Dietrich Epp
2
@jww: penggunaan ini sesuai dengan apa yang dijelaskan dalam posting blog itu. volatileartinya akses memori harus terjadi seperti yang tertulis, persis seperti yang kita inginkan. Dengan kata lain, kita telah memikirkannya dengan hati-hati, dan itu berarti apa yang kita pikirkan.
Dietrich Epp
184

Kamu bisa memakai

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

your code

#pragma GCC pop_options

untuk menonaktifkan pengoptimalan sejak GCC 4.4.

Lihat dokumentasi GCC jika Anda membutuhkan detail lebih lanjut.

Bajak
sumber
3
Namun perlu dicatat bahwa ini hanya berfungsi pada seluruh fungsi, bukan pada pernyataan khusus: gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/… "Setiap fungsi yang ditentukan setelah titik ini adalah seolah-olah atribut (( optimalkan ("STRING"))) telah ditentukan untuk fungsi itu. ".
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
134

Alih-alih menggunakan pragma baru, Anda juga bisa menggunakan __attribute__((optimize("O0")))untuk kebutuhan Anda. Ini memiliki keuntungan karena hanya diterapkan ke satu fungsi dan tidak semua fungsi ditentukan dalam file yang sama.

Contoh penggunaan:

void __attribute__((optimize("O0"))) foo(unsigned char data) {
    // unmodifiable compiler code
}
FRob
sumber
3
Bagaimana jika saya tidak menggunakan -Olevelopsi tetapi saya menggunakan opsi individu yang diaktifkan secara terpisah? (Dalam kasus saya, saya tidak dapat menentukan opsi pengoptimalan individual mana yang melanggar kode) .
pengguna2284570