Mari kita tafsirkan kode sumber GCC 5.1 untuk melihat apa yang terjadi -O100
karena tidak jelas pada halaman manual.
Kami akan menyimpulkan bahwa:
- apa pun di
-O3
atas INT_MAX
sama 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 --help
mengatakan itu saja collect2
dan cc1
mengambil -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 -O
diteruskan ke keduanya cc1
dan 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 O
opsi. Perhatikan bagaimana -O<n>
berada dalam satu keluarga terpisah dari yang lain Os
, Ofast
dan Og
.
Saat kami membangun, ini menghasilkan options.h
file yang berisi:
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
Sebagai bonus, saat kita menggapai \bO\n
bagian dalam common.opt
kita memperhatikan garis:
-optimize
Common Alias(O)
yang mengajarkan kita bahwa --optimize
(tanda hubung ganda karena dimulai dengan tanda hubung -optimize
pada .opt
file) adalah alias tidak berdokumen -O
yang 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.c
penggunaan 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.c
merupakan titik masuk dari cc1
. Baik!
Bagian pertama dari fungsi ini:
- apakah
integral_argument
yang memanggil atoi
string yang sesuai OPT_O
untuk mengurai argumen input
- menyimpan nilai di dalam di
opts->x_optimize
mana opts
a struct gcc_opts
.
struct gcc_opts
Setelah melakukan grep dengan sia-sia, kami melihat bahwa ini struct
juga dihasilkan di options.h
:
struct gcc_options {
int x_optimize;
[...]
}
dari mana x_optimize
berasal 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_optimize
merupakan nilai pengoptimalan.
255 adalah maksimum internal
in opts.c:integral_argument
, atoi
diterapkan ke argumen input, begitu INT_MAX
juga batas atasnya. Dan jika Anda meletakkan sesuatu yang lebih besar, tampaknya GCC menjalankan perilaku C tidak terdefinisi. Aduh?
integral_argument
juga dengan tipis membungkus atoi
dan 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.awk
saya 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 char
untuk menghemat ruang. Jadi 255 sebenarnya adalah maksimum internal.
opts.c: maybe_default_options
Kembali ke opts.c:default_options_optimization
, kami menemukan maybe_default_options
yang terdengar menarik. Kami memasukinya, dan kemudian di maybe_default_option
mana 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 >= 4
pemeriksaan, yang menunjukkan bahwa 3
kemungkinan terbesar.
Lalu kita cari definisi OPT_LEVELS_3_PLUS
in 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_levels
sangat 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 -On
pemetaan pengoptimalan khusus yang disebutkan dalam dokumen dikodekan. Bagus!
Pastikan tidak ada lagi kegunaan x_optimize
Penggunaan utama dari x_optimize
adalah untuk mengatur opsi pengoptimalan spesifik lainnya seperti yang -fdefer_pop
didokumentasikan 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 -O
opsi, dan akan ditautkan collec2
(yang pada dasarnya adalah penaut).
Faktanya, baris pertama lto-wrapper.c
mengatakan:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
Dalam file ini, OPT_O
kejadian tampaknya hanya menormalkan nilai O
untuk meneruskannya, jadi kita akan baik-baik saja.
man gcc
di Cygwin (12000 baris ganjil) Anda dapat mencari-O
dan menemukan semua jawaban di bawah status, dan kemudian beberapa.