W tym poście chciałbym opisać kilka rodzajów flag kompilatora GCC oraz parametry optymalizacji kodu.
[Źródło: https://pl.wikipedia.org/wiki/GNU_Compiler_Collection]
Do testów można użyć program Compiler Explorer, gdzie w czasie rzeczywistym można podglądnąć zarówno wykonanie program jak i flagi kompilacji czy kod assemblera.
Poniżej opis niektórych flag wraz z przykładami zastosowania.
-Wall
Uruchomienie podstawowych flag generowania ostrzeżeń.
Wywołanie tej flagi uruchamia następujący zestaw flag:
- -Waddress
- -Warray-bounds=1 (only with -O2)
- -Warray-parameter=2 (C and Objective-C only)
- -Wbool-compare
- -Wbool-operation
- -Wc++11-compat -Wc++14-compat
- -Wcatch-value (C++ and Objective-C++ only)
- -Wchar-subscripts
- -Wcomment
- -Wduplicate-decl-specifier (C and Objective-C only)
- -Wenum-compare (in C/ObjC; this is on by default in C++)
- -Wformat
- -Wformat-overflow
- -Wformat-truncation
- -Wint-in-bool-context
- -Wimplicit (C and Objective-C only)
- -Wimplicit-int (C and Objective-C only)
- -Wimplicit-function-declaration (C and Objective-C only)
- -Winit-self (only for C++)
- -Wlogical-not-parentheses
- -Wmain (only for C/ObjC and unless -ffreestanding)
- -Wmaybe-uninitialized
- -Wmemset-elt-size
- -Wmemset-transposed-args
- -Wmisleading-indentation (only for C/C++)
- -Wmissing-attributes
- -Wmissing-braces (only for C/ObjC)
- -Wmultistatement-macros
- -Wnarrowing (only for C++)
- -Wnonnull
- -Wnonnull-compare
- -Wopenmp-simd
- -Wparentheses
- -Wpessimizing-move (only for C++)
- -Wpointer-sign
- -Wrange-loop-construct (only for C++)
- -Wreorder
- -Wrestrict
- -Wreturn-type
- -Wsequence-point
- -Wsign-compare (only in C++)
- -Wsizeof-array-div
- -Wsizeof-pointer-div
- -Wsizeof-pointer-memaccess
- -Wstrict-aliasing
- -Wstrict-overflow=1
- -Wswitch
- -Wtautological-compare
- -Wtrigraphs
- -Wuninitialized
- -Wunknown-pragmas
- -Wunused-function
- -Wunused-label
- -Wunused-value
- -Wunused-variable
- -Wvla-parameter (C and Objective-C only)
- -Wvolatile-register-var
- -Wzero-length-bounds
-Wextra
Uruchamia dodatkowe flagi ostrzeżeń.
Wykaz uruchamianych flag:
- -Wclobbered
- -Wcast-function-type
- -Wdeprecated-copy (C++ only)
- -Wempty-body
- -Wenum-conversion (C only)
- -Wignored-qualifiers
- -Wimplicit-fallthrough=3
- -Wmissing-field-initializers
- -Wmissing-parameter-type (C only)
- -Wold-style-declaration (C only)
- -Woverride-init
- -Wsign-compare (C only)
- -Wstring-compare
- -Wredundant-move (only for C++)
- -Wtype-limits
- -Wuninitialized
- -Wshift-negative-value (in C++03 and in C99 and newer)
- -Wunused-parameter (only with -Wunused or -Wall)
- -Wunused-but-set-parameter (only with -Wunused or -Wall)
-Werror
Flaga pozwala na zmianę wszystkich ostrzeżeń w błędy.
-Wfatal-errors
Zatrzymanie kompilacji na pierwszym napotkanym błędzie.
-Wshadow
Flaga nie została uwzględniona w -Wall ani w -Wextra. Kompilator wygeneruje ostrzeżenie o przysłonięciu zmiennej przez inną zmienną, która ma taką samą nazwę.
-Wdouble-promotion
Flaga nie została uwzględniona w -Wall ani w -Wextra.. Wygenerowanie ostrzeżenia gdy następuje promocja typu z float na double.
Jest to szczególne istotne w przypadku jednostek posiadających FPU. W przypadku promocji typu na double, obsługa typu nie jest już sprzętowa tylko programowa.
-Wundef
Wyświetlenie ostrzeżenie o występującej niezdefiniowanej wartości w deklaracji #if. Taka wartość zostanie zastąpiona przez wartość 0.
To ostrzeżenie pozwala na wyłapanie błędnie zdefiniowanej wartości w dyrektywie #if lub braku widoczności tej wartości w wykonywanym pliku.
-Wunused
Flaga uruchamia generowanie ostrzeżeń gdy w kodzie znajdują się elementy które nie są używane.
Jest ona uruchamiana automatycznie po wprowadzeniu flagi -Wall.
- -Wunused-function
- -Wunused-label
- -Wunused-value
- -Wunused-variable
oraz dla flagi -Wextra
- -Wunused-parameter (only with -Wunused or -Wall)
- -Wunused-but-set-parameter (only with -Wunused or -Wall)
-fno-common
Flaga pozwala na znalezienie dodatkowej definicji zmiennej globalnej, do której nie została przypisana wartość.
Poniżej krótki przykład. Jeśli zapiszemy część programu w następujący sposób:
- uint8_t val1 = 4;
- uint8_t val1;
- void setValue(uint8_t startValue) {
- val1 = startValue;
- }
- int incrementValue(void) {
- val1++;
- }
- int decrementValue(void) {
- val1--;
- }
Program nie wygeneruje błędu i będzie można całość skompilować poprawnie. Oczywiście poważniejsze problemy pojawią się w przypadku wykorzystywania tych wartości do różnych operacji, gdzie nazwy mogą się dublować.
Kompilator nie zgłasza błędu ponieważ wartość nie została zainicjalizowana, a przez to pamięć dla niej nie została przydzielona.
Błąd podczas kompilacji nastąpi dopiero jak do drugiej zmiennej zostanie przydzielona wartość, lub gdy zmienne będą różnego typu.
-g, -g3
Wyświetlanie dodatkowych informacji podczas debugowania aplikacji.
-O0
Większość funkcji optymalizacyjnych została wyłączona. Jest to podstawowe ustawienie dla GCC.
-O1
Pozwala na wykonanie optymalizacji zarówno pod względem zmniejszenia czasu wykonywania jak i rozmiaru kodu
Można to bardzo łatwo zaobserwować na przykładzie redukcji ilości wykonywanych instrukcji assemblera np. za pomocą Compiler Explorer.
-O2
Zwiększenie optymalizacji pod względem szybkości wykonywania programu. Mniejsze rozwinięcie w stronę wielkości kodu.
-O3
Najwyższy poziom optymalizacji.
-Os
Optymalizacji pod względem wielkości kodu. Uruchamia ona wszystkie flagi dla -O2 oraz kilka dodatkowych flag. Wyjątkiem są flagi, które powodują zwiększenia rozmiaru kodu.
- -falign-functions
- -falign-jumps
- -falign-labels
- -falign-loops
- -fprefetch-loop-arrays
- -freorder-blocks-algorithm=stc
- -finline-functions
Zapewnia dosyć dobrą równowagę pomiędzy wielkością kodu a jego rozmiarem. Z tego powodu powinna być wykorzystywana w systemach wbudowanych.
-Ofast
Uruchamianie wszystkich flag dla -O3 oraz kilku dodatkowych flag.
-Og
Optymalizacja skierowana pod debugowanie oprogramowania. Zapewnia dobrze dobraną szybkość kompilacji do możliwości testowania programu.
Bibliografia:
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html