Mari kita tafsirkan kode sumber GCC 5.1 untuk melihat apa yang terjadi -O100karena tidak jelas pada halaman manual.
Kami akan menyimpulkan bahwa:
- apa pun di
-O3atas INT_MAXsama dengan -O3, tetapi itu dapat dengan mudah berubah di masa depan, jadi jangan mengandalkannya.
- GCC 5.1 menjalankan perilaku tidak ditentukan jika Anda memasukkan bilangan bulat yang lebih besar dari
INT_MAX.
- argumen hanya dapat terdiri dari angka, atau gagal dengan baik. Secara khusus, ini mengecualikan bilangan bulat negatif seperti
-O-1
Fokus pada subprogram
Pertama ingat bahwa GCC hanya sebuah front-end untuk cpp, as, cc1, collect2. A quick ./XXX --helpmengatakan itu saja collect2dan cc1mengambil -O, jadi mari kita fokus pada mereka.
Dan:
gcc -v -O100 main.c |& grep 100
memberikan:
COLLECT_GCC_OPTIONS='-O100' '-v' '-mtune=generic' '-march=x86-64'
/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1 [[noise]] hello_world.c -O100 -o /tmp/ccetECB5.
jadi -Oditeruskan ke keduanya cc1dan collect2.
O yang sama. Opt
common.opt adalah format deskripsi opsi CLI khusus GCC yang dijelaskan dalam dokumentasi internal dan diterjemahkan ke C oleh opth-gen.awk dan optc-gen.awk .
Ini berisi baris menarik berikut:
O
Common JoinedOrMissing Optimization
-O<number> Set optimization level to <number>
Os
Common Optimization
Optimize for space rather than speed
Ofast
Common Optimization
Optimize for speed disregarding exact standards compliance
Og
Common Optimization
Optimize for debugging experience rather than speed or size
yang menentukan semua Oopsi. Perhatikan bagaimana -O<n>berada dalam satu keluarga terpisah dari yang lain Os, Ofastdan Og.
Saat kami membangun, ini menghasilkan options.hfile yang berisi:
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
Sebagai bonus, saat kita menggapai \bO\nbagian dalam common.optkita memperhatikan garis:
-optimize
Common Alias(O)
yang mengajarkan kita bahwa --optimize(tanda hubung ganda karena dimulai dengan tanda hubung -optimizepada .optfile) adalah alias tidak berdokumen -Oyang dapat digunakan sebagai --optimize=3!
Dimana OPT_O digunakan
Sekarang kita grep:
git grep -E '\bOPT_O\b'
yang mengarahkan kita ke dua file:
Mari kita telusuri dulu opts.c
opts.c: default_options_optimization
Semua opts.cpenggunaan terjadi di dalam: default_options_optimization.
Kami grep mundur untuk melihat siapa yang memanggil fungsi ini, dan kami melihat bahwa satu-satunya jalur kode adalah:
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
dan main.cmerupakan titik masuk dari cc1. Baik!
Bagian pertama dari fungsi ini:
- apakah
integral_argumentyang memanggil atoistring yang sesuai OPT_Ountuk mengurai argumen input
- menyimpan nilai di dalam di
opts->x_optimizemana optsa struct gcc_opts.
struct gcc_opts
Setelah melakukan grep dengan sia-sia, kami melihat bahwa ini structjuga dihasilkan di options.h:
struct gcc_options {
int x_optimize;
[...]
}
dari mana x_optimizeberasal dari garis:
Variable
int optimize
hadir di common.opt, dan bahwa options.c:
struct gcc_options global_options;
jadi kami menebak bahwa inilah yang berisi seluruh konfigurasi status global, dan int x_optimizemerupakan nilai pengoptimalan.
255 adalah maksimum internal
in opts.c:integral_argument, atoiditerapkan ke argumen input, begitu INT_MAXjuga batas atasnya. Dan jika Anda meletakkan sesuatu yang lebih besar, tampaknya GCC menjalankan perilaku C tidak terdefinisi. Aduh?
integral_argumentjuga dengan tipis membungkus atoidan menolak argumen jika ada karakter yang bukan digit. Jadi nilai-nilai negatif gagal dengan baik.
Kembali ke opts.c:default_options_optimization, kita melihat baris:
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
sehingga tingkat pengoptimalan dipotong menjadi 255. Saat membaca opth-gen.awksaya menemukan:
# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.
dan di hasilkan options.h:
struct GTY(()) cl_optimization
{
unsigned char x_optimize;
yang menjelaskan mengapa pemotongan: opsi juga harus diteruskan cl_optimization, yang menggunakan a charuntuk menghemat ruang. Jadi 255 sebenarnya adalah maksimum internal.
opts.c: maybe_default_options
Kembali ke opts.c:default_options_optimization, kami menemukan maybe_default_optionsyang terdengar menarik. Kami memasukinya, dan kemudian di maybe_default_optionmana kami mencapai sakelar besar:
switch (default_opt->levels)
{
[...]
case OPT_LEVELS_1_PLUS:
enabled = (level >= 1);
break;
[...]
case OPT_LEVELS_3_PLUS:
enabled = (level >= 3);
break;
Tidak ada >= 4pemeriksaan, yang menunjukkan bahwa 3kemungkinan terbesar.
Lalu kita cari definisi OPT_LEVELS_3_PLUSin common-target.h:
enum opt_levels
{
OPT_LEVELS_NONE, /* No levels (mark end of array). */
OPT_LEVELS_ALL, /* All levels (used by targets to disable options
enabled in target-independent code). */
OPT_LEVELS_0_ONLY, /* -O0 only. */
OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og. */
OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og. */
OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og. */
OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */
OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og. */
OPT_LEVELS_3_PLUS, /* -O3 and above. */
OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */
OPT_LEVELS_SIZE, /* -Os only. */
OPT_LEVELS_FAST /* -Ofast only. */
};
Ha! Ini adalah indikator kuat bahwa hanya ada 3 level.
opts.c: default_options_table
opt_levelssangat menarik, sehingga kami grep OPT_LEVELS_3_PLUS, dan menemukan opts.c:default_options_table:
static const struct default_options default_options_table[] = {
/* -O1 optimizations. */
{ OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
[...]
/* -O3 optimizations. */
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
[...]
}
jadi di sinilah -Onpemetaan pengoptimalan khusus yang disebutkan dalam dokumen dikodekan. Bagus!
Pastikan tidak ada lagi kegunaan x_optimize
Penggunaan utama dari x_optimizeadalah untuk mengatur opsi pengoptimalan spesifik lainnya seperti yang -fdefer_popdidokumentasikan di halaman manual. Apakah masih ada lagi
Kami grep, dan temukan beberapa lagi. Jumlahnya kecil, dan setelah pemeriksaan manual kami melihat bahwa setiap penggunaan hanya melakukan paling banyak a x_optimize >= 3, jadi kesimpulan kami berlaku.
lto-wrapper.c
Sekarang kita pergi ke kejadian kedua OPT_O, yaitu masuk lto-wrapper.c.
LTO berarti Pengoptimalan Waktu Tautan, yang seperti namanya akan membutuhkan -Oopsi, dan akan ditautkan collec2(yang pada dasarnya adalah penaut).
Faktanya, baris pertama lto-wrapper.cmengatakan:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
Dalam file ini, OPT_Okejadian tampaknya hanya menormalkan nilai Ountuk meneruskannya, jadi kita akan baik-baik saja.
man gccdi Cygwin (12000 baris ganjil) Anda dapat mencari-Odan menemukan semua jawaban di bawah status, dan kemudian beberapa.