Hãy giải thích mã nguồn của GCC 5.1 để xem điều gì xảy ra -O100vì nó không rõ ràng trên trang người dùng.
Chúng tôi sẽ kết luận rằng:
- bất cứ thứ gì ở trên
-O3cho đến INT_MAXđều giống như -O3, nhưng điều đó có thể dễ dàng thay đổi trong tương lai, vì vậy đừng dựa vào nó.
- GCC 5.1 chạy hành vi không xác định nếu bạn nhập các số nguyên lớn hơn
INT_MAX.
- đối số chỉ có thể có các chữ số hoặc nó không thành công. Đặc biệt, điều này loại trừ các số nguyên âm như
-O-1
Tập trung vào các chương trình con
Đầu tiên hãy nhớ rằng GCC chỉ là một front-end cho cpp, as, cc1, collect2. Nhanh ./XXX --helpnói rằng chỉ collect2và cc1lấy -O, vì vậy hãy tập trung vào chúng.
Và:
gcc -v -O100 main.c |& grep 100
cho:
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.
vì vậy -Ođã được chuyển tiếp cho cả hai cc1và collect2.
O chung .opt
common.opt là một định dạng mô tả tùy chọn CLI GCC cụ thể được mô tả trong tài liệu hướng dẫn internals và dịch sang C bằng opth-gen.awk và optc-gen.awk .
Nó chứa những dòng thú vị sau:
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
trong đó chỉ định tất cả các Otùy chọn. Lưu ý như thế nào -O<n>là trong một họ riêng biệt với họ khác Os, Ofastvà Og.
Khi chúng tôi xây dựng, điều này sẽ tạo ra một options.htệp chứa:
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
Như một phần thưởng, trong khi chúng tôi đang tìm kiếm \bO\nbên trong, common.optchúng tôi nhận thấy các dòng:
-optimize
Common Alias(O)
điều này dạy chúng ta rằng --optimize(dấu gạch ngang kép vì nó bắt đầu bằng dấu gạch ngang -optimizetrên .opttệp) là một bí danh không có giấy tờ -Ocó thể được sử dụng làm --optimize=3!
OPT_O được sử dụng ở đâu
Bây giờ chúng tôi grep:
git grep -E '\bOPT_O\b'
dẫn chúng ta đến hai tệp:
Đầu tiên chúng ta hãy theo dõi opts.c
opts.c: default_options_optimization
Tất cả các opts.ctập quán xảy ra bên trong: default_options_optimization.
Chúng tôi grep backtrack để xem ai gọi hàm này và chúng tôi thấy rằng đường dẫn mã duy nhất là:
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
và main.clà điểm vào của cc1. Tốt!
Phần đầu tiên của chức năng này:
- Liệu
integral_argumenttrong đó kêu gọi atoitrên chuỗi tương ứng với OPT_Ophân tích lập luận đầu vào
- lưu trữ giá trị bên trong
opts->x_optimizeở đâu optsa struct gcc_opts.
struct gcc_opts
Sau khi nạp vô ích, chúng tôi nhận thấy rằng điều này structcũng được tạo ra tại options.h:
struct gcc_options {
int x_optimize;
[...]
}
từ đâu x_optimizeđến từ các dòng:
Variable
int optimize
hiện tại common.opt, và rằng options.c:
struct gcc_options global_options;
vì vậy chúng tôi đoán rằng đây là thứ chứa toàn bộ trạng thái chung của cấu hình và int x_optimizelà giá trị tối ưu hóa.
255 là mức tối đa nội bộ
in opts.c:integral_argument, atoiđược áp dụng cho đối số đầu vào, INT_MAXgiới hạn trên cũng vậy. Và nếu bạn đặt bất cứ thứ gì lớn hơn, có vẻ như GCC chạy C hành vi không xác định. Ầm ĩ?
integral_argumentcũng kết thúc mỏng atoivà bác bỏ đối số nếu bất kỳ ký tự nào không phải là chữ số. Vì vậy, các giá trị âm không thành công một cách duyên dáng.
Quay lại opts.c:default_options_optimization, chúng ta thấy dòng:
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
để mức độ tối ưu hóa được cắt bớt 255. Trong khi đọc, opth-gen.awktôi đã bắt gặp:
# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.
và trên được tạo options.h:
struct GTY(()) cl_optimization
{
unsigned char x_optimize;
điều này giải thích lý do tại sao cắt bớt: các tùy chọn cũng phải được chuyển tiếp tới cl_optimization, sử dụng a charđể tiết kiệm dung lượng. Vì vậy, 255 là một tối đa nội bộ thực sự.
opts.c: could_default_options
Quay lại opts.c:default_options_optimization, chúng ta bắt gặp maybe_default_optionscái nào nghe có vẻ thú vị. Chúng tôi nhập nó, và sau đó maybe_default_optionchúng tôi đạt được một công tắc lớn:
switch (default_opt->levels)
{
[...]
case OPT_LEVELS_1_PLUS:
enabled = (level >= 1);
break;
[...]
case OPT_LEVELS_3_PLUS:
enabled = (level >= 3);
break;
Không có >= 4séc nào , cho thấy đó 3là số lớn nhất có thể.
Sau đó, chúng tôi tìm kiếm định nghĩa của OPT_LEVELS_3_PLUStrong 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! Đây là một chỉ báo mạnh rằng chỉ có 3 cấp độ.
opts.c: default_options_table
opt_levelsrất thú vị, đến mức chúng tôi thu thập OPT_LEVELS_3_PLUSvà bắt gặp 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 },
[...]
}
vì vậy đây là nơi mà -Onánh xạ tối ưu hóa cụ thể được đề cập trong tài liệu được mã hóa. Đẹp!
Đảm bảo rằng không còn cách sử dụng x_optimize nữa
Cách sử dụng chính của x_optimizelà để đặt các tùy chọn tối ưu hóa cụ thể khác -fdefer_popnhư được ghi lại trên trang chủ. Còn nữa không?
Chúng tôi grep, và tìm thấy một số khác. Số lượng nhỏ, và khi kiểm tra thủ công, chúng tôi thấy rằng mọi cách sử dụng chỉ thực hiện nhiều nhất là a x_optimize >= 3, vì vậy kết luận của chúng tôi là đúng.
lto-wrapper.c
Bây giờ chúng ta đi đến sự xuất hiện thứ hai của OPT_O, đã ở lto-wrapper.c.
LTO có nghĩa là Tối ưu hóa thời gian liên kết, như tên cho thấy sẽ cần một -Otùy chọn và sẽ được liên kết với collec2(về cơ bản là một trình liên kết).
Trên thực tế, dòng đầu tiên lto-wrapper.cnói:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
Trong tệp này, các OPT_Olần xuất hiện dường như chỉ chuẩn hóa giá trị của Ođể chuyển nó về phía trước, vì vậy chúng ta sẽ ổn.
man gccCygwin (12000 dòng lẻ), bạn có thể tìm kiếm-Ovà tìm thấy mọi thứ câu trả lời ở trạng thái bên dưới, và sau đó là một số.